JitArm64: Add the ability to emit an unconditional exception exit

In cases where we already know that there is an exception,
either because we just checked for it or because we were
the ones that generated the exception to begin with,
we can skip the branch inside WriteExceptionExit.
This commit is contained in:
JosJuice 2021-07-03 12:47:09 +02:00
parent ffdc8538a1
commit 1a64364ae3
4 changed files with 21 additions and 36 deletions

View File

@ -207,7 +207,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);
WriteExceptionExit(js.compilerPC);
WriteExceptionExit(js.compilerPC, false, true);
SwitchToNearCode();
SetJumpTarget(noException);
@ -454,43 +454,25 @@ void JitArm64::WriteBLRExit(Arm64Gen::ARM64Reg dest)
B(dispatcher);
}
void JitArm64::WriteExceptionExit(u32 destination, bool only_external)
void JitArm64::WriteExceptionExit(u32 destination, bool only_external, bool always_exception)
{
Cleanup();
LDR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(Exceptions));
MOVI2R(DISPATCHER_PC, destination);
FixupBranch no_exceptions = CBZ(ARM64Reg::W30);
static_assert(PPCSTATE_OFF(pc) <= 252);
static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc));
STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
if (only_external)
MOVP2R(ARM64Reg::X8, &PowerPC::CheckExternalExceptions);
else
MOVP2R(ARM64Reg::X8, &PowerPC::CheckExceptions);
BLR(ARM64Reg::X8);
LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
SetJumpTarget(no_exceptions);
EndTimeProfile(js.curBlock);
DoDownCount();
B(dispatcher);
WriteExceptionExit(DISPATCHER_PC, only_external, always_exception);
}
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always_exception)
{
if (dest != DISPATCHER_PC)
MOV(DISPATCHER_PC, dest);
Cleanup();
LDR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(Exceptions));
FixupBranch no_exceptions = CBZ(ARM64Reg::W30);
FixupBranch no_exceptions;
if (!always_exception)
{
LDR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(Exceptions));
no_exceptions = CBZ(ARM64Reg::W30);
}
static_assert(PPCSTATE_OFF(pc) <= 252);
static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc));
@ -504,7 +486,8 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
SetJumpTarget(no_exceptions);
if (!always_exception)
SetJumpTarget(no_exceptions);
EndTimeProfile(js.curBlock);
DoDownCount();
@ -757,7 +740,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);
WriteExceptionExit(js.compilerPC, true);
WriteExceptionExit(js.compilerPC, true, true);
SwitchToNearCode();
SetJumpTarget(exit);
gpr.Unlock(ARM64Reg::W30);
@ -789,7 +772,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
gpr.Flush(FlushMode::MaintainState);
fpr.Flush(FlushMode::MaintainState);
WriteExceptionExit(js.compilerPC, true);
WriteExceptionExit(js.compilerPC, true, true);
SwitchToNearCode();
SetJumpTarget(NoExtException);
SetJumpTarget(exit);
@ -820,7 +803,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
gpr.Unlock(WA);
WriteExceptionExit(js.compilerPC);
WriteExceptionExit(js.compilerPC, false, true);
SwitchToNearCode();

View File

@ -250,8 +250,10 @@ protected:
// Exits
void WriteExit(u32 destination, bool LK = false, u32 exit_address_after_return = 0);
void WriteExit(Arm64Gen::ARM64Reg dest, bool LK = false, u32 exit_address_after_return = 0);
void WriteExceptionExit(u32 destination, bool only_external = false);
void WriteExceptionExit(Arm64Gen::ARM64Reg dest, bool only_external = false);
void WriteExceptionExit(u32 destination, bool only_external = false,
bool always_exception = false);
void WriteExceptionExit(Arm64Gen::ARM64Reg dest, bool only_external = false,
bool always_exception = false);
void FakeLKExit(u32 exit_address_after_return);
void WriteBLRExit(Arm64Gen::ARM64Reg dest);

View File

@ -29,7 +29,7 @@ void JitArm64::sc(UGeckoInstruction inst)
gpr.Unlock(WA);
WriteExceptionExit(js.compilerPC + 4);
WriteExceptionExit(js.compilerPC + 4, false, true);
}
void JitArm64::rfi(UGeckoInstruction inst)

View File

@ -221,7 +221,7 @@ void JitArm64::twx(UGeckoInstruction inst)
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
gpr.Unlock(WA);
WriteExceptionExit(js.compilerPC);
WriteExceptionExit(js.compilerPC, false, true);
SwitchToNearCode();