Interpreter: Move global state into class, move instance to System.

This commit is contained in:
Admiral H. Curtiss 2023-03-17 00:24:22 +01:00
parent 919182eda2
commit 3d67c11b91
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
11 changed files with 80 additions and 53 deletions

View File

@ -109,7 +109,8 @@ void CachedInterpreter::ExecuteOneBlock()
break; break;
case Instruction::Type::Interpreter: case Instruction::Type::Interpreter:
code->interpreter_callback(*Interpreter::getInstance(), UGeckoInstruction(code->data)); code->interpreter_callback(Core::System::GetInstance().GetInterpreter(),
UGeckoInstruction(code->data));
break; break;
default: default:

View File

@ -27,13 +27,6 @@
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h" #include "Core/System.h"
namespace
{
u32 last_pc;
}
bool Interpreter::m_end_block;
namespace namespace
{ {
// Determines whether or not the given instruction is one where its execution // 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 && return HID2(PowerPC::ppcState).PSE && !HID2(PowerPC::ppcState).LSQE &&
IsPairedSingleQuantizedNonIndexedInstruction(inst); 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; 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() void Interpreter::Init()
{ {
@ -80,9 +80,7 @@ void Interpreter::Shutdown()
{ {
} }
static bool s_start_trace = false; void Interpreter::Trace(const UGeckoInstruction& inst)
static void Trace(const UGeckoInstruction& inst)
{ {
std::string regs; std::string regs;
for (size_t i = 0; i < std::size(PowerPC::ppcState.gpr); i++) 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) bool Interpreter::HandleFunctionHooking(u32 address)
{ {
return HLE::ReplaceFunctionIfPossible(address, [](u32 hook_index, HLE::HookType type) { return HLE::ReplaceFunctionIfPossible(address, [this](u32 hook_index, HLE::HookType type) {
HLEFunction(*Interpreter::getInstance(), hook_index); HLEFunction(*this, hook_index);
return type != HLE::HookType::Start; return type != HLE::HookType::Start;
}); });
} }
@ -135,14 +133,14 @@ int Interpreter::SingleStepInner()
// if ((PowerPC::ppcState.pc & 0x00FFFFFF) >= 0x000AB54C && // if ((PowerPC::ppcState.pc & 0x00FFFFFF) >= 0x000AB54C &&
// (PowerPC::ppcState.pc & 0x00FFFFFF) <= 0x000AB624) // (PowerPC::ppcState.pc & 0x00FFFFFF) <= 0x000AB624)
// { // {
// s_start_trace = true; // m_start_trace = true;
// } // }
// else // else
// { // {
// s_start_trace = false; // m_start_trace = false;
// } // }
if (s_start_trace) if (m_start_trace)
{ {
Trace(m_prev_inst); Trace(m_prev_inst);
} }
@ -156,7 +154,7 @@ int Interpreter::SingleStepInner()
} }
else if (PowerPC::ppcState.msr.FP) else if (PowerPC::ppcState.msr.FP)
{ {
RunInterpreterOp(*Interpreter::getInstance(), m_prev_inst); RunInterpreterOp(*this, m_prev_inst);
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
CheckExceptions(); CheckExceptions();
@ -172,7 +170,7 @@ int Interpreter::SingleStepInner()
} }
else else
{ {
RunInterpreterOp(*Interpreter::getInstance(), m_prev_inst); RunInterpreterOp(*this, m_prev_inst);
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0) if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{ {
CheckExceptions(); CheckExceptions();
@ -319,6 +317,7 @@ void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstructio
auto& system = Core::System::GetInstance(); auto& system = Core::System::GetInstance();
Core::CPUThreadGuard guard(system); Core::CPUThreadGuard guard(system);
const u32 last_pc = interpreter.m_last_pc;
const u32 opcode = PowerPC::HostRead_U32(guard, last_pc); const u32 opcode = PowerPC::HostRead_U32(guard, last_pc);
const std::string disasm = Common::GekkoDisassembler::Disassemble(opcode, last_pc); const std::string disasm = Common::GekkoDisassembler::Disassemble(opcode, last_pc);
NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm); NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm);
@ -360,9 +359,3 @@ const char* Interpreter::GetName() const
return "Interpreter32"; return "Interpreter32";
#endif #endif
} }
Interpreter* Interpreter::getInstance()
{
static Interpreter instance;
return &instance;
}

View File

@ -9,9 +9,25 @@
#include "Core/PowerPC/CPUCoreBase.h" #include "Core/PowerPC/CPUCoreBase.h"
#include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/Gekko.h"
namespace Core
{
class System;
}
namespace PowerPC
{
struct PowerPCState;
}
class Interpreter : public CPUCoreBase class Interpreter : public CPUCoreBase
{ {
public: 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 Init() override;
void Shutdown() override; void Shutdown() override;
void SingleStep() override; void SingleStep() override;
@ -266,9 +282,6 @@ public:
static Instruction GetInterpreterOp(UGeckoInstruction inst); static Instruction GetInterpreterOp(UGeckoInstruction inst);
static void RunInterpreterOp(Interpreter& interpreter, UGeckoInstruction inst); static void RunInterpreterOp(Interpreter& interpreter, UGeckoInstruction inst);
// singleton
static Interpreter* getInstance();
static void RunTable4(Interpreter& interpreter, UGeckoInstruction inst); static void RunTable4(Interpreter& interpreter, UGeckoInstruction inst);
static void RunTable19(Interpreter& interpreter, UGeckoInstruction inst); static void RunTable19(Interpreter& interpreter, UGeckoInstruction inst);
static void RunTable31(Interpreter& interpreter, UGeckoInstruction inst); static void RunTable31(Interpreter& interpreter, UGeckoInstruction inst);
@ -280,7 +293,7 @@ public:
private: private:
void CheckExceptions(); void CheckExceptions();
static bool HandleFunctionHooking(u32 address); bool HandleFunctionHooking(u32 address);
// flag helper // flag helper
static void Helper_UpdateCR0(u32 value); static void Helper_UpdateCR0(u32 value);
@ -290,7 +303,15 @@ private:
static void Helper_FloatCompareOrdered(UGeckoInstruction inst, double a, double b); static void Helper_FloatCompareOrdered(UGeckoInstruction inst, double a, double b);
static void Helper_FloatCompareUnordered(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;
}; };

View File

@ -24,7 +24,7 @@ void Interpreter::bx(Interpreter& interpreter, UGeckoInstruction inst)
else else
PowerPC::ppcState.npc = PowerPC::ppcState.pc + address; PowerPC::ppcState.npc = PowerPC::ppcState.pc + address;
m_end_block = true; interpreter.m_end_block = true;
} }
// bcx - ugly, straight from PPC manual equations :) // 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; PowerPC::ppcState.npc = PowerPC::ppcState.pc + address;
} }
m_end_block = true; interpreter.m_end_block = true;
} }
void Interpreter::bcctrx(Interpreter& interpreter, UGeckoInstruction inst) 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; LR(PowerPC::ppcState) = PowerPC::ppcState.pc + 4;
} }
m_end_block = true; interpreter.m_end_block = true;
} }
void Interpreter::bclrx(Interpreter& interpreter, UGeckoInstruction inst) 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; LR(PowerPC::ppcState) = PowerPC::ppcState.pc + 4;
} }
m_end_block = true; interpreter.m_end_block = true;
} }
void Interpreter::HLEFunction(Interpreter& interpreter, UGeckoInstruction inst) void Interpreter::HLEFunction(Interpreter& interpreter, UGeckoInstruction inst)
{ {
m_end_block = true; interpreter.m_end_block = true;
ASSERT(Core::IsCPUThread()); ASSERT(Core::IsCPUThread());
Core::CPUThreadGuard guard(Core::System::GetInstance()); Core::CPUThreadGuard guard(Core::System::GetInstance());
@ -126,7 +126,7 @@ void Interpreter::rfi(Interpreter& interpreter, UGeckoInstruction inst)
// else // else
// set NPC to saved offset and resume // set NPC to saved offset and resume
PowerPC::ppcState.npc = SRR0(PowerPC::ppcState); 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 // 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::ppcState.Exceptions |= EXCEPTION_SYSCALL;
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_end_block = true; interpreter.m_end_block = true;
} }

