diff --git a/Source/Core/Common/BreakPoints.cpp b/Source/Core/Common/BreakPoints.cpp index db0cedf0bb..6014eae776 100644 --- a/Source/Core/Common/BreakPoints.cpp +++ b/Source/Core/Common/BreakPoints.cpp @@ -113,6 +113,19 @@ void BreakPoints::Clear() m_BreakPoints.clear(); } +void BreakPoints::ClearAllTemporary() +{ + for (const TBreakPoint& bp : m_BreakPoints) + { + if (bp.bTemporary) + { + if (jit) + jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4, true); + Remove(bp.iAddress); + } + } +} + MemChecks::TMemChecksStr MemChecks::GetStrings() const { TMemChecksStr mcs; diff --git a/Source/Core/Common/BreakPoints.h b/Source/Core/Common/BreakPoints.h index 99ea0809ca..3d656b12e8 100644 --- a/Source/Core/Common/BreakPoints.h +++ b/Source/Core/Common/BreakPoints.h @@ -67,6 +67,7 @@ public: // Remove Breakpoint void Remove(u32 _iAddress); void Clear(); + void ClearAllTemporary(); void DeleteByAddress(u32 _Address); diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 0480677831..ebd5a7d7db 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -161,6 +161,9 @@ void Init(int cpu_core) state = CPU_STEPPING; ppcState.iCache.Init(); + + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) + breakpoints.ClearAllTemporary(); } void Shutdown() diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp index f10421e860..c6ad04e8b7 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp @@ -37,6 +37,7 @@ #include "Core/Debugger/PPCDebugInterface.h" #include "Core/HW/CPU.h" #include "Core/HW/Memmap.h" +#include "Core/HW/SystemTimers.h" #include "Core/PowerPC/Gekko.h" #include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/PowerPC.h" @@ -292,6 +293,7 @@ void CCodeWindow::SingleStep() { if (CCPU::IsStepping()) { + PowerPC::breakpoints.ClearAllTemporary(); JitInterface::InvalidateICache(PC, 4, true); CCPU::StepOpcode(&sync_event); wxThread::Sleep(20); @@ -305,6 +307,7 @@ void CCodeWindow::StepOver() { if (CCPU::IsStepping()) { + PowerPC::breakpoints.ClearAllTemporary(); UGeckoInstruction inst = Memory::Read_Instruction(PC); if (inst.LK) { @@ -328,8 +331,39 @@ void CCodeWindow::StepOut() { if (CCPU::IsStepping()) { - PowerPC::breakpoints.Add(LR, true); - CCPU::EnableStepping(false); + PowerPC::breakpoints.ClearAllTemporary(); + + // Keep stepping until the next blr or timeout after one second + u64 timeout = SystemTimers::GetTicksPerSecond(); + u64 steps = 0; + PowerPC::CoreMode oldMode = PowerPC::GetMode(); + PowerPC::SetMode(PowerPC::MODE_INTERPRETER); + UGeckoInstruction inst = Memory::Read_Instruction(PC); + GekkoOPInfo *opinfo = GetOpInfo(inst); + while (inst.hex != 0x4e800020 && steps < timeout) // check for blr + { + if (inst.LK) + { + // Step over branches + u32 next_pc = PC + 4; + while (PC != next_pc && steps < timeout) + { + PowerPC::SingleStep(); + ++steps; + } + } + else + { + PowerPC::SingleStep(); + ++steps; + } + inst = Memory::Read_Instruction(PC); + opinfo = GetOpInfo(inst); + } + + PowerPC::SingleStep(); + PowerPC::SetMode(oldMode); + JumpToAddress(PC); Update();