diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index 2772872ce4..bf75e3d0f1 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -20,6 +20,8 @@ struct CachedInterpreter::Instruction using CommonCallback = void (*)(UGeckoInstruction); using ConditionalCallback = bool (*)(u32); using InterpreterCallback = void (*)(Interpreter&, UGeckoInstruction); + using CachedInterpreterCallback = void (*)(CachedInterpreter&, UGeckoInstruction); + using ConditionalCachedInterpreterCallback = bool (*)(CachedInterpreter&, u32); Instruction() {} Instruction(const CommonCallback c, UGeckoInstruction i) @@ -37,12 +39,25 @@ struct CachedInterpreter::Instruction { } + Instruction(const CachedInterpreterCallback c, UGeckoInstruction i) + : cached_interpreter_callback(c), data(i.hex), type(Type::CachedInterpreter) + { + } + + Instruction(const ConditionalCachedInterpreterCallback c, u32 d) + : conditional_cached_interpreter_callback(c), data(d), + type(Type::ConditionalCachedInterpreter) + { + } + enum class Type { Abort, Common, Conditional, Interpreter, + CachedInterpreter, + ConditionalCachedInterpreter, }; union @@ -50,6 +65,8 @@ struct CachedInterpreter::Instruction const CommonCallback common_callback = nullptr; const ConditionalCallback conditional_callback; const InterpreterCallback interpreter_callback; + const CachedInterpreterCallback cached_interpreter_callback; + const ConditionalCachedInterpreterCallback conditional_cached_interpreter_callback; }; u32 data = 0; @@ -91,11 +108,12 @@ void CachedInterpreter::ExecuteOneBlock() const u8* normal_entry = m_block_cache.Dispatch(); if (!normal_entry) { - Jit(PowerPC::ppcState.pc); + Jit(m_ppc_state.pc); return; } const Instruction* code = reinterpret_cast(normal_entry); + auto& interpreter = m_system.GetInterpreter(); for (; code->type != Instruction::Type::Abort; ++code) { @@ -111,8 +129,16 @@ void CachedInterpreter::ExecuteOneBlock() break; case Instruction::Type::Interpreter: - code->interpreter_callback(Core::System::GetInstance().GetInterpreter(), - UGeckoInstruction(code->data)); + code->interpreter_callback(interpreter, UGeckoInstruction(code->data)); + break; + + case Instruction::Type::CachedInterpreter: + code->cached_interpreter_callback(*this, UGeckoInstruction(code->data)); + break; + + case Instruction::Type::ConditionalCachedInterpreter: + if (code->conditional_cached_interpreter_callback(*this, code->data)) + return; break; default: @@ -125,9 +151,8 @@ void CachedInterpreter::ExecuteOneBlock() void CachedInterpreter::Run() { - auto& system = Core::System::GetInstance(); - auto& core_timing = system.GetCoreTiming(); - auto& cpu = system.GetCPU(); + auto& core_timing = m_system.GetCoreTiming(); + auto& cpu = m_system.GetCPU(); const CPU::State* state_ptr = cpu.GetStatePtr(); while (cpu.GetState() == CPU::State::Running) @@ -139,96 +164,103 @@ void CachedInterpreter::Run() do { ExecuteOneBlock(); - } while (PowerPC::ppcState.downcount > 0 && *state_ptr == CPU::State::Running); + } while (m_ppc_state.downcount > 0 && *state_ptr == CPU::State::Running); } } void CachedInterpreter::SingleStep() { // Enter new timing slice - Core::System::GetInstance().GetCoreTiming().Advance(); + m_system.GetCoreTiming().Advance(); ExecuteOneBlock(); } -static void EndBlock(UGeckoInstruction data) +void CachedInterpreter::EndBlock(CachedInterpreter& cached_interpreter, UGeckoInstruction data) { - PowerPC::ppcState.pc = PowerPC::ppcState.npc; - PowerPC::ppcState.downcount -= data.hex; - PowerPC::UpdatePerformanceMonitor(data.hex, 0, 0, PowerPC::ppcState); + auto& ppc_state = cached_interpreter.m_ppc_state; + ppc_state.pc = ppc_state.npc; + ppc_state.downcount -= data.hex; + PowerPC::UpdatePerformanceMonitor(data.hex, 0, 0, ppc_state); } -static void UpdateNumLoadStoreInstructions(UGeckoInstruction data) +void CachedInterpreter::UpdateNumLoadStoreInstructions(CachedInterpreter& cached_interpreter, + UGeckoInstruction data) { - PowerPC::UpdatePerformanceMonitor(0, data.hex, 0, PowerPC::ppcState); + PowerPC::UpdatePerformanceMonitor(0, data.hex, 0, cached_interpreter.m_ppc_state); } -static void UpdateNumFloatingPointInstructions(UGeckoInstruction data) +void CachedInterpreter::UpdateNumFloatingPointInstructions(CachedInterpreter& cached_interpreter, + UGeckoInstruction data) { - PowerPC::UpdatePerformanceMonitor(0, 0, data.hex, PowerPC::ppcState); + PowerPC::UpdatePerformanceMonitor(0, 0, data.hex, cached_interpreter.m_ppc_state); } -static void WritePC(UGeckoInstruction data) +void CachedInterpreter::WritePC(CachedInterpreter& cached_interpreter, UGeckoInstruction data) { - PowerPC::ppcState.pc = data.hex; - PowerPC::ppcState.npc = data.hex + 4; + auto& ppc_state = cached_interpreter.m_ppc_state; + ppc_state.pc = data.hex; + ppc_state.npc = data.hex + 4; } -static void WriteBrokenBlockNPC(UGeckoInstruction data) +void CachedInterpreter::WriteBrokenBlockNPC(CachedInterpreter& cached_interpreter, + UGeckoInstruction data) { - PowerPC::ppcState.npc = data.hex; + cached_interpreter.m_ppc_state.npc = data.hex; } -static bool CheckFPU(u32 data) +bool CachedInterpreter::CheckFPU(CachedInterpreter& cached_interpreter, u32 data) { - if (!PowerPC::ppcState.msr.FP) + auto& ppc_state = cached_interpreter.m_ppc_state; + if (!ppc_state.msr.FP) { - PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; + ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; PowerPC::CheckExceptions(); - PowerPC::ppcState.downcount -= data; + ppc_state.downcount -= data; return true; } return false; } -static bool CheckDSI(u32 data) +bool CachedInterpreter::CheckDSI(CachedInterpreter& cached_interpreter, u32 data) { - if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + auto& ppc_state = cached_interpreter.m_ppc_state; + if (ppc_state.Exceptions & EXCEPTION_DSI) { PowerPC::CheckExceptions(); - PowerPC::ppcState.downcount -= data; + ppc_state.downcount -= data; return true; } return false; } -static bool CheckProgramException(u32 data) +bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpreter, u32 data) { - if (PowerPC::ppcState.Exceptions & EXCEPTION_PROGRAM) + auto& ppc_state = cached_interpreter.m_ppc_state; + if (ppc_state.Exceptions & EXCEPTION_PROGRAM) { PowerPC::CheckExceptions(); - PowerPC::ppcState.downcount -= data; + ppc_state.downcount -= data; return true; } return false; } -static bool CheckBreakpoint(u32 data) +bool CachedInterpreter::CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data) { PowerPC::CheckBreakPoints(); - auto& system = Core::System::GetInstance(); - if (system.GetCPU().GetState() != CPU::State::Running) + if (cached_interpreter.m_system.GetCPU().GetState() != CPU::State::Running) { - PowerPC::ppcState.downcount -= data; + cached_interpreter.m_ppc_state.downcount -= data; return true; } return false; } -static bool CheckIdle(u32 idle_pc) +bool CachedInterpreter::CheckIdle(CachedInterpreter& cached_interpreter, u32 idle_pc) { - if (PowerPC::ppcState.npc == idle_pc) + if (cached_interpreter.m_ppc_state.npc == idle_pc) { - Core::System::GetInstance().GetCoreTiming().Idle(); + cached_interpreter.m_system.GetCoreTiming().Idle(); } return false; } @@ -257,20 +289,20 @@ void CachedInterpreter::Jit(u32 address) } const u32 nextPC = - analyzer.Analyze(PowerPC::ppcState.pc, &code_block, &m_code_buffer, m_code_buffer.size()); + analyzer.Analyze(m_ppc_state.pc, &code_block, &m_code_buffer, m_code_buffer.size()); if (code_block.m_memory_exception) { // Address of instruction could not be translated - PowerPC::ppcState.npc = nextPC; - PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; + m_ppc_state.npc = nextPC; + m_ppc_state.Exceptions |= EXCEPTION_ISI; PowerPC::CheckExceptions(); WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC); return; } - JitBlock* b = m_block_cache.AllocateBlock(PowerPC::ppcState.pc); + JitBlock* b = m_block_cache.AllocateBlock(m_ppc_state.pc); - js.blockStart = PowerPC::ppcState.pc; + js.blockStart = m_ppc_state.pc; js.firstFPInstructionFound = false; js.fifoBytesSinceCheck = 0; js.downcountAmount = 0; diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h index e853be9edf..513ad7dbc9 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h @@ -43,6 +43,19 @@ private: bool HandleFunctionHooking(u32 address); + static void EndBlock(CachedInterpreter& cached_interpreter, UGeckoInstruction data); + static void UpdateNumLoadStoreInstructions(CachedInterpreter& cached_interpreter, + UGeckoInstruction data); + static void UpdateNumFloatingPointInstructions(CachedInterpreter& cached_interpreter, + UGeckoInstruction data); + static void WritePC(CachedInterpreter& cached_interpreter, UGeckoInstruction data); + static void WriteBrokenBlockNPC(CachedInterpreter& cached_interpreter, UGeckoInstruction data); + static bool CheckFPU(CachedInterpreter& cached_interpreter, u32 data); + static bool CheckDSI(CachedInterpreter& cached_interpreter, u32 data); + static bool CheckProgramException(CachedInterpreter& cached_interpreter, u32 data); + static bool CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data); + static bool CheckIdle(CachedInterpreter& cached_interpreter, u32 idle_pc); + BlockCache m_block_cache{*this}; std::vector m_code; };