diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index 98534ed903..0960b77fb7 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -98,11 +98,37 @@ s32 CachedInterpreter::EndBlock(PowerPC::PowerPCState& ppc_state, const EndBlock return 0; } +template s32 CachedInterpreter::Interpret(PowerPC::PowerPCState& ppc_state, const InterpretOperands& operands) { - const auto& [interpreter, func, current_pc, inst] = operands; - func(interpreter, inst); + if constexpr (write_pc) + { + ppc_state.pc = operands.current_pc; + ppc_state.npc = operands.current_pc + 4; + } + operands.func(operands.interpreter, operands.inst); + return sizeof(AnyCallback) + sizeof(operands); +} + +template +s32 CachedInterpreter::InterpretAndCheckExceptions( + PowerPC::PowerPCState& ppc_state, const InterpretAndCheckExceptionsOperands& operands) +{ + if constexpr (write_pc) + { + ppc_state.pc = operands.current_pc; + ppc_state.npc = operands.current_pc + 4; + } + operands.func(operands.interpreter, operands.inst); + + if ((ppc_state.Exceptions & (EXCEPTION_DSI | EXCEPTION_PROGRAM)) != 0) + { + ppc_state.pc = operands.current_pc; + ppc_state.downcount -= operands.downcount; + operands.power_pc.CheckExceptions(); + return 0; + } return sizeof(AnyCallback) + sizeof(operands); } @@ -115,16 +141,8 @@ s32 CachedInterpreter::HLEFunction(PowerPC::PowerPCState& ppc_state, return sizeof(AnyCallback) + sizeof(operands); } -s32 CachedInterpreter::WritePC(PowerPC::PowerPCState& ppc_state, const WritePCOperands& operands) -{ - const auto& [current_pc] = operands; - ppc_state.pc = current_pc; - ppc_state.npc = current_pc + 4; - return sizeof(AnyCallback) + sizeof(operands); -} - s32 CachedInterpreter::WriteBrokenBlockNPC(PowerPC::PowerPCState& ppc_state, - const WritePCOperands& operands) + const WriteBrokenBlockNPCOperands& operands) { const auto& [current_pc] = operands; ppc_state.npc = current_pc; @@ -145,33 +163,6 @@ s32 CachedInterpreter::CheckFPU(PowerPC::PowerPCState& ppc_state, const CheckHal return sizeof(AnyCallback) + sizeof(operands); } -s32 CachedInterpreter::CheckDSI(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands) -{ - const auto& [power_pc, current_pc, downcount] = operands; - if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0) - { - ppc_state.pc = current_pc; - ppc_state.downcount -= downcount; - power_pc.CheckExceptions(); - return 0; - } - return sizeof(AnyCallback) + sizeof(operands); -} - -s32 CachedInterpreter::CheckProgramException(PowerPC::PowerPCState& ppc_state, - const CheckHaltOperands& operands) -{ - const auto& [power_pc, current_pc, downcount] = operands; - if ((ppc_state.Exceptions & EXCEPTION_PROGRAM) != 0) - { - ppc_state.pc = current_pc; - ppc_state.downcount -= downcount; - power_pc.CheckExceptions(); - return 0; - } - return sizeof(AnyCallback) + sizeof(operands); -} - s32 CachedInterpreter::CheckBreakpoint(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands) { @@ -344,14 +335,25 @@ bool CachedInterpreter::DoJit(u32 em_address, JitBlock* b, u32 nextPC) js.firstFPInstructionFound = true; } - if (op.canEndBlock) - Write(WritePC, {js.compilerPC}); - Write(Interpret, - {interpreter, Interpreter::GetInterpreterOp(op.inst), js.compilerPC, op.inst}); - if (jo.memcheck && (op.opinfo->flags & FL_LOADSTORE) != 0) - Write(CheckDSI, {power_pc, js.compilerPC, js.downcountAmount}); - if (!op.canEndBlock && ShouldHandleFPExceptionForInstruction(&op)) - Write(CheckProgramException, {power_pc, js.compilerPC, js.downcountAmount}); + // Instruction may cause a DSI Exception or Program Exception. + if ((jo.memcheck && (op.opinfo->flags & FL_LOADSTORE) != 0) || + (!op.canEndBlock && ShouldHandleFPExceptionForInstruction(&op))) + { + const InterpretAndCheckExceptionsOperands operands = { + {interpreter, Interpreter::GetInterpreterOp(op.inst), js.compilerPC, op.inst}, + power_pc, + js.downcountAmount}; + Write(op.canEndBlock ? InterpretAndCheckExceptions : + InterpretAndCheckExceptions, + operands); + } + else + { + const InterpretOperands operands = {interpreter, Interpreter::GetInterpreterOp(op.inst), + js.compilerPC, op.inst}; + Write(op.canEndBlock ? Interpret : Interpret, operands); + } + if (op.branchIsIdleLoop) Write(CheckIdle, {m_system.GetCoreTiming(), js.blockStart}); if (op.canEndBlock) diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h index a1c87a8986..8b4752dbb8 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h @@ -64,20 +64,22 @@ private: struct EndBlockOperands; struct InterpretOperands; + struct InterpretAndCheckExceptionsOperands; struct HLEFunctionOperands; - struct WritePCOperands; + struct WriteBrokenBlockNPCOperands; struct CheckHaltOperands; struct CheckIdleOperands; static s32 EndBlock(PowerPC::PowerPCState& ppc_state, const EndBlockOperands& operands); + template static s32 Interpret(PowerPC::PowerPCState& ppc_state, const InterpretOperands& operands); + template + static s32 InterpretAndCheckExceptions(PowerPC::PowerPCState& ppc_state, + const InterpretAndCheckExceptionsOperands& operands); static s32 HLEFunction(PowerPC::PowerPCState& ppc_state, const HLEFunctionOperands& operands); - static s32 WritePC(PowerPC::PowerPCState& ppc_state, const WritePCOperands& operands); - static s32 WriteBrokenBlockNPC(PowerPC::PowerPCState& ppc_state, const WritePCOperands& operands); + static s32 WriteBrokenBlockNPC(PowerPC::PowerPCState& ppc_state, + const WriteBrokenBlockNPCOperands& operands); static s32 CheckFPU(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands); - static s32 CheckDSI(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands); - static s32 CheckProgramException(PowerPC::PowerPCState& ppc_state, - const CheckHaltOperands& operands); static s32 CheckBreakpoint(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands); static s32 CheckIdle(PowerPC::PowerPCState& ppc_state, const CheckIdleOperands& operands); @@ -101,6 +103,12 @@ struct CachedInterpreter::InterpretOperands UGeckoInstruction inst; }; +struct CachedInterpreter::InterpretAndCheckExceptionsOperands : InterpretOperands +{ + PowerPC::PowerPCManager& power_pc; + u32 downcount; +}; + struct CachedInterpreter::HLEFunctionOperands { Core::System& system; @@ -108,7 +116,7 @@ struct CachedInterpreter::HLEFunctionOperands u32 hook_index; }; -struct CachedInterpreter::WritePCOperands +struct CachedInterpreter::WriteBrokenBlockNPCOperands { u32 current_pc; u32 : 32;