aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/physical_core.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/physical_core.cpp')
-rw-r--r--src/core/hle/kernel/physical_core.cpp28
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);