View File

@ -137,7 +137,7 @@ void Interpreter::twi(Interpreter& interpreter, UGeckoInstruction inst)
{ {
GenerateProgramException(ProgramExceptionCause::Trap); GenerateProgramException(ProgramExceptionCause::Trap);
PowerPC::CheckExceptions(); 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); GenerateProgramException(ProgramExceptionCause::Trap);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_end_block = true; // Dunno about this interpreter.m_end_block = true; // Dunno about this
} }
} }

View File

@ -175,7 +175,7 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst)
CheckFPExceptions(PowerPC::ppcState.fpscr); CheckFPExceptions(PowerPC::ppcState.fpscr);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_end_block = true; interpreter.m_end_block = true;
} }
// Segment registers. MMU control. // Segment registers. MMU control.

View File

@ -344,7 +344,7 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst); Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
ABI_PushRegistersAndAdjustStack({}, 0); ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunctionPC(instr, Interpreter::getInstance(), inst.hex); ABI_CallFunctionPC(instr, &Core::System::GetInstance().GetInterpreter(), inst.hex);
ABI_PopRegistersAndAdjustStack({}, 0); ABI_PopRegistersAndAdjustStack({}, 0);
// If the instruction wrote to any registers which were marked as discarded, // If the instruction wrote to any registers which were marked as discarded,

View File

@ -199,7 +199,7 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst); Interpreter::Instruction instr = Interpreter::GetInterpreterOp(inst);
MOVP2R(ARM64Reg::X8, instr); MOVP2R(ARM64Reg::X8, instr);
MOVP2R(ARM64Reg::W0, Interpreter::getInstance()); MOVP2R(ARM64Reg::W0, &Core::System::GetInstance().GetInterpreter());
MOVI2R(ARM64Reg::W1, inst.hex); MOVI2R(ARM64Reg::W1, inst.hex);
BLR(ARM64Reg::X8); BLR(ARM64Reg::X8);

