From 1a64364ae367ff19ff1159f71f0fa5c72b1f674b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 3 Jul 2021 12:47:09 +0200 Subject: [PATCH] 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. --- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 47 ++++++------------- Source/Core/Core/PowerPC/JitArm64/Jit.h | 6 ++- .../Core/PowerPC/JitArm64/JitArm64_Branch.cpp | 2 +- .../JitArm64/JitArm64_SystemRegisters.cpp | 2 +- 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index a7a2388660..9186db3744 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -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(); diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index d1d373ac9a..a9c0785e72 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -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); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp index bad0e482a7..962fd79a10 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp @@ -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) diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index b1334d42f0..81e007177f 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -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();