diff options
Diffstat (limited to 'src/core/hle/kernel/physical_core.cpp')
| -rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index e4aff43d82..f394122764 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -50,6 +50,14 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { }; const auto ExitContext = [&]() { + // Save the JIT context back to the thread so the debugger can + // read the current register state. Debug halt paths (step, + // breakpoint, watchpoint) return from RunThread without going + // through the scheduler's Unload/SaveContext. + if (system.DebuggerEnabled()) { + interface->GetContext(thread->GetContext()); + } + // Unlock the thread. interface->UnlockThread(thread); @@ -97,11 +105,16 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { } // Determine why we stopped. - const bool supervisor_call = True(hr & Core::HaltReason::SupervisorCall); - const bool prefetch_abort = True(hr & Core::HaltReason::PrefetchAbort); - const bool breakpoint = True(hr & Core::HaltReason::InstructionBreakpoint); - const bool data_abort = True(hr & Core::HaltReason::DataAbort); - const bool interrupt = True(hr & Core::HaltReason::BreakLoop); + // If a step completed successfully, skip other halt reason handlers — + // the step takes priority (e.g. step may also set InstructionBreakpoint + // if the next instruction happens to be a breakpoint). + const bool step_completed = True(hr & Core::HaltReason::StepThread) + && thread->GetStepState() == StepState::StepPerformed; + const bool supervisor_call = !step_completed && True(hr & Core::HaltReason::SupervisorCall); + const bool prefetch_abort = !step_completed && True(hr & Core::HaltReason::PrefetchAbort); + const bool breakpoint = !step_completed && True(hr & Core::HaltReason::InstructionBreakpoint); + const bool data_abort = !step_completed && True(hr & Core::HaltReason::DataAbort); + const bool interrupt = !step_completed && True(hr & Core::HaltReason::BreakLoop); // Since scheduling may occur here, we cannot use any cached // state after returning from calls we make. @@ -111,6 +124,11 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { if (breakpoint || prefetch_abort) { if (breakpoint) { interface->RewindBreakpointInstruction(); + // RewindBreakpointInstruction sets the JIT state to the + // saved breakpoint context. Update the thread context to + // match, since ExitContext already saved the post-execution + // state. + interface->GetContext(thread->GetContext()); } if (system.DebuggerEnabled()) { system.GetDebugger().NotifyThreadStopped(thread); |
