diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 3a48ae7df4..83b35f4108 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -209,20 +209,16 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst) } } -void JitArm64::HLEFunction(UGeckoInstruction inst) +void JitArm64::HLEFunction(u32 hook_index) { + FlushCarry(); gpr.Flush(FlushMode::FLUSH_ALL); fpr.Flush(FlushMode::FLUSH_ALL); MOVI2R(W0, js.compilerPC); - MOVI2R(W1, inst.hex); + MOVI2R(W1, hook_index); MOVP2R(X30, &HLE::Execute); BLR(X30); - - ARM64Reg WA = gpr.GetReg(); - LDR(INDEX_UNSIGNED, WA, PPC_REG, PPCSTATE_OFF(npc)); - WriteExit(WA); - gpr.Unlock(WA); } void JitArm64::DoNothing(UGeckoInstruction inst) @@ -490,6 +486,21 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external) B(dispatcher); } +bool JitArm64::HandleFunctionHooking(u32 address) +{ + return HLE::ReplaceFunctionIfPossible(address, [&](u32 hook_index, HLE::HookType type) { + HLEFunction(hook_index); + + if (type != HLE::HookType::Replace) + return false; + + LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc)); + js.downcountAmount += js.st.numCycles; + WriteExit(DISPATCHER_PC); + return true; + }); +} + void JitArm64::DumpCode(const u8* start, const u8* end) { std::string output; @@ -748,6 +759,9 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) SetJumpTarget(exit); } + if (HandleFunctionHooking(op.address)) + break; + if (!op.skip) { if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index a9a982ded4..a654109496 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -46,7 +46,7 @@ public: // OPCODES void FallBackToInterpreter(UGeckoInstruction inst); void DoNothing(UGeckoInstruction inst); - void HLEFunction(UGeckoInstruction inst); + void HLEFunction(u32 hook_index); void DynaRunTable4(UGeckoInstruction inst); void DynaRunTable19(UGeckoInstruction inst); @@ -175,6 +175,8 @@ private: static void InitializeInstructionTables(); void CompileInstruction(PPCAnalyst::CodeOp& op); + bool HandleFunctionHooking(u32 address); + // Simple functions to switch between near and far code emitting void SwitchToFarCode() {