diff options
Diffstat (limited to 'src/core/arm/arm_interface.cpp')
-rw-r--r-- | src/core/arm/arm_interface.cpp | 45 |
1 files changed, 43 insertions, 2 deletions
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 |