diff --git a/Core/Core.cpp b/Core/Core.cpp index 891da66bd9..64f323f9cf 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -237,11 +237,24 @@ void Core_UpdateSingleStep() { m_StepCond.notify_all(); } -void Core_SingleStep() { - Core_ResetException(); - currentMIPS->SingleStep(); - if (coreState == CORE_STEPPING) - steppingCounter++; +// See comment in header. +u32 Core_PerformStep(DebugInterface *cpu, CPUStepType stepType, int stepSize) { + switch (stepType) { + case CPUStepType::Into: + { + u32 currentPc = cpu->GetPC(); + u32 newAddress = currentPc + stepSize; + // If the current PC is on a breakpoint, the user still wants the step to happen. + CBreakPoints::SetSkipFirst(currentMIPS->pc); + for (int i = 0; i < (newAddress - currentPc) / 4; i++) { + Core_DoSingleStep(); + } + return newAddress; + } + default: + // Not yet implemented + return cpu->GetPC(); + } } static inline bool Core_WaitStepping() { @@ -284,7 +297,10 @@ void Core_ProcessStepping() { // We may still be stepping without singleStepPending to process a save state. if (doStep && coreState == CORE_STEPPING) { - Core_SingleStep(); + Core_ResetException(); + currentMIPS->SingleStep(); + steppingCounter++; + // Update disasm dialog. System_Notify(SystemNotification::DISASSEMBLY); System_Notify(SystemNotification::MEM_VIEW); diff --git a/Core/Core.h b/Core/Core.h index 478897c433..a3cc091b45 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -24,6 +24,7 @@ #include "Core/CoreParameter.h" class GraphicsContext; +class DebugInterface; // called from emu thread void UpdateRunLoop(GraphicsContext *ctx); @@ -35,20 +36,29 @@ void Core_SetGraphicsContext(GraphicsContext *ctx); bool Core_Run(GraphicsContext *ctx); void Core_Stop(); -/* +// X11, sigh. +#ifdef None +#undef None +#endif + enum class CPUStepType { None, Into, Over, Out, }; -*/ // Async, called from gui void Core_Break(const char *reason, u32 relatedAddress = 0); // void Core_Step(CPUStepType type); // CPUStepType::None not allowed void Core_Resume(); +// Handles more advanced step types (used by the debugger). +// stepSize is to support stepping through compound instructions like fused lui+ladd (li). +// Yes, our disassembler does support those. +// Returns the new address. +uint32_t Core_PerformStep(DebugInterface *mips, CPUStepType stepType, int stepSize); + // Refactor. void Core_DoSingleStep(); void Core_UpdateSingleStep(); diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index 7f9d2a2dbd..9ce66398f9 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -1428,5 +1428,5 @@ u32 CtrlDisAsmView::getInstructionSizeAt(u32 address) { u32 start = manager.getStartAddress(address); u32 next = manager.getNthNextAddress(start,1); - return next-address; + return next - address; } diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index fa833c85e6..9ee5bdc24d 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -92,7 +92,7 @@ static constexpr UINT UPDATE_DELAY = 1000 / 60; CDisasm::CDisasm(HINSTANCE _hInstance, HWND _hParent, DebugInterface *_cpu) : Dialog((LPCSTR)IDD_DISASM, _hInstance, _hParent) { cpu = _cpu; - lastTicks = PSP_IsInited() ? CoreTiming::GetTicks() : 0; + lastTicks_ = PSP_IsInited() ? CoreTiming::GetTicks() : 0; SetWindowText(m_hDlg, ConvertUTF8ToWString(_cpu->GetName()).c_str()); @@ -205,41 +205,15 @@ void CDisasm::stepInto() } CtrlDisAsmView *ptr = DisAsmView(); - lastTicks = CoreTiming::GetTicks(); - u32 currentPc = cpu->GetPC(); + lastTicks_ = CoreTiming::GetTicks(); - // If the current PC is on a breakpoint, the user doesn't want to do nothing. - CBreakPoints::SetSkipFirst(currentMIPS->pc); - u32 newAddress = currentPc+ptr->getInstructionSizeAt(currentPc); - - MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(cpu,currentPc); - if (info.isBranch) - { - ptr->scrollStepping(newAddress); - } else { - bool scroll = true; - if (currentMIPS->inDelaySlot) - { - MIPSAnalyst::MipsOpcodeInfo prevInfo = MIPSAnalyst::GetOpcodeInfo(cpu,currentPc-cpu->getInstructionSize(0)); - if (!prevInfo.isConditional || prevInfo.conditionMet) - scroll = false; - } - - if (scroll) - { - ptr->scrollStepping(newAddress); - } - } - - for (u32 i = 0; i < (newAddress-currentPc)/4; i++) - { - Core_DoSingleStep(); - Sleep(1); - } + u32 stepSize = ptr->getInstructionSizeAt(cpu->GetPC()); + u32 newAddress = Core_PerformStep(cpu, CPUStepType::Into, stepSize); + ptr->scrollStepping(newAddress); + Sleep(1); ptr->gotoPC(); UpdateDialog(); - threadList->reloadThreads(); stackTraceView->loadStackTrace(); } @@ -251,15 +225,15 @@ void CDisasm::stepOver() } CtrlDisAsmView *ptr = DisAsmView(); - lastTicks = CoreTiming::GetTicks(); + lastTicks_ = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. - CBreakPoints::SetSkipFirst(currentMIPS->pc); u32 currentPc = cpu->GetPC(); + CBreakPoints::SetSkipFirst(currentMIPS->pc); MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(cpu,cpu->GetPC()); ptr->setDontRedraw(true); - u32 breakpointAddress = currentPc+ptr->getInstructionSizeAt(currentPc); + u32 breakpointAddress = currentPc + ptr->getInstructionSizeAt(currentPc); if (info.isBranch) { if (info.isConditional == false) @@ -313,7 +287,7 @@ void CDisasm::stepOut() { auto frames = MIPSStackWalk::Walk(cpu->GetPC(),cpu->GetRegValue(0,31),cpu->GetRegValue(0,29),entry,stackTop); if (frames.size() < 2) return; u32 breakpointAddress = frames[1].pc; - lastTicks = CoreTiming::GetTicks(); + lastTicks_ = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); @@ -328,8 +302,7 @@ void CDisasm::stepOut() { UpdateDialog(); } -void CDisasm::runToLine() -{ +void CDisasm::runToLine() { if (!PSP_IsInited()) { return; } @@ -337,7 +310,7 @@ void CDisasm::runToLine() CtrlDisAsmView *ptr = DisAsmView(); u32 pos = ptr->getSelection(); - lastTicks = CoreTiming::GetTicks(); + lastTicks_ = CoreTiming::GetTicks(); ptr->setDontRedraw(true); CBreakPoints::AddBreakPoint(pos,true); Core_Resume(); @@ -524,7 +497,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) ptr->gotoPC(); UpdateDialog(); } else { // go - lastTicks = CoreTiming::GetTicks(); + lastTicks_ = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); @@ -550,7 +523,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { if (Core_IsActive()) break; - lastTicks = CoreTiming::GetTicks(); + lastTicks_ = CoreTiming::GetTicks(); // If the current PC is on a breakpoint, the user doesn't want to do nothing. CBreakPoints::SetSkipFirst(currentMIPS->pc); @@ -904,7 +877,7 @@ void CDisasm::ProcessUpdateDialog() { // Update Debug Counter if (PSP_IsInited()) { wchar_t tempTicks[24]{}; - _snwprintf(tempTicks, 23, L"%lld", CoreTiming::GetTicks() - lastTicks); + _snwprintf(tempTicks, 23, L"%lld", CoreTiming::GetTicks() - lastTicks_); SetDlgItemText(m_hDlg, IDC_DEBUG_COUNT, tempTicks); } diff --git a/Windows/Debugger/Debugger_Disasm.h b/Windows/Debugger/Debugger_Disasm.h index 9ce5cbf660..3fda21d5a4 100644 --- a/Windows/Debugger/Debugger_Disasm.h +++ b/Windows/Debugger/Debugger_Disasm.h @@ -18,7 +18,7 @@ private: int minWidth; int minHeight; DebugInterface *cpu; - u64 lastTicks; + u64 lastTicks_; HWND statusBarWnd; CtrlBreakpointList* breakpointList;