mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-12 23:48:58 +01:00
CachedInterpreter: WritePC optimizations
WritePC is now needed far less, only for instructions that end the block. Unfortunately, WritePC still needs to update `PowerPCState::npc` to support the false path of conditional branch instructions. Both drawbacks should be smoothed over by optimized cached instructions in the future.
This commit is contained in:
parent
0282fa7adb
commit
818647d694
@ -110,6 +110,7 @@ s32 CachedInterpreter::HLEFunction(PowerPC::PowerPCState& ppc_state,
|
|||||||
const HLEFunctionOperands& operands)
|
const HLEFunctionOperands& operands)
|
||||||
{
|
{
|
||||||
const auto& [system, current_pc, hook_index] = operands;
|
const auto& [system, current_pc, hook_index] = operands;
|
||||||
|
ppc_state.pc = current_pc;
|
||||||
HLE::Execute(Core::CPUThreadGuard{system}, current_pc, hook_index);
|
HLE::Execute(Core::CPUThreadGuard{system}, current_pc, hook_index);
|
||||||
return sizeof(AnyCallback) + sizeof(operands);
|
return sizeof(AnyCallback) + sizeof(operands);
|
||||||
}
|
}
|
||||||
@ -132,9 +133,10 @@ s32 CachedInterpreter::WriteBrokenBlockNPC(PowerPC::PowerPCState& ppc_state,
|
|||||||
|
|
||||||
s32 CachedInterpreter::CheckFPU(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands)
|
s32 CachedInterpreter::CheckFPU(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands)
|
||||||
{
|
{
|
||||||
const auto& [power_pc, downcount] = operands;
|
const auto& [power_pc, current_pc, downcount] = operands;
|
||||||
if (!ppc_state.msr.FP)
|
if (!ppc_state.msr.FP)
|
||||||
{
|
{
|
||||||
|
ppc_state.pc = current_pc;
|
||||||
ppc_state.downcount -= downcount;
|
ppc_state.downcount -= downcount;
|
||||||
ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
||||||
power_pc.CheckExceptions();
|
power_pc.CheckExceptions();
|
||||||
@ -145,9 +147,10 @@ s32 CachedInterpreter::CheckFPU(PowerPC::PowerPCState& ppc_state, const CheckHal
|
|||||||
|
|
||||||
s32 CachedInterpreter::CheckDSI(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands)
|
s32 CachedInterpreter::CheckDSI(PowerPC::PowerPCState& ppc_state, const CheckHaltOperands& operands)
|
||||||
{
|
{
|
||||||
const auto& [power_pc, downcount] = operands;
|
const auto& [power_pc, current_pc, downcount] = operands;
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_DSI) != 0)
|
||||||
{
|
{
|
||||||
|
ppc_state.pc = current_pc;
|
||||||
ppc_state.downcount -= downcount;
|
ppc_state.downcount -= downcount;
|
||||||
power_pc.CheckExceptions();
|
power_pc.CheckExceptions();
|
||||||
return 0;
|
return 0;
|
||||||
@ -158,9 +161,10 @@ s32 CachedInterpreter::CheckDSI(PowerPC::PowerPCState& ppc_state, const CheckHal
|
|||||||
s32 CachedInterpreter::CheckProgramException(PowerPC::PowerPCState& ppc_state,
|
s32 CachedInterpreter::CheckProgramException(PowerPC::PowerPCState& ppc_state,
|
||||||
const CheckHaltOperands& operands)
|
const CheckHaltOperands& operands)
|
||||||
{
|
{
|
||||||
const auto& [power_pc, downcount] = operands;
|
const auto& [power_pc, current_pc, downcount] = operands;
|
||||||
if ((ppc_state.Exceptions & EXCEPTION_PROGRAM) != 0)
|
if ((ppc_state.Exceptions & EXCEPTION_PROGRAM) != 0)
|
||||||
{
|
{
|
||||||
|
ppc_state.pc = current_pc;
|
||||||
ppc_state.downcount -= downcount;
|
ppc_state.downcount -= downcount;
|
||||||
power_pc.CheckExceptions();
|
power_pc.CheckExceptions();
|
||||||
return 0;
|
return 0;
|
||||||
@ -171,7 +175,8 @@ s32 CachedInterpreter::CheckProgramException(PowerPC::PowerPCState& ppc_state,
|
|||||||
s32 CachedInterpreter::CheckBreakpoint(PowerPC::PowerPCState& ppc_state,
|
s32 CachedInterpreter::CheckBreakpoint(PowerPC::PowerPCState& ppc_state,
|
||||||
const CheckHaltOperands& operands)
|
const CheckHaltOperands& operands)
|
||||||
{
|
{
|
||||||
const auto& [power_pc, downcount] = operands;
|
const auto& [power_pc, current_pc, downcount] = operands;
|
||||||
|
ppc_state.pc = current_pc;
|
||||||
if (power_pc.CheckAndHandleBreakPoints())
|
if (power_pc.CheckAndHandleBreakPoints())
|
||||||
{
|
{
|
||||||
// Accessing PowerPCState through power_pc instead of ppc_state produces better assembly.
|
// Accessing PowerPCState through power_pc instead of ppc_state produces better assembly.
|
||||||
@ -198,7 +203,6 @@ bool CachedInterpreter::HandleFunctionHooking(u32 address)
|
|||||||
if (!result)
|
if (!result)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Write(WritePC, {address});
|
|
||||||
Write(HLEFunction, {m_system, address, result.hook_index});
|
Write(HLEFunction, {m_system, address, result.hook_index});
|
||||||
|
|
||||||
if (result.type != HLE::HookType::Replace)
|
if (result.type != HLE::HookType::Replace)
|
||||||
@ -329,33 +333,27 @@ bool CachedInterpreter::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||||||
|
|
||||||
if (!op.skip)
|
if (!op.skip)
|
||||||
{
|
{
|
||||||
const bool breakpoint = IsDebuggingEnabled() && !cpu.IsStepping() &&
|
if (IsDebuggingEnabled() && !cpu.IsStepping() &&
|
||||||
breakpoints.IsAddressBreakPoint(js.compilerPC);
|
breakpoints.IsAddressBreakPoint(js.compilerPC))
|
||||||
const bool check_fpu = (op.opinfo->flags & FL_USE_FPU) != 0 && !js.firstFPInstructionFound;
|
|
||||||
const bool endblock = (op.opinfo->flags & FL_ENDBLOCK) != 0;
|
|
||||||
const bool memcheck = (op.opinfo->flags & FL_LOADSTORE) != 0 && jo.memcheck;
|
|
||||||
const bool check_program_exception = !endblock && ShouldHandleFPExceptionForInstruction(&op);
|
|
||||||
const bool idle_loop = op.branchIsIdleLoop;
|
|
||||||
|
|
||||||
if (breakpoint || check_fpu || endblock || memcheck || check_program_exception)
|
|
||||||
Write(WritePC, {js.compilerPC});
|
|
||||||
|
|
||||||
if (breakpoint)
|
|
||||||
Write(CheckBreakpoint, {power_pc, js.downcountAmount});
|
|
||||||
|
|
||||||
if (check_fpu)
|
|
||||||
{
|
{
|
||||||
Write(CheckFPU, {power_pc, js.downcountAmount});
|
Write(CheckBreakpoint, {power_pc, js.compilerPC, js.downcountAmount});
|
||||||
|
}
|
||||||
|
if (!js.firstFPInstructionFound && (op.opinfo->flags & FL_USE_FPU) != 0)
|
||||||
|
{
|
||||||
|
Write(CheckFPU, {power_pc, js.compilerPC, js.downcountAmount});
|
||||||
js.firstFPInstructionFound = true;
|
js.firstFPInstructionFound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool endblock = (op.opinfo->flags & FL_ENDBLOCK) != 0;
|
||||||
|
if (endblock)
|
||||||
|
Write(WritePC, {js.compilerPC});
|
||||||
Write(Interpret,
|
Write(Interpret,
|
||||||
{interpreter, Interpreter::GetInterpreterOp(op.inst), js.compilerPC, op.inst});
|
{interpreter, Interpreter::GetInterpreterOp(op.inst), js.compilerPC, op.inst});
|
||||||
if (memcheck)
|
if (jo.memcheck && (op.opinfo->flags & FL_LOADSTORE) != 0)
|
||||||
Write(CheckDSI, {power_pc, js.downcountAmount});
|
Write(CheckDSI, {power_pc, js.compilerPC, js.downcountAmount});
|
||||||
if (check_program_exception)
|
if (!endblock && ShouldHandleFPExceptionForInstruction(&op))
|
||||||
Write(CheckProgramException, {power_pc, js.downcountAmount});
|
Write(CheckProgramException, {power_pc, js.compilerPC, js.downcountAmount});
|
||||||
if (idle_loop)
|
if (op.branchIsIdleLoop)
|
||||||
Write(CheckIdle, {m_system.GetCoreTiming(), js.blockStart});
|
Write(CheckIdle, {m_system.GetCoreTiming(), js.blockStart});
|
||||||
if (endblock)
|
if (endblock)
|
||||||
Write(EndBlock, {js.downcountAmount, js.numLoadStoreInst, js.numFloatingPointInst});
|
Write(EndBlock, {js.downcountAmount, js.numLoadStoreInst, js.numFloatingPointInst});
|
||||||
|
@ -117,6 +117,7 @@ struct CachedInterpreter::WritePCOperands
|
|||||||
struct CachedInterpreter::CheckHaltOperands
|
struct CachedInterpreter::CheckHaltOperands
|
||||||
{
|
{
|
||||||
PowerPC::PowerPCManager& power_pc;
|
PowerPC::PowerPCManager& power_pc;
|
||||||
|
u32 current_pc;
|
||||||
u32 downcount;
|
u32 downcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user