diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index 7b89fbf5a6..86f971d173 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -109,7 +109,8 @@ void CachedInterpreter::ExecuteOneBlock() break; case Instruction::Type::Interpreter: - code->interpreter_callback(*Interpreter::getInstance(), UGeckoInstruction(code->data)); + code->interpreter_callback(Core::System::GetInstance().GetInterpreter(), + UGeckoInstruction(code->data)); break; default: diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 977c6cefad..4f2b3a89bd 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -27,13 +27,6 @@ #include "Core/PowerPC/PowerPC.h" #include "Core/System.h" -namespace -{ -u32 last_pc; -} - -bool Interpreter::m_end_block; - namespace { // Determines whether or not the given instruction is one where its execution @@ -63,13 +56,20 @@ bool IsInvalidPairedSingleExecution(UGeckoInstruction inst) return HID2(PowerPC::ppcState).PSE && !HID2(PowerPC::ppcState).LSQE && IsPairedSingleQuantizedNonIndexedInstruction(inst); } +} // namespace -void UpdatePC() +void Interpreter::UpdatePC() { - last_pc = PowerPC::ppcState.pc; + m_last_pc = PowerPC::ppcState.pc; PowerPC::ppcState.pc = PowerPC::ppcState.npc; } -} // Anonymous namespace + +Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state) + : m_system(system), m_ppc_state(ppc_state) +{ +} + +Interpreter::~Interpreter() = default; void Interpreter::Init() { @@ -80,9 +80,7 @@ void Interpreter::Shutdown() { } -static bool s_start_trace = false; - -static void Trace(const UGeckoInstruction& inst) +void Interpreter::Trace(const UGeckoInstruction& inst) { std::string regs; for (size_t i = 0; i < std::size(PowerPC::ppcState.gpr); i++) @@ -109,8 +107,8 @@ static void Trace(const UGeckoInstruction& inst) bool Interpreter::HandleFunctionHooking(u32 address) { - return HLE::ReplaceFunctionIfPossible(address, [](u32 hook_index, HLE::HookType type) { - HLEFunction(*Interpreter::getInstance(), hook_index); + return HLE::ReplaceFunctionIfPossible(address, [this](u32 hook_index, HLE::HookType type) { + HLEFunction(*this, hook_index); return type != HLE::HookType::Start; }); } @@ -135,14 +133,14 @@ int Interpreter::SingleStepInner() // if ((PowerPC::ppcState.pc & 0x00FFFFFF) >= 0x000AB54C && // (PowerPC::ppcState.pc & 0x00FFFFFF) <= 0x000AB624) // { - // s_start_trace = true; + // m_start_trace = true; // } // else // { - // s_start_trace = false; + // m_start_trace = false; // } - if (s_start_trace) + if (m_start_trace) { Trace(m_prev_inst); } @@ -156,7 +154,7 @@ int Interpreter::SingleStepInner() } else if (PowerPC::ppcState.msr.FP) { - RunInterpreterOp(*Interpreter::getInstance(), m_prev_inst); + RunInterpreterOp(*this, m_prev_inst); if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0) { CheckExceptions(); @@ -172,7 +170,7 @@ int Interpreter::SingleStepInner() } else { - RunInterpreterOp(*Interpreter::getInstance(), m_prev_inst); + RunInterpreterOp(*this, m_prev_inst); if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0) { CheckExceptions(); @@ -319,6 +317,7 @@ void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstructio auto& system = Core::System::GetInstance(); Core::CPUThreadGuard guard(system); + const u32 last_pc = interpreter.m_last_pc; const u32 opcode = PowerPC::HostRead_U32(guard, last_pc); const std::string disasm = Common::GekkoDisassembler::Disassemble(opcode, last_pc); NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm); @@ -360,9 +359,3 @@ const char* Interpreter::GetName() const return "Interpreter32"; #endif } - -Interpreter* Interpreter::getInstance() -{ - static Interpreter instance; - return &instance; -} diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.h b/Source/Core/Core/PowerPC/Interpreter/Interpreter.h index ae2e87bff4..88dac22031 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.h +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.h @@ -9,9 +9,25 @@ #include "Core/PowerPC/CPUCoreBase.h" #include "Core/PowerPC/Gekko.h" +namespace Core +{ +class System; +} +namespace PowerPC +{ +struct PowerPCState; +} + class Interpreter : public CPUCoreBase { public: + Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state); + Interpreter(const Interpreter&) = delete; + Interpreter(Interpreter&&) = delete; + Interpreter& operator=(const Interpreter&) = delete; + Interpreter& operator=(Interpreter&&) = delete; + ~Interpreter(); + void Init() override; void Shutdown() override; void SingleStep() override; @@ -266,9 +282,6 @@ public: static Instruction GetInterpreterOp(UGeckoInstruction inst); static void RunInterpreterOp(Interpreter& interpreter, UGeckoInstruction inst); - // singleton - static Interpreter* getInstance(); - static void RunTable4(Interpreter& interpreter, UGeckoInstruction inst); static void RunTable19(Interpreter& interpreter, UGeckoInstruction inst); static void RunTable31(Interpreter& interpreter, UGeckoInstruction inst); @@ -280,7 +293,7 @@ public: private: void CheckExceptions(); - static bool HandleFunctionHooking(u32 address); + bool HandleFunctionHooking(u32 address); // flag helper static void Helper_UpdateCR0(u32 value); @@ -290,7 +303,15 @@ private: static void Helper_FloatCompareOrdered(UGeckoInstruction inst, double a, double b); static void Helper_FloatCompareUnordered(UGeckoInstruction inst, double a, double b); - UGeckoInstruction m_prev_inst{}; + void UpdatePC(); - static bool m_end_block; + void Trace(const UGeckoInstruction& inst); + + Core::System& m_system; + PowerPC::PowerPCState& m_ppc_state; + + UGeckoInstruction m_prev_inst{}; + u32 m_last_pc = 0; + bool m_end_block = false; + bool m_start_trace = false; }; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp index e2fba4a931..09d696076d 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Branch.cpp @@ -24,7 +24,7 @@ void Interpreter::bx(Interpreter& interpreter, UGeckoInstruction inst) else PowerPC::ppcState.npc = PowerPC::ppcState.pc + address; - m_end_block = true; + interpreter.m_end_block = true; } // bcx - ugly, straight from PPC manual equations :) @@ -54,7 +54,7 @@ void Interpreter::bcx(Interpreter& interpreter, UGeckoInstruction inst) PowerPC::ppcState.npc = PowerPC::ppcState.pc + address; } - m_end_block = true; + interpreter.m_end_block = true; } void Interpreter::bcctrx(Interpreter& interpreter, UGeckoInstruction inst) @@ -72,7 +72,7 @@ void Interpreter::bcctrx(Interpreter& interpreter, UGeckoInstruction inst) LR(PowerPC::ppcState) = PowerPC::ppcState.pc + 4; } - m_end_block = true; + interpreter.m_end_block = true; } void Interpreter::bclrx(Interpreter& interpreter, UGeckoInstruction inst) @@ -91,12 +91,12 @@ void Interpreter::bclrx(Interpreter& interpreter, UGeckoInstruction inst) LR(PowerPC::ppcState) = PowerPC::ppcState.pc + 4; } - m_end_block = true; + interpreter.m_end_block = true; } void Interpreter::HLEFunction(Interpreter& interpreter, UGeckoInstruction inst) { - m_end_block = true; + interpreter.m_end_block = true; ASSERT(Core::IsCPUThread()); Core::CPUThreadGuard guard(Core::System::GetInstance()); @@ -126,7 +126,7 @@ void Interpreter::rfi(Interpreter& interpreter, UGeckoInstruction inst) // else // set NPC to saved offset and resume PowerPC::ppcState.npc = SRR0(PowerPC::ppcState); - m_end_block = true; + interpreter.m_end_block = true; } // sc isn't really used for anything important in GameCube games (just for a write barrier) so we @@ -136,5 +136,5 @@ void Interpreter::sc(Interpreter& interpreter, UGeckoInstruction inst) { PowerPC::ppcState.Exceptions |= EXCEPTION_SYSCALL; PowerPC::CheckExceptions(); - m_end_block = true; + interpreter.m_end_block = true; } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp index 7f3a4c1827..b5bc42d234 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -137,7 +137,7 @@ void Interpreter::twi(Interpreter& interpreter, UGeckoInstruction inst) { GenerateProgramException(ProgramExceptionCause::Trap); PowerPC::CheckExceptions(); - m_end_block = true; // Dunno about this + interpreter.m_end_block = true; // Dunno about this } } @@ -353,7 +353,7 @@ void Interpreter::tw(Interpreter& interpreter, UGeckoInstruction inst) { GenerateProgramException(ProgramExceptionCause::Trap); PowerPC::CheckExceptions(); - m_end_block = true; // Dunno about this + interpreter.m_end_block = true; // Dunno about this } } diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 3d00d01b29..4e171f087d 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -175,7 +175,7 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst) CheckFPExceptions(PowerPC::ppcState.fpscr); PowerPC::CheckExceptions(); - m_end_block = true; + interpreter.m_end_block = true; } // Segment registers. MMU control. diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 3a97cf3711..73e0dd3601 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -344,7 +344,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst) Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst); ABI_PushRegistersAndAdjustStack({}, 0); - ABI_CallFunctionPC(instr, Interpreter::getInstance(), inst.hex); + ABI_CallFunctionPC(instr, &Core::System::GetInstance().GetInterpreter(), inst.hex); ABI_PopRegistersAndAdjustStack({}, 0); // If the instruction wrote to any registers which were marked as discarded, diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 65e454b21a..51c775f66d 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -199,7 +199,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst) Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst); MOVP2R(ARM64Reg::X8, instr); - MOVP2R(ARM64Reg::W0, Interpreter::getInstance()); + MOVP2R(ARM64Reg::W0, &Core::System::GetInstance().GetInterpreter()); MOVI2R(ARM64Reg::W1, inst.hex); BLR(ARM64Reg::X8); diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 2d8f201b30..c2b763b684 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -40,7 +40,6 @@ PowerPCState ppcState; static CPUCoreBase* s_cpu_core_base = nullptr; static bool s_cpu_core_base_is_injected = false; -Interpreter* const s_interpreter = Interpreter::getInstance(); static CoreMode s_mode = CoreMode::Interpreter; BreakPoints breakpoints; @@ -220,12 +219,13 @@ static void InitializeCPUCore(CPUCore cpu_core) { // We initialize the interpreter because // it is used on boot and code window independently. - s_interpreter->Init(); + auto& interpreter = Core::System::GetInstance().GetInterpreter(); + interpreter.Init(); switch (cpu_core) { case CPUCore::Interpreter: - s_cpu_core_base = s_interpreter; + s_cpu_core_base = &interpreter; break; default: @@ -239,7 +239,7 @@ static void InitializeCPUCore(CPUCore cpu_core) break; } - s_mode = s_cpu_core_base == s_interpreter ? CoreMode::Interpreter : CoreMode::JIT; + s_mode = s_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT; } const std::vector& AvailableCPUCores() @@ -316,7 +316,8 @@ void Shutdown() { InjectExternalCPUCore(nullptr); JitInterface::Shutdown(); - s_interpreter->Shutdown(); + auto& interpreter = Core::System::GetInstance().GetInterpreter(); + interpreter.Shutdown(); s_cpu_core_base = nullptr; } @@ -327,17 +328,19 @@ CoreMode GetMode() static void ApplyMode() { + auto& interpreter = Core::System::GetInstance().GetInterpreter(); + switch (s_mode) { case CoreMode::Interpreter: // Switching from JIT to interpreter - s_cpu_core_base = s_interpreter; + s_cpu_core_base = &interpreter; break; case CoreMode::JIT: // Switching from interpreter to JIT. // Don't really need to do much. It'll work, the cache will refill itself. s_cpu_core_base = JitInterface::GetCore(); if (!s_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host - s_cpu_core_base = s_interpreter; + s_cpu_core_base = &interpreter; break; } } diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 788a4834b9..0a1a0eb77f 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -22,6 +22,7 @@ #include "Core/HW/SI/SI.h" #include "Core/HW/Sram.h" #include "Core/HW/VideoInterface.h" +#include "Core/PowerPC/Interpreter/Interpreter.h" #include "Core/PowerPC/PowerPC.h" #include "IOS/USB/Emulated/Skylander.h" #include "VideoCommon/CommandProcessor.h" @@ -39,7 +40,7 @@ struct System::Impl : m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system), m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system), m_ppc_state(PowerPC::ppcState), m_processor_interface(system), m_serial_interface(system), - m_video_interface(system) + m_video_interface(system), m_interpreter(system, m_ppc_state) { } @@ -70,6 +71,7 @@ struct System::Impl Sram m_sram; VertexShaderManager m_vertex_shader_manager; VideoInterface::VideoInterfaceManager m_video_interface; + Interpreter m_interpreter; }; System::System() : m_impl{std::make_unique(*this)} @@ -175,6 +177,11 @@ HSP::HSPManager& System::GetHSP() const return m_impl->m_hsp; } +Interpreter& System::GetInterpreter() const +{ + return m_impl->m_interpreter; +} + IOS::HLE::USB::SkylanderPortal& System::GetSkylanderPortal() const { return m_impl->m_skylander_portal; diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index d49819a1aa..e1c7b9a5b8 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -6,6 +6,7 @@ #include class GeometryShaderManager; +class Interpreter; class PixelShaderManager; class SoundStream; struct Sram; @@ -131,6 +132,7 @@ public: GeometryShaderManager& GetGeometryShaderManager() const; GPFifo::GPFifoManager& GetGPFifo() const; HSP::HSPManager& GetHSP() const; + Interpreter& GetInterpreter() const; IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const; Memory::MemoryManager& GetMemory() const; MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;