mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
CachedInterpreter: Avoid System::GetInstance() and ppcState.
This commit is contained in:
parent
9c0226b7e3
commit
dfc14db313
@ -20,6 +20,8 @@ struct CachedInterpreter::Instruction
|
|||||||
using CommonCallback = void (*)(UGeckoInstruction);
|
using CommonCallback = void (*)(UGeckoInstruction);
|
||||||
using ConditionalCallback = bool (*)(u32);
|
using ConditionalCallback = bool (*)(u32);
|
||||||
using InterpreterCallback = void (*)(Interpreter&, UGeckoInstruction);
|
using InterpreterCallback = void (*)(Interpreter&, UGeckoInstruction);
|
||||||
|
using CachedInterpreterCallback = void (*)(CachedInterpreter&, UGeckoInstruction);
|
||||||
|
using ConditionalCachedInterpreterCallback = bool (*)(CachedInterpreter&, u32);
|
||||||
|
|
||||||
Instruction() {}
|
Instruction() {}
|
||||||
Instruction(const CommonCallback c, UGeckoInstruction i)
|
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
|
enum class Type
|
||||||
{
|
{
|
||||||
Abort,
|
Abort,
|
||||||
Common,
|
Common,
|
||||||
Conditional,
|
Conditional,
|
||||||
Interpreter,
|
Interpreter,
|
||||||
|
CachedInterpreter,
|
||||||
|
ConditionalCachedInterpreter,
|
||||||
};
|
};
|
||||||
|
|
||||||
union
|
union
|
||||||
@ -50,6 +65,8 @@ struct CachedInterpreter::Instruction
|
|||||||
const CommonCallback common_callback = nullptr;
|
const CommonCallback common_callback = nullptr;
|
||||||
const ConditionalCallback conditional_callback;
|
const ConditionalCallback conditional_callback;
|
||||||
const InterpreterCallback interpreter_callback;
|
const InterpreterCallback interpreter_callback;
|
||||||
|
const CachedInterpreterCallback cached_interpreter_callback;
|
||||||
|
const ConditionalCachedInterpreterCallback conditional_cached_interpreter_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 data = 0;
|
u32 data = 0;
|
||||||
@ -91,11 +108,12 @@ void CachedInterpreter::ExecuteOneBlock()
|
|||||||
const u8* normal_entry = m_block_cache.Dispatch();
|
const u8* normal_entry = m_block_cache.Dispatch();
|
||||||
if (!normal_entry)
|
if (!normal_entry)
|
||||||
{
|
{
|
||||||
Jit(PowerPC::ppcState.pc);
|
Jit(m_ppc_state.pc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry);
|
const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry);
|
||||||
|
auto& interpreter = m_system.GetInterpreter();
|
||||||
|
|
||||||
for (; code->type != Instruction::Type::Abort; ++code)
|
for (; code->type != Instruction::Type::Abort; ++code)
|
||||||
{
|
{
|
||||||
@ -111,8 +129,16 @@ void CachedInterpreter::ExecuteOneBlock()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Instruction::Type::Interpreter:
|
case Instruction::Type::Interpreter:
|
||||||
code->interpreter_callback(Core::System::GetInstance().GetInterpreter(),
|
code->interpreter_callback(interpreter, UGeckoInstruction(code->data));
|
||||||
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -125,9 +151,8 @@ void CachedInterpreter::ExecuteOneBlock()
|
|||||||
|
|
||||||
void CachedInterpreter::Run()
|
void CachedInterpreter::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();
|
|
||||||
|
|
||||||
const CPU::State* state_ptr = cpu.GetStatePtr();
|
const CPU::State* state_ptr = cpu.GetStatePtr();
|
||||||
while (cpu.GetState() == CPU::State::Running)
|
while (cpu.GetState() == CPU::State::Running)
|
||||||
@ -139,96 +164,103 @@ void CachedInterpreter::Run()
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
ExecuteOneBlock();
|
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()
|
void CachedInterpreter::SingleStep()
|
||||||
{
|
{
|
||||||
// Enter new timing slice
|
// Enter new timing slice
|
||||||
Core::System::GetInstance().GetCoreTiming().Advance();
|
m_system.GetCoreTiming().Advance();
|
||||||
ExecuteOneBlock();
|
ExecuteOneBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EndBlock(UGeckoInstruction data)
|
void CachedInterpreter::EndBlock(CachedInterpreter& cached_interpreter, UGeckoInstruction data)
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc;
|
auto& ppc_state = cached_interpreter.m_ppc_state;
|
||||||
PowerPC::ppcState.downcount -= data.hex;
|
ppc_state.pc = ppc_state.npc;
|
||||||
PowerPC::UpdatePerformanceMonitor(data.hex, 0, 0, PowerPC::ppcState);
|
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;
|
auto& ppc_state = cached_interpreter.m_ppc_state;
|
||||||
PowerPC::ppcState.npc = data.hex + 4;
|
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::CheckExceptions();
|
||||||
PowerPC::ppcState.downcount -= data;
|
ppc_state.downcount -= data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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::CheckExceptions();
|
||||||
PowerPC::ppcState.downcount -= data;
|
ppc_state.downcount -= data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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::CheckExceptions();
|
||||||
PowerPC::ppcState.downcount -= data;
|
ppc_state.downcount -= data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckBreakpoint(u32 data)
|
bool CachedInterpreter::CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data)
|
||||||
{
|
{
|
||||||
PowerPC::CheckBreakPoints();
|
PowerPC::CheckBreakPoints();
|
||||||
auto& system = Core::System::GetInstance();
|
if (cached_interpreter.m_system.GetCPU().GetState() != CPU::State::Running)
|
||||||
if (system.GetCPU().GetState() != CPU::State::Running)
|
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.downcount -= data;
|
cached_interpreter.m_ppc_state.downcount -= data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -257,20 +289,20 @@ void CachedInterpreter::Jit(u32 address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const u32 nextPC =
|
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)
|
if (code_block.m_memory_exception)
|
||||||
{
|
{
|
||||||
// Address of instruction could not be translated
|
// Address of instruction could not be translated
|
||||||
PowerPC::ppcState.npc = nextPC;
|
m_ppc_state.npc = nextPC;
|
||||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
|
m_ppc_state.Exceptions |= EXCEPTION_ISI;
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
|
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
|
||||||
return;
|
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.firstFPInstructionFound = false;
|
||||||
js.fifoBytesSinceCheck = 0;
|
js.fifoBytesSinceCheck = 0;
|
||||||
js.downcountAmount = 0;
|
js.downcountAmount = 0;
|
||||||
|
@ -43,6 +43,19 @@ private:
|
|||||||
|
|
||||||
bool HandleFunctionHooking(u32 address);
|
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};
|
BlockCache m_block_cache{*this};
|
||||||
std::vector<Instruction> m_code;
|
std::vector<Instruction> m_code;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user