From 989d4a7a41f449af0ea09e34bee331a3a3ac8170 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Tue, 31 May 2022 14:37:37 -0400
Subject: core/debugger: Improved stepping mechanism and misc fixes

---
 src/core/arm/arm_interface.cpp | 45 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)

(limited to 'src/core/arm/arm_interface.cpp')

diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 1310f72bf9..9b5a5ca576 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -11,6 +11,7 @@
 #include "core/core.h"
 #include "core/debugger/debugger.h"
 #include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/svc.h"
 #include "core/loader/loader.h"
 #include "core/memory.h"
 
@@ -89,8 +90,48 @@ void ARM_Interface::LogBacktrace() const {
     }
 }
 
-bool ARM_Interface::ShouldStep() const {
-    return system.DebuggerEnabled() && system.GetDebugger().IsStepping();
+void ARM_Interface::Run() {
+    using Kernel::StepState;
+    using Kernel::SuspendType;
+
+    while (true) {
+        Kernel::KThread* current_thread{system.Kernel().CurrentScheduler()->GetCurrentThread()};
+        Dynarmic::HaltReason hr{};
+
+        // Notify the debugger and go to sleep if a step was performed
+        // and this thread has been scheduled again.
+        if (current_thread->GetStepState() == StepState::StepPerformed) {
+            system.GetDebugger().NotifyThreadStopped(current_thread);
+            current_thread->RequestSuspend(SuspendType::Debug);
+            break;
+        }
+
+        // Otherwise, run the thread.
+        if (current_thread->GetStepState() == StepState::StepPending) {
+            hr = StepJit();
+
+            if (Has(hr, step_thread)) {
+                current_thread->SetStepState(StepState::StepPerformed);
+            }
+        } else {
+            hr = RunJit();
+        }
+
+        // Notify the debugger and go to sleep if a breakpoint was hit.
+        if (Has(hr, breakpoint)) {
+            system.GetDebugger().NotifyThreadStopped(current_thread);
+            current_thread->RequestSuspend(Kernel::SuspendType::Debug);
+            break;
+        }
+
+        // Handle syscalls and scheduling (this may change the current thread)
+        if (Has(hr, svc_call)) {
+            Kernel::Svc::Call(system, GetSvcNumber());
+        }
+        if (Has(hr, break_loop) || !uses_wall_clock) {
+            break;
+        }
+    }
 }
 
 } // namespace Core
-- 
cgit v1.2.3-70-g09d2