Skip to content

Commit

Permalink
CPUBackend: Make guest RIP reconstruction offsets signed
Browse files Browse the repository at this point in the history
With multiblock enabled, host code generated from guest code with a
lower address may be placed after host code generated from guest code
with a higher address in a multiblock. As each guest RIP reconstruction
entry is always relative to the one before it the offset needs to be
signed to allow this.
  • Loading branch information
bylaws committed Jan 14, 2025
1 parent 8cfc016 commit 06ea691
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 1 deletion.
2 changes: 1 addition & 1 deletion FEXCore/Source/Interface/Core/CPUBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ namespace CPU {
uint16_t HostPCOffset;

// How much to offset the RIP from the previous entry.
uint16_t GuestRIPOffset;
int16_t GuestRIPOffset;
};

/**
Expand Down
8 changes: 8 additions & 0 deletions FEXCore/Source/Interface/Core/JIT/JIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ desc: Main glue logic of the arm64 splatter backend
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <limits>

static constexpr size_t INITIAL_CODE_SIZE = 1024 * 1024 * 16;
// We don't want to move above 128MB atm because that means we will have to encode longer jumps
Expand Down Expand Up @@ -875,6 +876,13 @@ CPUBackend::CompiledCode Arm64JITCore::CompileCode(uint64_t Entry, uint64_t Size
for (size_t i = 0; i < DebugData->GuestOpcodes.size(); i++) {
const auto& GuestOpcode = DebugData->GuestOpcodes[i];
auto& RIPEntry = JITRIPEntries[i];
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
uint64_t HostPCOffset = GuestOpcode.HostEntryOffset - CurrentPCOffset;
int64_t GuestRIPOffset = GuestOpcode.GuestEntryOffset - CurrentRIPOffset;
LOGMAN_THROW_AA_FMT(HostPCOffset <= std::numeric_limits<uint16_t>::max() , "PC offset too large");
LOGMAN_THROW_AA_FMT(GuestRIPOffset >= std::numeric_limits<int16_t>::min() , "RIP offset too small");
LOGMAN_THROW_AA_FMT(GuestRIPOffset <= std::numeric_limits<int16_t>::max() , "RIP offset too large");
#endif
RIPEntry.HostPCOffset = GuestOpcode.HostEntryOffset - CurrentPCOffset;
RIPEntry.GuestRIPOffset = GuestOpcode.GuestEntryOffset - CurrentRIPOffset;
CurrentPCOffset = GuestOpcode.HostEntryOffset;
Expand Down

0 comments on commit 06ea691

Please sign in to comment.