summaryrefslogtreecommitdiffstats
path: root/src/core/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.cpp5
-rw-r--r--src/core/arm/arm_interface.h5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp35
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp32
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h4
6 files changed, 69 insertions, 16 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index c347e7ea7..1310f72bf 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -9,6 +9,7 @@
#include "core/arm/arm_interface.h"
#include "core/arm/symbols.h"
#include "core/core.h"
+#include "core/debugger/debugger.h"
#include "core/hle/kernel/k_process.h"
#include "core/loader/loader.h"
#include "core/memory.h"
@@ -88,4 +89,8 @@ void ARM_Interface::LogBacktrace() const {
}
}
+bool ARM_Interface::ShouldStep() const {
+ return system.DebuggerEnabled() && system.GetDebugger().IsStepping();
+}
+
} // namespace Core
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 8ce973a77..7842c626b 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -66,9 +66,6 @@ public:
/// Runs the CPU until an event happens
virtual void Run() = 0;
- /// Step CPU by one instruction
- virtual void Step() = 0;
-
/// Clear all instruction cache
virtual void ClearInstructionCache() = 0;
@@ -194,6 +191,8 @@ public:
void LogBacktrace() const;
+ bool ShouldStep() const;
+
protected:
/// System context that this ARM interface is running under.
System& system;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 781a77f6f..894c1c527 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -17,6 +17,8 @@
#include "core/arm/dynarmic/arm_exclusive_monitor.h"
#include "core/core.h"
#include "core/core_timing.h"
+#include "core/debugger/debugger.h"
+#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
@@ -26,6 +28,7 @@ using namespace Common::Literals;
constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
+constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public:
@@ -78,11 +81,16 @@ public:
}
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
+ if (parent.system.DebuggerEnabled()) {
+ parent.breakpoint_pc = pc;
+ parent.jit.load()->HaltExecution(breakpoint);
+ return;
+ }
+
parent.LogBacktrace();
LOG_CRITICAL(Core_ARM,
"ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})",
exception, pc, MemoryReadCode(pc), parent.IsInThumbMode());
- UNIMPLEMENTED();
}
void CallSVC(u32 swi) override {
@@ -234,20 +242,35 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
void ARM_Dynarmic_32::Run() {
while (true) {
- const auto hr = jit.load()->Run();
+ const auto hr = ShouldStep() ? jit.load()->Step() : jit.load()->Run();
if (Has(hr, svc_call)) {
Kernel::Svc::Call(system, svc_swi);
}
+
+ // Check to see if breakpoint is triggered.
+ // Recheck step condition in case stop is no longer desired.
+ Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread();
+ if (Has(hr, breakpoint)) {
+ jit.load()->Regs()[15] = breakpoint_pc;
+
+ if (system.GetDebugger().NotifyThreadStopped(current_thread)) {
+ current_thread->RequestSuspend(Kernel::SuspendType::Debug);
+ }
+ break;
+ }
+ if (ShouldStep()) {
+ // When stepping, this should be the only thread running.
+ ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread));
+ current_thread->RequestSuspend(Kernel::SuspendType::Debug);
+ break;
+ }
+
if (Has(hr, break_loop) || !uses_wall_clock) {
break;
}
}
}
-void ARM_Dynarmic_32::Step() {
- jit.load()->Step();
-}
-
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_,
bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
std::size_t core_index_)
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index abfe76644..0557d5940 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -42,7 +42,6 @@ public:
u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override;
void Run() override;
- void Step() override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override;
@@ -95,6 +94,9 @@ private:
// SVC callback
u32 svc_swi{};
+
+ // Debug restart address
+ u32 breakpoint_pc{};
};
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 1b1334598..1f596cfef 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -15,6 +15,7 @@
#include "core/arm/dynarmic/arm_exclusive_monitor.h"
#include "core/core.h"
#include "core/core_timing.h"
+#include "core/debugger/debugger.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
@@ -27,6 +28,7 @@ using namespace Common::Literals;
constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
+constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
public:
@@ -119,8 +121,13 @@ public:
case Dynarmic::A64::Exception::SendEventLocal:
case Dynarmic::A64::Exception::Yield:
return;
- case Dynarmic::A64::Exception::Breakpoint:
default:
+ if (parent.system.DebuggerEnabled()) {
+ parent.breakpoint_pc = pc;
+ parent.jit.load()->HaltExecution(breakpoint);
+ return;
+ }
+
parent.LogBacktrace();
ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
@@ -299,16 +306,31 @@ void ARM_Dynarmic_64::Run() {
if (Has(hr, svc_call)) {
Kernel::Svc::Call(system, svc_swi);
}
+
+ // Check to see if breakpoint is triggered.
+ // Recheck step condition in case stop is no longer desired.
+ Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread();
+ if (Has(hr, breakpoint)) {
+ jit.load()->SetPC(breakpoint_pc);
+
+ if (system.GetDebugger().NotifyThreadStopped(current_thread)) {
+ current_thread->RequestSuspend(Kernel::SuspendType::Debug);
+ }
+ break;
+ }
+ if (ShouldStep()) {
+ // When stepping, this should be the only thread running.
+ ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread));
+ current_thread->RequestSuspend(Kernel::SuspendType::Debug);
+ break;
+ }
+
if (Has(hr, break_loop) || !uses_wall_clock) {
break;
}
}
}
-void ARM_Dynarmic_64::Step() {
- jit.load()->Step();
-}
-
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_,
bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
std::size_t core_index_)
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 01a7e4dad..aa7054e0c 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -40,7 +40,6 @@ public:
u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override;
void Run() override;
- void Step() override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override;
@@ -88,6 +87,9 @@ private:
// SVC callback
u32 svc_swi{};
+
+ // Debug restart address
+ u64 breakpoint_pc{};
};
} // namespace Core