diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index 0a03329096..d3e766450f 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -380,6 +380,7 @@ void Idle() Fifo::FlushGpu(); } + PowerPC::UpdatePerformanceMonitor(PowerPC::ppcState.downcount, 0, 0); s_idled_cycles += DowncountToCycles(PowerPC::ppcState.downcount); PowerPC::ppcState.downcount = 0; } diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index eea5b63988..17b91a6627 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -134,6 +134,17 @@ static void EndBlock(UGeckoInstruction data) { PC = NPC; PowerPC::ppcState.downcount -= data.hex; + PowerPC::UpdatePerformanceMonitor(data.hex, 0, 0); +} + +static void UpdateNumLoadStoreInstructions(UGeckoInstruction data) +{ + PowerPC::UpdatePerformanceMonitor(0, data.hex, 0); +} + +static void UpdateNumFloatingPointInstructions(UGeckoInstruction data) +{ + PowerPC::UpdatePerformanceMonitor(0, 0, data.hex); } static void WritePC(UGeckoInstruction data) @@ -230,6 +241,8 @@ void CachedInterpreter::Jit(u32 address) js.firstFPInstructionFound = false; js.fifoBytesSinceCheck = 0; js.downcountAmount = 0; + js.numLoadStoreInst = 0; + js.numFloatingPointInst = 0; js.curBlock = b; b->checkedEntry = GetCodePtr(); @@ -240,6 +253,10 @@ void CachedInterpreter::Jit(u32 address) PPCAnalyst::CodeOp& op = m_code_buffer[i]; js.downcountAmount += op.opinfo->numCycles; + if (op.opinfo->flags & FL_LOADSTORE) + ++js.numLoadStoreInst; + if (op.opinfo->flags & FL_USE_FPU) + ++js.numFloatingPointInst; if (HandleFunctionHooking(op.address)) break; @@ -274,13 +291,19 @@ void CachedInterpreter::Jit(u32 address) if (idle_loop) m_code.emplace_back(CheckIdle, js.blockStart); if (endblock) + { m_code.emplace_back(EndBlock, js.downcountAmount); + m_code.emplace_back(UpdateNumLoadStoreInstructions, js.numLoadStoreInst); + m_code.emplace_back(UpdateNumFloatingPointInstructions, js.numFloatingPointInst); + } } } if (code_block.m_broken) { m_code.emplace_back(WriteBrokenBlockNPC, nextPC); m_code.emplace_back(EndBlock, js.downcountAmount); + m_code.emplace_back(UpdateNumLoadStoreInstructions, js.numLoadStoreInst); + m_code.emplace_back(UpdateNumFloatingPointInstructions, js.numFloatingPointInst); } m_code.emplace_back(); diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 6702fb798c..8835945416 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -219,7 +219,11 @@ int Interpreter::SingleStepInner() } UpdatePC(); - return PPCTables::GetOpInfo(m_prev_inst)->numCycles; + + const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst); + PowerPC::UpdatePerformanceMonitor(opinfo->numCycles, (opinfo->flags & FL_LOADSTORE) != 0, + (opinfo->flags & FL_USE_FPU) != 0); + return opinfo->numCycles; } void Interpreter::SingleStep() diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 43b9462600..38e6ae8ed3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -244,6 +244,16 @@ void JitArm64::Cleanup() BLR(X0); SetJumpTarget(exit); } + + // SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time. + if (MMCR0.Hex || MMCR1.Hex) + { + MOVP2R(X30, &PowerPC::UpdatePerformanceMonitor); + MOVI2R(X0, js.downcountAmount); + MOVI2R(X1, js.numLoadStoreInst); + MOVI2R(X2, js.numFloatingPointInst); + BLR(X30); + } } void JitArm64::DoDownCount() @@ -620,6 +630,8 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) js.skipInstructions = 0; js.curBlock = b; js.carryFlagSet = false; + js.numLoadStoreInst = 0; + js.numFloatingPointInst = 0; u8* const start = GetWritableCodePtr(); b->checkedEntry = start; @@ -807,6 +819,12 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) // If we have a register that will never be used again, flush it. gpr.StoreRegisters(~op.gprInUse); fpr.StoreRegisters(~op.fprInUse); + + if (opinfo->flags & FL_LOADSTORE) + ++js.numLoadStoreInst; + + if (opinfo->flags & FL_USE_FPU) + ++js.numFloatingPointInst; } i += js.skipInstructions;