summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinWX/Debugger/CodeWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/DolphinWX/Debugger/CodeWindow.cpp')
-rw-r--r--Source/Core/DolphinWX/Debugger/CodeWindow.cpp50
1 files changed, 26 insertions, 24 deletions
diff --git a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp
index 2f1ba3aaa7..aff5d48577 100644
--- a/Source/Core/DolphinWX/Debugger/CodeWindow.cpp
+++ b/Source/Core/DolphinWX/Debugger/CodeWindow.cpp
@@ -149,8 +149,6 @@ void CCodeWindow::OnHostMessage(wxCommandEvent& event)
case IDM_UPDATE_DISASM_DIALOG:
Update();
- if (codeview)
- codeview->Center(PC);
if (CPU::IsStepping())
Parent->UpdateGUI();
if (m_RegisterWindow)
@@ -160,7 +158,6 @@ void CCodeWindow::OnHostMessage(wxCommandEvent& event)
break;
case IDM_UPDATE_BREAKPOINTS:
- Update();
if (m_BreakpointWindow)
m_BreakpointWindow->NotifyUpdate();
break;
@@ -296,13 +293,13 @@ void CCodeWindow::SingleStep()
{
if (CPU::IsStepping())
{
+ PowerPC::CoreMode old_mode = PowerPC::GetMode();
+ PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
PowerPC::breakpoints.ClearAllTemporary();
- JitInterface::InvalidateICache(PC, 4, true);
CPU::StepOpcode(&sync_event);
- wxThread::Sleep(20);
- // need a short wait here
- JumpToAddress(PC);
- Update();
+ sync_event.WaitFor(std::chrono::milliseconds(20));
+ PowerPC::SetMode(old_mode);
+ // Will get a IDM_UPDATE_DISASM_DIALOG. Don't update the GUI here.
}
}
@@ -316,20 +313,23 @@ void CCodeWindow::StepOver()
PowerPC::breakpoints.ClearAllTemporary();
PowerPC::breakpoints.Add(PC + 4, true);
CPU::EnableStepping(false);
- JumpToAddress(PC);
- Update();
}
else
{
SingleStep();
}
-
- UpdateButtonStates();
- // Update all toolbars in the aui manager
- Parent->UpdateGUI();
}
}
+// Returns true on a blr or on a bclr that evaluates to true.
+static bool WillInstructionReturn(UGeckoInstruction inst)
+{
+ bool counter = (inst.BO_2 >> 2 & 1) != 0 || (CTR != 0) != ((inst.BO_2 >> 1 & 1) != 0);
+ bool condition = inst.BO_2 >> 4 != 0 || GetCRBit(inst.BI_2) == (inst.BO_2 >> 3 & 1);
+ bool isBclr = inst.OPCD_7 == 0b010011 && (inst.hex >> 1 & 0b10000) != 0;
+ return isBclr && counter && condition && !inst.LK_3;
+}
+
void CCodeWindow::StepOut()
{
if (CPU::IsStepping())
@@ -337,13 +337,16 @@ void CCodeWindow::StepOut()
CPU::PauseAndLock(true, false);
PowerPC::breakpoints.ClearAllTemporary();
- // Keep stepping until the next blr or timeout after one second
+ // Keep stepping until the next return instruction or timeout after one second
u64 timeout = SystemTimers::GetTicksPerSecond();
u64 steps = 0;
- PowerPC::CoreMode oldMode = PowerPC::GetMode();
+ PowerPC::CoreMode old_mode = PowerPC::GetMode();
PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
UGeckoInstruction inst = PowerPC::HostRead_Instruction(PC);
- while (inst.hex != 0x4e800020 && steps < timeout) // check for blr
+ // Loop until either the current instruction is a return instruction with no Link flag
+ // or a breakpoint is detected so it can step at the breakpoint.
+ while (!(WillInstructionReturn(inst)) && steps < timeout &&
+ !PowerPC::breakpoints.IsAddressBreakPoint(PC))
{
if (inst.LK)
{
@@ -362,15 +365,14 @@ void CCodeWindow::StepOut()
}
inst = PowerPC::HostRead_Instruction(PC);
}
-
- PowerPC::SingleStep();
- PowerPC::SetMode(oldMode);
+ // If the loop stopped because of a breakpoint, we do not want to step to
+ // an instruction after it.
+ if (!PowerPC::breakpoints.IsAddressBreakPoint(PC))
+ PowerPC::SingleStep();
+ PowerPC::SetMode(old_mode);
CPU::PauseAndLock(false, false);
- JumpToAddress(PC);
- Update();
Host_UpdateDisasmDialog();
-
UpdateButtonStates();
// Update all toolbars in the aui manager
Parent->UpdateGUI();
@@ -698,7 +700,7 @@ void CCodeWindow::Update()
if (!codeview)
return;
- codeview->Refresh();
+ codeview->Center(PC);
UpdateCallstack();
UpdateButtonStates();