Skip to content

Commit

Permalink
JitArm64: Use farcode in WriteLinkBlock
Browse files Browse the repository at this point in the history
Now block link nearcode is back to a length of three instructions.

Unfortunately, the code I'm adding to Jit.cpp ends up being a bit messy
because we need to handle the case of already being in farcode...
  • Loading branch information
JosJuice committed Jul 30, 2023
1 parent 1813f0f commit d2c5d79
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 10 deletions.
75 changes: 75 additions & 0 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Expand Up @@ -372,12 +372,29 @@ void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return
STP(IndexType::Pre, ARM64Reg::X0, ARM64Reg::X1, ARM64Reg::SP, -16);
}

constexpr size_t primary_farcode_size = 3 * sizeof(u32);
const bool switch_to_far_code = !IsInFarCode();
const u8* primary_farcode_addr;
if (switch_to_far_code)
{
SwitchToFarCode();
primary_farcode_addr = GetCodePtr();
SwitchToNearCode();
}
else
{
primary_farcode_addr = GetCodePtr() + JitArm64BlockCache::BLOCK_LINK_SIZE +
(LK ? JitArm64BlockCache::BLOCK_LINK_SIZE : 0);
}
const u8* return_farcode_addr = primary_farcode_addr + primary_farcode_size;

JitBlock* b = js.curBlock;
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
linkData.call = LK;
linkData.exitFarcode = primary_farcode_addr;
b->linkData.push_back(linkData);

blocks.WriteLinkBlock(*this, linkData);
Expand All @@ -391,10 +408,32 @@ void JitArm64::WriteExit(u32 destination, bool LK, u32 exit_address_after_return
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
linkData.call = false;
linkData.exitFarcode = return_farcode_addr;
b->linkData.push_back(linkData);

blocks.WriteLinkBlock(*this, linkData);
}

if (switch_to_far_code)
SwitchToFarCode();
DEBUG_ASSERT(GetCodePtr() == primary_farcode_addr || HasWriteFailed());
MOVI2R(DISPATCHER_PC, destination);
if (LK)
BL(GetAsmRoutines()->do_timing);
else
B(GetAsmRoutines()->do_timing);

if (LK)
{
if (GetCodePtr() == return_farcode_addr - sizeof(u32))
BRK(101);
DEBUG_ASSERT(GetCodePtr() == return_farcode_addr || HasWriteFailed());
MOVI2R(DISPATCHER_PC, exit_address_after_return);
B(GetAsmRoutines()->do_timing);
}

if (switch_to_far_code)
SwitchToNearCode();
}

void JitArm64::WriteExit(Arm64Gen::ARM64Reg dest, bool LK, u32 exit_address_after_return)
Expand Down Expand Up @@ -431,9 +470,27 @@ void JitArm64::WriteExit(Arm64Gen::ARM64Reg dest, bool LK, u32 exit_address_afte
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
linkData.call = false;
const bool switch_to_far_code = !IsInFarCode();
if (switch_to_far_code)
{
SwitchToFarCode();
linkData.exitFarcode = GetCodePtr();
SwitchToNearCode();
}
else
{
linkData.exitFarcode = GetCodePtr() + JitArm64BlockCache::BLOCK_LINK_SIZE;
}
b->linkData.push_back(linkData);

blocks.WriteLinkBlock(*this, linkData);

if (switch_to_far_code)
SwitchToFarCode();
MOVI2R(DISPATCHER_PC, exit_address_after_return);
B(GetAsmRoutines()->do_timing);
if (switch_to_far_code)
SwitchToNearCode();
}
}

Expand Down Expand Up @@ -465,10 +522,28 @@ void JitArm64::FakeLKExit(u32 exit_address_after_return)
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
linkData.call = false;
const bool switch_to_far_code = !IsInFarCode();
if (switch_to_far_code)
{
SwitchToFarCode();
linkData.exitFarcode = GetCodePtr();
SwitchToNearCode();
}
else
{
linkData.exitFarcode = GetCodePtr() + JitArm64BlockCache::BLOCK_LINK_SIZE;
}
b->linkData.push_back(linkData);

