diff --git a/Core/Core.cpp b/Core/Core.cpp index 9fe9b44df7..0960957bd4 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -54,7 +54,8 @@ // Step command to execute next static std::mutex g_stepMutex; -struct StepCommand { + +struct CPUStepCommand { CPUStepType type; int stepSize; const char *reason; @@ -69,7 +70,20 @@ struct StepCommand { relatedAddr = 0; } }; -static StepCommand g_stepCommand; + +static CPUStepCommand g_cpuStepCommand; + +struct GeStepCommand { + CPUStepType type; + bool empty() const { + return type == CPUStepType::None; + } + void clear() { + type = CPUStepType::None; + } +}; + +static GeStepCommand g_geStepCommand; // This is so that external threads can wait for the CPU to become inactive. static std::condition_variable m_InactiveCond; @@ -157,15 +171,25 @@ bool Core_GetPowerSaving() { return powerSaving; } -bool Core_RequestSingleStep(CPUStepType type, int stepSize) { +bool Core_RequestCPUStep(CPUStepType type, int stepSize) { std::lock_guard guard(g_stepMutex); - if (g_stepCommand.type != CPUStepType::None) { - ERROR_LOG(Log::CPU, "Can't submit two steps in one frame"); + if (g_cpuStepCommand.type != CPUStepType::None) { + ERROR_LOG(Log::CPU, "Can't submit two steps in one host frame"); return false; } // Out-steps don't need a size. _dbg_assert_(stepSize != 0 || type == CPUStepType::Out); - g_stepCommand = { type, stepSize }; + g_cpuStepCommand = { type, stepSize }; + return true; +} + +bool Core_RequestGeStep(CPUStepType type) { + std::lock_guard guard(g_stepMutex); + if (g_geStepCommand.type != CPUStepType::None) { + ERROR_LOG(Log::CPU, "Can't submit two steps in one host frame"); + return false; + } + g_geStepCommand = { type }; return true; } @@ -174,7 +198,7 @@ bool Core_RequestSingleStep(CPUStepType type, int stepSize) { // Yes, our disassembler does support those. // Doesn't return the new address, as that's just mips->getPC(). // Internal use. -static void Core_PerformStep(MIPSDebugInterface *cpu, CPUStepType stepType, int stepSize) { +static void Core_PerformCPUStep(MIPSDebugInterface *cpu, CPUStepType stepType, int stepSize) { switch (stepType) { case CPUStepType::Into: { @@ -257,6 +281,11 @@ static void Core_PerformStep(MIPSDebugInterface *cpu, CPUStepType stepType, int } } +static void Core_PerformGeStep(CPUStepType stepType) { + // TODO +} + +// Should only be called from GPUCommon functions (called from sceGe functions). void Core_SwitchToGe() { coreState = CORE_RUNNING_GE; } @@ -269,6 +298,7 @@ void Core_ProcessStepping(MIPSDebugInterface *cpu) { switch (coreState) { case CORE_STEPPING_CPU: + case CORE_STEPPING_GE: // All good break; default: @@ -277,6 +307,7 @@ void Core_ProcessStepping(MIPSDebugInterface *cpu) { } // Or any GPU actions. + // Legacy stepping code. GPUStepping::SingleStep(); // We're not inside jit now, so it's safe to clear the breakpoints. @@ -291,19 +322,29 @@ void Core_ProcessStepping(MIPSDebugInterface *cpu) { // Need to check inside the lock to avoid races. std::lock_guard guard(g_stepMutex); - if (coreState != CORE_STEPPING_CPU || g_stepCommand.empty()) { + if (coreState == CORE_STEPPING_GE) { + if (!g_geStepCommand.empty()) { + Core_PerformGeStep(g_geStepCommand.type); + // System_Notify(SystemNotification::) + g_geStepCommand.clear(); + steppingCounter++; + } + return; + } + + if (coreState != CORE_STEPPING_CPU || g_cpuStepCommand.empty()) { return; } Core_ResetException(); - if (!g_stepCommand.empty()) { - Core_PerformStep(cpu, g_stepCommand.type, g_stepCommand.stepSize); - if (g_stepCommand.type == CPUStepType::Into) { + if (!g_cpuStepCommand.empty()) { + Core_PerformCPUStep(cpu, g_cpuStepCommand.type, g_cpuStepCommand.stepSize); + if (g_cpuStepCommand.type == CPUStepType::Into) { // We're already done. The other step types will resume the CPU. System_Notify(SystemNotification::DISASSEMBLY_AFTERSTEP); } - g_stepCommand.clear(); + g_cpuStepCommand.clear(); steppingCounter++; } @@ -316,22 +357,22 @@ void Core_Break(const char *reason, u32 relatedAddress) { // Stop the tracer { std::lock_guard lock(g_stepMutex); - if (!g_stepCommand.empty() && Core_IsStepping()) { + if (!g_cpuStepCommand.empty() && Core_IsStepping()) { // If we're in a failed step that uses a temp breakpoint, we need to be able to override it here. - switch (g_stepCommand.type) { + switch (g_cpuStepCommand.type) { case CPUStepType::Over: case CPUStepType::Out: // Allow overwriting the command. break; default: - ERROR_LOG(Log::CPU, "Core_Break called with a step-command already in progress: %s", g_stepCommand.reason); + ERROR_LOG(Log::CPU, "Core_Break called with a step-command already in progress: %s", g_cpuStepCommand.reason); return; } } mipsTracer.stop_tracing(); - g_stepCommand.type = CPUStepType::None; - g_stepCommand.reason = reason; - g_stepCommand.relatedAddr = relatedAddress; + g_cpuStepCommand.type = CPUStepType::None; + g_cpuStepCommand.reason = reason; + g_cpuStepCommand.relatedAddr = relatedAddress; steppingCounter++; _assert_msg_(reason != nullptr, "No reason specified for break"); Core_UpdateState(CORE_STEPPING_CPU); @@ -341,6 +382,12 @@ void Core_Break(const char *reason, u32 relatedAddress) { // Free-threaded (or at least should be) void Core_Resume() { + // Handle resuming from GE. + if (coreState == CORE_STEPPING_GE) { + coreState = CORE_RUNNING_GE; + return; + } + // Clear the exception if we resume. Core_ResetException(); coreState = CORE_RUNNING_CPU; @@ -349,6 +396,8 @@ void Core_Resume() { // Should be called from the EmuThread. bool Core_NextFrame() { + _dbg_assert_(coreState != CORE_STEPPING_GE && coreState != CORE_RUNNING_GE); + if (coreState == CORE_RUNNING_CPU) { coreState = CORE_NEXTFRAME; return true; @@ -364,9 +413,9 @@ int Core_GetSteppingCounter() { SteppingReason Core_GetSteppingReason() { SteppingReason r; std::lock_guard lock(g_stepMutex); - if (!g_stepCommand.empty()) { - r.reason = g_stepCommand.reason; - r.relatedAddress = g_stepCommand.relatedAddr; + if (!g_cpuStepCommand.empty()) { + r.reason = g_cpuStepCommand.reason; + r.relatedAddress = g_cpuStepCommand.relatedAddr; } return r; } diff --git a/Core/Core.h b/Core/Core.h index fe55c31f1b..0df85039b3 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -22,6 +22,7 @@ #include "Core/System.h" #include "Core/CoreParameter.h" +#include "GPU/GPUDefinitions.h" class GraphicsContext; @@ -50,7 +51,8 @@ void Core_Resume(); // This should be called externally. // Can fail if another step type was requested this frame. -bool Core_RequestSingleStep(CPUStepType stepType, int stepSize); +bool Core_RequestCPUStep(CPUStepType stepType, int stepSize); +bool Core_RequestGeStep(CPUStepType stepType); bool Core_ShouldRunBehind(); bool Core_MustRunBehind(); diff --git a/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp b/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp index 5540a31e65..60c46c4f28 100644 --- a/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp +++ b/Core/Debugger/WebSocket/CPUCoreSubscriber.cpp @@ -90,7 +90,7 @@ void WebSocketCPUResume(DebuggerRequest &req) { g_breakpoints.SetSkipFirst(currentMIPS->pc); if (currentMIPS->inDelaySlot) { - Core_RequestSingleStep(CPUStepType::Into, 1); + Core_RequestCPUStep(CPUStepType::Into, 1); } Core_Resume(); } diff --git a/Core/Debugger/WebSocket/SteppingSubscriber.cpp b/Core/Debugger/WebSocket/SteppingSubscriber.cpp index b0d4cf37de..019a4868e4 100644 --- a/Core/Debugger/WebSocket/SteppingSubscriber.cpp +++ b/Core/Debugger/WebSocket/SteppingSubscriber.cpp @@ -107,7 +107,7 @@ void WebSocketSteppingState::Into(DebuggerRequest &req) { g_breakpoints.SetSkipFirst(currentMIPS->pc); int c = GetNextInstructionCount(cpuDebug); - Core_RequestSingleStep(CPUStepType::Into, c); + Core_RequestCPUStep(CPUStepType::Into, c); } else { uint32_t breakpointAddress = cpuDebug->GetPC(); PrepareResume(); @@ -277,7 +277,7 @@ int WebSocketSteppingState::GetNextInstructionCount(DebugInterface *cpuDebug) { void WebSocketSteppingState::PrepareResume() { if (currentMIPS->inDelaySlot) { // Delay slot instructions are never joined, so we pass 1. - Core_RequestSingleStep(CPUStepType::Into, 1); + Core_RequestCPUStep(CPUStepType::Into, 1); } else { // If the current PC is on a breakpoint, the user doesn't want to do nothing. g_breakpoints.SetSkipFirst(currentMIPS->pc); diff --git a/GPU/GPUDefinitions.h b/GPU/GPUDefinitions.h index e5d640f113..5dc6d6d08a 100644 --- a/GPU/GPUDefinitions.h +++ b/GPU/GPUDefinitions.h @@ -53,3 +53,24 @@ enum GPUInvalidationType { // Forced invalidation for when the texture hash may not catch changes. GPU_INVALIDATE_FORCE, }; + +enum class DLRunType { + Run, + RunDebug, + Step, +}; + +enum class DLStepType { + None, + Single, + Prim, + Draw, + Texture, + Rendertarget, +}; + +enum class DLResult { + Done, + Error, + Pause, // used for stepping, breakpoints +}; diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 49f4959960..e6e377b9e8 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -942,11 +942,11 @@ void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState c // Process stepping keyboard shortcuts. if (ImGui::IsKeyPressed(ImGuiKey_F10)) { u32 stepSize = disasmView_.getInstructionSizeAt(mipsDebug->GetPC()); - Core_RequestSingleStep(CPUStepType::Over, stepSize); + Core_RequestCPUStep(CPUStepType::Over, stepSize); } if (ImGui::IsKeyPressed(ImGuiKey_F11)) { u32 stepSize = disasmView_.getInstructionSizeAt(mipsDebug->GetPC()); - Core_RequestSingleStep(CPUStepType::Into, stepSize); + Core_RequestCPUStep(CPUStepType::Into, stepSize); } } @@ -972,18 +972,18 @@ void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState c ImGui::SameLine(); if (ImGui::SmallButton("Step Into")) { u32 stepSize = disasmView_.getInstructionSizeAt(mipsDebug->GetPC()); - Core_RequestSingleStep(CPUStepType::Into, stepSize); + Core_RequestCPUStep(CPUStepType::Into, stepSize); } ImGui::SameLine(); if (ImGui::SmallButton("Step Over")) { u32 stepSize = disasmView_.getInstructionSizeAt(mipsDebug->GetPC()); - Core_RequestSingleStep(CPUStepType::Over, stepSize); + Core_RequestCPUStep(CPUStepType::Over, stepSize); } ImGui::SameLine(); if (ImGui::SmallButton("Step Out")) { - Core_RequestSingleStep(CPUStepType::Out, 0); + Core_RequestCPUStep(CPUStepType::Out, 0); } ImGui::EndDisabled(); diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index 78dcedb2c0..8569d6bca7 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -210,7 +210,7 @@ void CDisasm::step(CPUStepType stepType) { lastTicks_ = CoreTiming::GetTicks(); u32 stepSize = ptr->getInstructionSizeAt(cpu->GetPC()); - Core_RequestSingleStep(stepType, stepSize); + Core_RequestCPUStep(stepType, stepSize); } void CDisasm::runToLine() {