View File

@ -40,7 +40,6 @@ PowerPCState ppcState;
static CPUCoreBase* s_cpu_core_base = nullptr; static CPUCoreBase* s_cpu_core_base = nullptr;
static bool s_cpu_core_base_is_injected = false; static bool s_cpu_core_base_is_injected = false;
Interpreter* const s_interpreter = Interpreter::getInstance();
static CoreMode s_mode = CoreMode::Interpreter; static CoreMode s_mode = CoreMode::Interpreter;
BreakPoints breakpoints; BreakPoints breakpoints;
@ -220,12 +219,13 @@ static void InitializeCPUCore(CPUCore cpu_core)
{ {
// We initialize the interpreter because // We initialize the interpreter because
// it is used on boot and code window independently. // it is used on boot and code window independently.
s_interpreter->Init(); auto& interpreter = Core::System::GetInstance().GetInterpreter();
interpreter.Init();
switch (cpu_core) switch (cpu_core)
{ {
case CPUCore::Interpreter: case CPUCore::Interpreter:
s_cpu_core_base = s_interpreter; s_cpu_core_base = &interpreter;
break; break;
default: default:
@ -239,7 +239,7 @@ static void InitializeCPUCore(CPUCore cpu_core)
break; 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<CPUCore>& AvailableCPUCores() const std::vector<CPUCore>& AvailableCPUCores()
@ -316,7 +316,8 @@ void Shutdown()
{ {
InjectExternalCPUCore(nullptr); InjectExternalCPUCore(nullptr);
JitInterface::Shutdown(); JitInterface::Shutdown();
s_interpreter->Shutdown(); auto& interpreter = Core::System::GetInstance().GetInterpreter();
interpreter.Shutdown();
s_cpu_core_base = nullptr; s_cpu_core_base = nullptr;
} }
@ -327,17 +328,19 @@ CoreMode GetMode()
static void ApplyMode() static void ApplyMode()
{ {
auto& interpreter = Core::System::GetInstance().GetInterpreter();
switch (s_mode) switch (s_mode)
{ {
case CoreMode::Interpreter: // Switching from JIT to interpreter case CoreMode::Interpreter: // Switching from JIT to interpreter
s_cpu_core_base = s_interpreter; s_cpu_core_base = &interpreter;
break; break;
case CoreMode::JIT: // Switching from interpreter to JIT. case CoreMode::JIT: // Switching from interpreter to JIT.
// Don't really need to do much. It'll work, the cache will refill itself. // Don't really need to do much. It'll work, the cache will refill itself.
s_cpu_core_base = JitInterface::GetCore(); 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 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; break;
} }
} }

View File

@ -22,6 +22,7 @@
#include "Core/HW/SI/SI.h" #include "Core/HW/SI/SI.h"
#include "Core/HW/Sram.h" #include "Core/HW/Sram.h"
#include "Core/HW/VideoInterface.h" #include "Core/HW/VideoInterface.h"
#include "Core/PowerPC/Interpreter/Interpreter.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "IOS/USB/Emulated/Skylander.h" #include "IOS/USB/Emulated/Skylander.h"
#include "VideoCommon/CommandProcessor.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_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_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_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; Sram m_sram;
VertexShaderManager m_vertex_shader_manager; VertexShaderManager m_vertex_shader_manager;
VideoInterface::VideoInterfaceManager m_video_interface; VideoInterface::VideoInterfaceManager m_video_interface;
Interpreter m_interpreter;
}; };
System::System() : m_impl{std::make_unique<Impl>(*this)} System::System() : m_impl{std::make_unique<Impl>(*this)}
@ -175,6 +177,11 @@ HSP::HSPManager& System::GetHSP() const
return m_impl->m_hsp; return m_impl->m_hsp;
} }
Interpreter& System::GetInterpreter() const
{
return m_impl->m_interpreter;
}
IOS::HLE::USB::SkylanderPortal& System::GetSkylanderPortal() const IOS::HLE::USB::SkylanderPortal& System::GetSkylanderPortal() const
{ {
return m_impl->m_skylander_portal; return m_impl->m_skylander_portal;

View File

@ -6,6 +6,7 @@
#include <memory> #include <memory>
class GeometryShaderManager; class GeometryShaderManager;
class Interpreter;
class PixelShaderManager; class PixelShaderManager;
class SoundStream; class SoundStream;
struct Sram; struct Sram;
@ -131,6 +132,7 @@ public:
GeometryShaderManager& GetGeometryShaderManager() const; GeometryShaderManager& GetGeometryShaderManager() const;
GPFifo::GPFifoManager& GetGPFifo() const; GPFifo::GPFifoManager& GetGPFifo() const;
HSP::HSPManager& GetHSP() const; HSP::HSPManager& GetHSP() const;
Interpreter& GetInterpreter() const;
IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const; IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const;
Memory::MemoryManager& GetMemory() const; Memory::MemoryManager& GetMemory() const;
MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const; MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;