blocks.WriteLinkBlock(*this, linkData);

if (switch_to_far_code)
SwitchToFarCode();
MOVI2R(DISPATCHER_PC, exit_address_after_return);
B(GetAsmRoutines()->do_timing);
if (switch_to_far_code)
SwitchToNearCode();

SetJumpTarget(skip_exit);
}

Expand Down
15 changes: 6 additions & 9 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp
Expand Up @@ -29,8 +29,9 @@ void JitArm64BlockCache::WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit,
emit.MOVI2R(DISPATCHER_PC, source.exitAddress);
if (source.call)
{
while (emit.GetCodePtr() < start + BLOCK_LINK_FAST_BL_OFFSET && !emit.HasWriteFailed())
if (emit.GetCodePtr() == start + BLOCK_LINK_FAST_BL_OFFSET - sizeof(u32))
emit.NOP();
DEBUG_ASSERT(emit.GetCodePtr() == start + BLOCK_LINK_FAST_BL_OFFSET || emit.HasWriteFailed());
emit.BL(m_jit.GetAsmRoutines()->dispatcher);
}
else
Expand All @@ -45,10 +46,8 @@ void JitArm64BlockCache::WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit,
// The "fast" BL should be the last instruction, so that the return address matches the
// address that was pushed onto the stack by the function that called WriteLinkBlock
FixupBranch fast = emit.B(CC_GT);
emit.MOVI2R(DISPATCHER_PC, source.exitAddress);
emit.BL(m_jit.GetAsmRoutines()->do_timing);
while (emit.GetCodePtr() < start + BLOCK_LINK_FAST_BL_OFFSET && !emit.HasWriteFailed())
emit.BRK(101);
emit.B(source.exitFarcode);
DEBUG_ASSERT(emit.GetCodePtr() == start + BLOCK_LINK_FAST_BL_OFFSET || emit.HasWriteFailed());
emit.SetJumpTarget(fast);
emit.BL(dest->normalEntry);
}
Expand All @@ -59,16 +58,14 @@ void JitArm64BlockCache::WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit,
if (block_distance >= -0x40000 && block_distance <= 0x3FFFF)
{
emit.B(CC_GT, dest->normalEntry);
emit.MOVI2R(DISPATCHER_PC, source.exitAddress);
emit.B(m_jit.GetAsmRoutines()->do_timing);
emit.B(source.exitFarcode);
}
else
{
FixupBranch slow = emit.B(CC_LE);
emit.B(dest->normalEntry);
emit.SetJumpTarget(slow);
emit.MOVI2R(DISPATCHER_PC, source.exitAddress);
emit.B(m_jit.GetAsmRoutines()->do_timing);
emit.B(source.exitFarcode);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.h
Expand Up @@ -29,7 +29,7 @@ class JitArm64BlockCache : public JitBaseBlockCache
void WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit, const JitBlock::LinkData& source,
const JitBlock* dest = nullptr);

static constexpr size_t BLOCK_LINK_SIZE = 5 * sizeof(u32);
static constexpr size_t BLOCK_LINK_SIZE = 3 * sizeof(u32);
static constexpr size_t BLOCK_LINK_FAST_BL_OFFSET = BLOCK_LINK_SIZE - sizeof(u32);

private:
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/Core/PowerPC/JitCommon/JitCache.h
Expand Up @@ -70,6 +70,9 @@ struct JitBlock : public JitBlockData
struct LinkData
{
u8* exitPtrs; // to be able to rewrite the exit jump
#ifdef _M_ARM_64
const u8* exitFarcode;
#endif
u32 exitAddress;
bool linkStatus; // is it already linked?
bool call;
Expand Down

0 comments on commit d2c5d79

Please sign in to comment.