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:
parent
ffdc8538a1
commit
1a64364ae3
|
@ -207,7 +207,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
|
||||||
gpr.Flush(FlushMode::MaintainState);
|
gpr.Flush(FlushMode::MaintainState);
|
||||||
fpr.Flush(FlushMode::MaintainState);
|
fpr.Flush(FlushMode::MaintainState);
|
||||||
|
|
||||||
WriteExceptionExit(js.compilerPC);
|
WriteExceptionExit(js.compilerPC, false, true);
|
||||||
|
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
SetJumpTarget(noException);
|
SetJumpTarget(noException);
|
||||||
|
@ -454,43 +454,25 @@ void JitArm64::WriteBLRExit(Arm64Gen::ARM64Reg dest)
|
||||||
B(dispatcher);
|
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);
|
MOVI2R(DISPATCHER_PC, destination);
|
||||||
FixupBranch no_exceptions = CBZ(ARM64Reg::W30);
|
WriteExceptionExit(DISPATCHER_PC, only_external, always_exception);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external)
|
void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always_exception)
|
||||||
{
|
{
|
||||||
if (dest != DISPATCHER_PC)
|
if (dest != DISPATCHER_PC)
|
||||||
MOV(DISPATCHER_PC, dest);
|
MOV(DISPATCHER_PC, dest);
|
||||||
|
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|
||||||
LDR(IndexType::Unsigned, ARM64Reg::W30, PPC_REG, PPCSTATE_OFF(Exceptions));
|
FixupBranch no_exceptions;
|
||||||
FixupBranch no_exceptions = CBZ(ARM64Reg::W30);
|
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) <= 252);
|
||||||
static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc));
|
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));
|
LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
|
||||||
|
|
||||||
SetJumpTarget(no_exceptions);
|
if (!always_exception)
|
||||||
|
SetJumpTarget(no_exceptions);
|
||||||
|
|
||||||
EndTimeProfile(js.curBlock);
|
EndTimeProfile(js.curBlock);
|
||||||
DoDownCount();
|
DoDownCount();
|
||||||
|
@ -757,7 +740,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
|
|
||||||
gpr.Flush(FlushMode::MaintainState);
|
gpr.Flush(FlushMode::MaintainState);
|
||||||
fpr.Flush(FlushMode::MaintainState);
|
fpr.Flush(FlushMode::MaintainState);
|
||||||
WriteExceptionExit(js.compilerPC, true);
|
WriteExceptionExit(js.compilerPC, true, true);
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
SetJumpTarget(exit);
|
SetJumpTarget(exit);
|
||||||
gpr.Unlock(ARM64Reg::W30);
|
gpr.Unlock(ARM64Reg::W30);
|
||||||
|
@ -789,7 +772,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
|
|
||||||
gpr.Flush(FlushMode::MaintainState);
|
gpr.Flush(FlushMode::MaintainState);
|
||||||
fpr.Flush(FlushMode::MaintainState);
|
fpr.Flush(FlushMode::MaintainState);
|
||||||
WriteExceptionExit(js.compilerPC, true);
|
WriteExceptionExit(js.compilerPC, true, true);
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
SetJumpTarget(NoExtException);
|
SetJumpTarget(NoExtException);
|
||||||
SetJumpTarget(exit);
|
SetJumpTarget(exit);
|
||||||
|
@ -820,7 +803,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
|
|
||||||
gpr.Unlock(WA);
|
gpr.Unlock(WA);
|
||||||
|
|
||||||
WriteExceptionExit(js.compilerPC);
|
WriteExceptionExit(js.compilerPC, false, true);
|
||||||
|
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
|
|
||||||
|
|
|
@ -250,8 +250,10 @@ protected:
|
||||||
// Exits
|
// Exits
|
||||||
void WriteExit(u32 destination, bool LK = false, u32 exit_address_after_return = 0);
|
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 WriteExit(Arm64Gen::ARM64Reg dest, bool LK = false, u32 exit_address_after_return = 0);
|
||||||
void WriteExceptionExit(u32 destination, bool only_external = false);
|
void WriteExceptionExit(u32 destination, bool only_external = false,
|
||||||
void WriteExceptionExit(Arm64Gen::ARM64Reg dest, 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 FakeLKExit(u32 exit_address_after_return);
|
||||||
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
void WriteBLRExit(Arm64Gen::ARM64Reg dest);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ void JitArm64::sc(UGeckoInstruction inst)
|
||||||
|
|
||||||
gpr.Unlock(WA);
|
gpr.Unlock(WA);
|
||||||
|
|
||||||
WriteExceptionExit(js.compilerPC + 4);
|
WriteExceptionExit(js.compilerPC + 4, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitArm64::rfi(UGeckoInstruction inst)
|
void JitArm64::rfi(UGeckoInstruction inst)
|
||||||
|
|
|
@ -221,7 +221,7 @@ void JitArm64::twx(UGeckoInstruction inst)
|
||||||
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(Exceptions));
|
||||||
gpr.Unlock(WA);
|
gpr.Unlock(WA);
|
||||||
|
|
||||||
WriteExceptionExit(js.compilerPC);
|
WriteExceptionExit(js.compilerPC, false, true);
|
||||||
|
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue