Interpreter: Avoid ppcState global (Interpreter.cpp).
This commit is contained in:
parent
3d67c11b91
commit
68ab623764
|
@ -42,26 +42,26 @@ bool IsPairedSingleInstruction(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
return inst.OPCD == 4 || IsPairedSingleQuantizedNonIndexedInstruction(inst);
|
return inst.OPCD == 4 || IsPairedSingleQuantizedNonIndexedInstruction(inst);
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// Checks if a given instruction would be illegal to execute if it's a paired single instruction.
|
// Checks if a given instruction would be illegal to execute if it's a paired single instruction.
|
||||||
//
|
//
|
||||||
// Paired single instructions are illegal to execute if HID2.PSE is not set.
|
// Paired single instructions are illegal to execute if HID2.PSE is not set.
|
||||||
// It's also illegal to execute psq_l, psq_lu, psq_st, and psq_stu if HID2.PSE is enabled,
|
// It's also illegal to execute psq_l, psq_lu, psq_st, and psq_stu if HID2.PSE is enabled,
|
||||||
// but HID2.LSQE is not set.
|
// but HID2.LSQE is not set.
|
||||||
bool IsInvalidPairedSingleExecution(UGeckoInstruction inst)
|
bool Interpreter::IsInvalidPairedSingleExecution(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (!HID2(PowerPC::ppcState).PSE && IsPairedSingleInstruction(inst))
|
if (!HID2(m_ppc_state).PSE && IsPairedSingleInstruction(inst))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return HID2(PowerPC::ppcState).PSE && !HID2(PowerPC::ppcState).LSQE &&
|
return HID2(m_ppc_state).PSE && !HID2(m_ppc_state).LSQE &&
|
||||||
IsPairedSingleQuantizedNonIndexedInstruction(inst);
|
IsPairedSingleQuantizedNonIndexedInstruction(inst);
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void Interpreter::UpdatePC()
|
void Interpreter::UpdatePC()
|
||||||
{
|
{
|
||||||
m_last_pc = PowerPC::ppcState.pc;
|
m_last_pc = m_ppc_state.pc;
|
||||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc;
|
m_ppc_state.pc = m_ppc_state.npc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state)
|
Interpreter::Interpreter(Core::System& system, PowerPC::PowerPCState& ppc_state)
|
||||||
|
@ -83,26 +83,25 @@ void Interpreter::Shutdown()
|
||||||
void Interpreter::Trace(const UGeckoInstruction& inst)
|
void Interpreter::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(m_ppc_state.gpr); i++)
|
||||||
{
|
{
|
||||||
regs += fmt::format("r{:02d}: {:08x} ", i, PowerPC::ppcState.gpr[i]);
|
regs += fmt::format("r{:02d}: {:08x} ", i, m_ppc_state.gpr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fregs;
|
std::string fregs;
|
||||||
for (size_t i = 0; i < std::size(PowerPC::ppcState.ps); i++)
|
for (size_t i = 0; i < std::size(m_ppc_state.ps); i++)
|
||||||
{
|
{
|
||||||
const auto& ps = PowerPC::ppcState.ps[i];
|
const auto& ps = m_ppc_state.ps[i];
|
||||||
fregs += fmt::format("f{:02d}: {:08x} {:08x} ", i, ps.PS0AsU64(), ps.PS1AsU64());
|
fregs += fmt::format("f{:02d}: {:08x} {:08x} ", i, ps.PS0AsU64(), ps.PS1AsU64());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string ppc_inst =
|
const std::string ppc_inst = Common::GekkoDisassembler::Disassemble(inst.hex, m_ppc_state.pc);
|
||||||
Common::GekkoDisassembler::Disassemble(inst.hex, PowerPC::ppcState.pc);
|
|
||||||
DEBUG_LOG_FMT(POWERPC,
|
DEBUG_LOG_FMT(POWERPC,
|
||||||
"INTER PC: {:08x} SRR0: {:08x} SRR1: {:08x} CRval: {:016x} "
|
"INTER PC: {:08x} SRR0: {:08x} SRR1: {:08x} CRval: {:016x} "
|
||||||
"FPSCR: {:08x} MSR: {:08x} LR: {:08x} {} {:08x} {}",
|
"FPSCR: {:08x} MSR: {:08x} LR: {:08x} {} {:08x} {}",
|
||||||
PowerPC::ppcState.pc, SRR0(PowerPC::ppcState), SRR1(PowerPC::ppcState),
|
m_ppc_state.pc, SRR0(m_ppc_state), SRR1(m_ppc_state), m_ppc_state.cr.fields[0],
|
||||||
PowerPC::ppcState.cr.fields[0], PowerPC::ppcState.fpscr.Hex,
|
m_ppc_state.fpscr.Hex, m_ppc_state.msr.Hex, m_ppc_state.spr[8], regs, inst.hex,
|
||||||
PowerPC::ppcState.msr.Hex, PowerPC::ppcState.spr[8], regs, inst.hex, ppc_inst);
|
ppc_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interpreter::HandleFunctionHooking(u32 address)
|
bool Interpreter::HandleFunctionHooking(u32 address)
|
||||||
|
@ -115,7 +114,7 @@ bool Interpreter::HandleFunctionHooking(u32 address)
|
||||||
|
|
||||||
int Interpreter::SingleStepInner()
|
int Interpreter::SingleStepInner()
|
||||||
{
|
{
|
||||||
if (HandleFunctionHooking(PowerPC::ppcState.pc))
|
if (HandleFunctionHooking(m_ppc_state.pc))
|
||||||
{
|
{
|
||||||
UpdatePC();
|
UpdatePC();
|
||||||
// TODO: Does it make sense to use m_prev_inst here?
|
// TODO: Does it make sense to use m_prev_inst here?
|
||||||
|
@ -124,14 +123,14 @@ int Interpreter::SingleStepInner()
|
||||||
return PPCTables::GetOpInfo(m_prev_inst)->num_cycles;
|
return PPCTables::GetOpInfo(m_prev_inst)->num_cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::ppcState.npc = PowerPC::ppcState.pc + sizeof(UGeckoInstruction);
|
m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction);
|
||||||
m_prev_inst.hex = PowerPC::Read_Opcode(PowerPC::ppcState.pc);
|
m_prev_inst.hex = PowerPC::Read_Opcode(m_ppc_state.pc);
|
||||||
|
|
||||||
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
|
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
|
||||||
|
|
||||||
// Uncomment to trace the interpreter
|
// Uncomment to trace the interpreter
|
||||||
// if ((PowerPC::ppcState.pc & 0x00FFFFFF) >= 0x000AB54C &&
|
// if ((m_ppc_state.pc & 0x00FFFFFF) >= 0x000AB54C &&
|
||||||
// (PowerPC::ppcState.pc & 0x00FFFFFF) <= 0x000AB624)
|
// (m_ppc_state.pc & 0x00FFFFFF) <= 0x000AB624)
|
||||||
// {
|
// {
|
||||||
// m_start_trace = true;
|
// m_start_trace = true;
|
||||||
// }
|
// }
|
||||||
|
@ -152,10 +151,10 @@ int Interpreter::SingleStepInner()
|
||||||
GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
|
GenerateProgramException(ProgramExceptionCause::IllegalInstruction);
|
||||||
CheckExceptions();
|
CheckExceptions();
|
||||||
}
|
}
|
||||||
else if (PowerPC::ppcState.msr.FP)
|
else if (m_ppc_state.msr.FP)
|
||||||
{
|
{
|
||||||
RunInterpreterOp(*this, m_prev_inst);
|
RunInterpreterOp(*this, m_prev_inst);
|
||||||
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
|
if ((m_ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
CheckExceptions();
|
CheckExceptions();
|
||||||
}
|
}
|
||||||
|
@ -165,13 +164,13 @@ int Interpreter::SingleStepInner()
|
||||||
// check if we have to generate a FPU unavailable exception or a program exception.
|
// check if we have to generate a FPU unavailable exception or a program exception.
|
||||||
if ((opinfo->flags & FL_USE_FPU) != 0)
|
if ((opinfo->flags & FL_USE_FPU) != 0)
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
m_ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
||||||
CheckExceptions();
|
CheckExceptions();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RunInterpreterOp(*this, m_prev_inst);
|
RunInterpreterOp(*this, m_prev_inst);
|
||||||
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
|
if ((m_ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
CheckExceptions();
|
CheckExceptions();
|
||||||
}
|
}
|
||||||
|
@ -187,13 +186,13 @@ int Interpreter::SingleStepInner()
|
||||||
UpdatePC();
|
UpdatePC();
|
||||||
|
|
||||||
PowerPC::UpdatePerformanceMonitor(opinfo->num_cycles, (opinfo->flags & FL_LOADSTORE) != 0,
|
PowerPC::UpdatePerformanceMonitor(opinfo->num_cycles, (opinfo->flags & FL_LOADSTORE) != 0,
|
||||||
(opinfo->flags & FL_USE_FPU) != 0, PowerPC::ppcState);
|
(opinfo->flags & FL_USE_FPU) != 0, m_ppc_state);
|
||||||
return opinfo->num_cycles;
|
return opinfo->num_cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::SingleStep()
|
void Interpreter::SingleStep()
|
||||||
{
|
{
|
||||||
auto& core_timing = Core::System::GetInstance().GetCoreTiming();
|
auto& core_timing = m_system.GetCoreTiming();
|
||||||
auto& core_timing_globals = core_timing.GetGlobals();
|
auto& core_timing_globals = core_timing.GetGlobals();
|
||||||
|
|
||||||
// Declare start of new slice
|
// Declare start of new slice
|
||||||
|
@ -203,12 +202,12 @@ void Interpreter::SingleStep()
|
||||||
|
|
||||||
// The interpreter ignores instruction timing information outside the 'fast runloop'.
|
// The interpreter ignores instruction timing information outside the 'fast runloop'.
|
||||||
core_timing_globals.slice_length = 1;
|
core_timing_globals.slice_length = 1;
|
||||||
PowerPC::ppcState.downcount = 0;
|
m_ppc_state.downcount = 0;
|
||||||
|
|
||||||
if (PowerPC::ppcState.Exceptions != 0)
|
if (m_ppc_state.Exceptions != 0)
|
||||||
{
|
{
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc;
|
m_ppc_state.pc = m_ppc_state.npc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,9 +222,8 @@ constexpr u32 s_show_steps = 300;
|
||||||
// FastRun - inspired by GCemu (to imitate the JIT so that they can be compared).
|
// FastRun - inspired by GCemu (to imitate the JIT so that they can be compared).
|
||||||
void Interpreter::Run()
|
void Interpreter::Run()
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& core_timing = m_system.GetCoreTiming();
|
||||||
auto& core_timing = system.GetCoreTiming();
|
auto& cpu = m_system.GetCPU();
|
||||||
auto& cpu = system.GetCPU();
|
|
||||||
while (cpu.GetState() == CPU::State::Running)
|
while (cpu.GetState() == CPU::State::Running)
|
||||||
{
|
{
|
||||||
// CoreTiming Advance() ends the previous slice and declares the start of the next
|
// CoreTiming Advance() ends the previous slice and declares the start of the next
|
||||||
|
@ -237,27 +235,27 @@ void Interpreter::Run()
|
||||||
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
|
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
|
||||||
{
|
{
|
||||||
#ifdef SHOW_HISTORY
|
#ifdef SHOW_HISTORY
|
||||||
s_pc_block_vec.push_back(PowerPC::ppcState.pc);
|
s_pc_block_vec.push_back(m_ppc_state.pc);
|
||||||
if (s_pc_block_vec.size() > s_show_blocks)
|
if (s_pc_block_vec.size() > s_show_blocks)
|
||||||
s_pc_block_vec.erase(s_pc_block_vec.begin());
|
s_pc_block_vec.erase(s_pc_block_vec.begin());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Debugging friendly version of inner loop. Tries to do the timing as similarly to the
|
// Debugging friendly version of inner loop. Tries to do the timing as similarly to the
|
||||||
// JIT as possible. Does not take into account that some instructions take multiple cycles.
|
// JIT as possible. Does not take into account that some instructions take multiple cycles.
|
||||||
while (PowerPC::ppcState.downcount > 0)
|
while (m_ppc_state.downcount > 0)
|
||||||
{
|
{
|
||||||
m_end_block = false;
|
m_end_block = false;
|
||||||
int cycles = 0;
|
int cycles = 0;
|
||||||
while (!m_end_block)
|
while (!m_end_block)
|
||||||
{
|
{
|
||||||
#ifdef SHOW_HISTORY
|
#ifdef SHOW_HISTORY
|
||||||
s_pc_vec.push_back(PowerPC::ppcState.pc);
|
s_pc_vec.push_back(m_ppc_state.pc);
|
||||||
if (s_pc_vec.size() > s_show_steps)
|
if (s_pc_vec.size() > s_show_steps)
|
||||||
s_pc_vec.erase(s_pc_vec.begin());
|
s_pc_vec.erase(s_pc_vec.begin());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 2: check for breakpoint
|
// 2: check for breakpoint
|
||||||
if (PowerPC::breakpoints.IsAddressBreakPoint(PowerPC::ppcState.pc))
|
if (PowerPC::breakpoints.IsAddressBreakPoint(m_ppc_state.pc))
|
||||||
{
|
{
|
||||||
#ifdef SHOW_HISTORY
|
#ifdef SHOW_HISTORY
|
||||||
NOTICE_LOG_FMT(POWERPC, "----------------------------");
|
NOTICE_LOG_FMT(POWERPC, "----------------------------");
|
||||||
|
@ -278,25 +276,25 @@ void Interpreter::Run()
|
||||||
NOTICE_LOG_FMT(POWERPC, "PC: {:#010x}", s_pc_vec[j]);
|
NOTICE_LOG_FMT(POWERPC, "PC: {:#010x}", s_pc_vec[j]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
INFO_LOG_FMT(POWERPC, "Hit Breakpoint - {:08x}", PowerPC::ppcState.pc);
|
INFO_LOG_FMT(POWERPC, "Hit Breakpoint - {:08x}", m_ppc_state.pc);
|
||||||
cpu.Break();
|
cpu.Break();
|
||||||
if (GDBStub::IsActive())
|
if (GDBStub::IsActive())
|
||||||
GDBStub::TakeControl();
|
GDBStub::TakeControl();
|
||||||
if (PowerPC::breakpoints.IsTempBreakPoint(PowerPC::ppcState.pc))
|
if (PowerPC::breakpoints.IsTempBreakPoint(m_ppc_state.pc))
|
||||||
PowerPC::breakpoints.Remove(PowerPC::ppcState.pc);
|
PowerPC::breakpoints.Remove(m_ppc_state.pc);
|
||||||
|
|
||||||
Host_UpdateDisasmDialog();
|
Host_UpdateDisasmDialog();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cycles += SingleStepInner();
|
cycles += SingleStepInner();
|
||||||
}
|
}
|
||||||
PowerPC::ppcState.downcount -= cycles;
|
m_ppc_state.downcount -= cycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// "fast" version of inner loop. well, it's not so fast.
|
// "fast" version of inner loop. well, it's not so fast.
|
||||||
while (PowerPC::ppcState.downcount > 0)
|
while (m_ppc_state.downcount > 0)
|
||||||
{
|
{
|
||||||
m_end_block = false;
|
m_end_block = false;
|
||||||
|
|
||||||
|
@ -305,7 +303,7 @@ void Interpreter::Run()
|
||||||
{
|
{
|
||||||
cycles += SingleStepInner();
|
cycles += SingleStepInner();
|
||||||
}
|
}
|
||||||
PowerPC::ppcState.downcount -= cycles;
|
m_ppc_state.downcount -= cycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,7 +312,7 @@ void Interpreter::Run()
|
||||||
void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstruction inst)
|
void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
ASSERT(Core::IsCPUThread());
|
ASSERT(Core::IsCPUThread());
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = interpreter.m_system;
|
||||||
Core::CPUThreadGuard guard(system);
|
Core::CPUThreadGuard guard(system);
|
||||||
|
|
||||||
const u32 last_pc = interpreter.m_last_pc;
|
const u32 last_pc = interpreter.m_last_pc;
|
||||||
|
@ -323,19 +321,21 @@ void Interpreter::unknown_instruction(Interpreter& interpreter, UGeckoInstructio
|
||||||
NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm);
|
NOTICE_LOG_FMT(POWERPC, "Last PC = {:08x} : {}", last_pc, disasm);
|
||||||
Dolphin_Debugger::PrintCallstack(system, guard, Common::Log::LogType::POWERPC,
|
Dolphin_Debugger::PrintCallstack(system, guard, Common::Log::LogType::POWERPC,
|
||||||
Common::Log::LogLevel::LNOTICE);
|
Common::Log::LogLevel::LNOTICE);
|
||||||
|
|
||||||
|
const auto& ppc_state = interpreter.m_ppc_state;
|
||||||
NOTICE_LOG_FMT(
|
NOTICE_LOG_FMT(
|
||||||
POWERPC,
|
POWERPC,
|
||||||
"\nIntCPU: Unknown instruction {:08x} at PC = {:08x} last_PC = {:08x} LR = {:08x}\n",
|
"\nIntCPU: Unknown instruction {:08x} at PC = {:08x} last_PC = {:08x} LR = {:08x}\n",
|
||||||
inst.hex, PowerPC::ppcState.pc, last_pc, LR(PowerPC::ppcState));
|
inst.hex, ppc_state.pc, last_pc, LR(ppc_state));
|
||||||
for (int i = 0; i < 32; i += 4)
|
for (int i = 0; i < 32; i += 4)
|
||||||
{
|
{
|
||||||
NOTICE_LOG_FMT(POWERPC, "r{}: {:#010x} r{}: {:#010x} r{}: {:#010x} r{}: {:#010x}", i,
|
NOTICE_LOG_FMT(POWERPC, "r{}: {:#010x} r{}: {:#010x} r{}: {:#010x} r{}: {:#010x}", i,
|
||||||
PowerPC::ppcState.gpr[i], i + 1, PowerPC::ppcState.gpr[i + 1], i + 2,
|
ppc_state.gpr[i], i + 1, ppc_state.gpr[i + 1], i + 2, ppc_state.gpr[i + 2],
|
||||||
PowerPC::ppcState.gpr[i + 2], i + 3, PowerPC::ppcState.gpr[i + 3]);
|
i + 3, ppc_state.gpr[i + 3]);
|
||||||
}
|
}
|
||||||
ASSERT_MSG(POWERPC, 0,
|
ASSERT_MSG(POWERPC, 0,
|
||||||
"\nIntCPU: Unknown instruction {:08x} at PC = {:08x} last_PC = {:08x} LR = {:08x}\n",
|
"\nIntCPU: Unknown instruction {:08x} at PC = {:08x} last_PC = {:08x} LR = {:08x}\n",
|
||||||
inst.hex, PowerPC::ppcState.pc, last_pc, LR(PowerPC::ppcState));
|
inst.hex, ppc_state.pc, last_pc, LR(ppc_state));
|
||||||
if (system.IsPauseOnPanicMode())
|
if (system.IsPauseOnPanicMode())
|
||||||
system.GetCPU().Break();
|
system.GetCPU().Break();
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,6 +304,7 @@ private:
|
||||||
static void Helper_FloatCompareUnordered(UGeckoInstruction inst, double a, double b);
|
static void Helper_FloatCompareUnordered(UGeckoInstruction inst, double a, double b);
|
||||||
|
|
||||||
void UpdatePC();
|
void UpdatePC();
|
||||||
|
bool IsInvalidPairedSingleExecution(UGeckoInstruction inst);
|
||||||
|
|
||||||
void Trace(const UGeckoInstruction& inst);
|
void Trace(const UGeckoInstruction& inst);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue