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;
case Instruction::Type::Interpreter:
code->interpreter_callback(*Interpreter::getInstance(), UGeckoInstruction(code->data));
code->interpreter_callback(Core::System::GetInstance().GetInterpreter(),
UGeckoInstruction(code->data));
break;
default:

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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.

View File

@ -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,

View File

@ -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);

View File

@ -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<CPUCore>& 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;
}
}

View File

@ -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<Impl>(*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;

View File

@ -6,6 +6,7 @@
#include <memory>
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;