diff options
Diffstat (limited to 'src/core/arm')
| -rw-r--r-- | src/core/arm/arm_interface.cpp | 45 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.h | 14 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 45 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 9 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 45 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 9 |
6 files changed, 87 insertions, 80 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 1310f72bf..9b5a5ca57 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/debugger/debugger.h" | 12 | #include "core/debugger/debugger.h" |
| 13 | #include "core/hle/kernel/k_process.h" | 13 | #include "core/hle/kernel/k_process.h" |
| 14 | #include "core/hle/kernel/svc.h" | ||
| 14 | #include "core/loader/loader.h" | 15 | #include "core/loader/loader.h" |
| 15 | #include "core/memory.h" | 16 | #include "core/memory.h" |
| 16 | 17 | ||
| @@ -89,8 +90,48 @@ void ARM_Interface::LogBacktrace() const { | |||
| 89 | } | 90 | } |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | bool ARM_Interface::ShouldStep() const { | 93 | void ARM_Interface::Run() { |
| 93 | return system.DebuggerEnabled() && system.GetDebugger().IsStepping(); | 94 | using Kernel::StepState; |
| 95 | using Kernel::SuspendType; | ||
| 96 | |||
| 97 | while (true) { | ||
| 98 | Kernel::KThread* current_thread{system.Kernel().CurrentScheduler()->GetCurrentThread()}; | ||
| 99 | Dynarmic::HaltReason hr{}; | ||
| 100 | |||
| 101 | // Notify the debugger and go to sleep if a step was performed | ||
| 102 | // and this thread has been scheduled again. | ||
| 103 | if (current_thread->GetStepState() == StepState::StepPerformed) { | ||
| 104 | system.GetDebugger().NotifyThreadStopped(current_thread); | ||
| 105 | current_thread->RequestSuspend(SuspendType::Debug); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | |||
| 109 | // Otherwise, run the thread. | ||
| 110 | if (current_thread->GetStepState() == StepState::StepPending) { | ||
| 111 | hr = StepJit(); | ||
| 112 | |||
| 113 | if (Has(hr, step_thread)) { | ||
| 114 | current_thread->SetStepState(StepState::StepPerformed); | ||
| 115 | } | ||
| 116 | } else { | ||
| 117 | hr = RunJit(); | ||
| 118 | } | ||
| 119 | |||
| 120 | // Notify the debugger and go to sleep if a breakpoint was hit. | ||
| 121 | if (Has(hr, breakpoint)) { | ||
| 122 | system.GetDebugger().NotifyThreadStopped(current_thread); | ||
| 123 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | |||
| 127 | // Handle syscalls and scheduling (this may change the current thread) | ||
| 128 | if (Has(hr, svc_call)) { | ||
| 129 | Kernel::Svc::Call(system, GetSvcNumber()); | ||
| 130 | } | ||
| 131 | if (Has(hr, break_loop) || !uses_wall_clock) { | ||
| 132 | break; | ||
| 133 | } | ||
| 134 | } | ||
| 94 | } | 135 | } |
| 95 | 136 | ||
| 96 | } // namespace Core | 137 | } // namespace Core |
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 7842c626b..66f6107e9 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | |||
| 10 | #include <dynarmic/interface/halt_reason.h> | ||
| 11 | |||
| 9 | #include "common/common_funcs.h" | 12 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 11 | #include "core/hardware_properties.h" | 14 | #include "core/hardware_properties.h" |
| @@ -64,7 +67,7 @@ public: | |||
| 64 | static_assert(sizeof(ThreadContext64) == 0x320); | 67 | static_assert(sizeof(ThreadContext64) == 0x320); |
| 65 | 68 | ||
| 66 | /// Runs the CPU until an event happens | 69 | /// Runs the CPU until an event happens |
| 67 | virtual void Run() = 0; | 70 | void Run(); |
| 68 | 71 | ||
| 69 | /// Clear all instruction cache | 72 | /// Clear all instruction cache |
| 70 | virtual void ClearInstructionCache() = 0; | 73 | virtual void ClearInstructionCache() = 0; |
| @@ -191,7 +194,10 @@ public: | |||
| 191 | 194 | ||
| 192 | void LogBacktrace() const; | 195 | void LogBacktrace() const; |
| 193 | 196 | ||
| 194 | bool ShouldStep() const; | 197 | static constexpr Dynarmic::HaltReason step_thread = Dynarmic::HaltReason::Step; |
| 198 | static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | ||
| 199 | static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||
| 200 | static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||
| 195 | 201 | ||
| 196 | protected: | 202 | protected: |
| 197 | /// System context that this ARM interface is running under. | 203 | /// System context that this ARM interface is running under. |
| @@ -200,6 +206,10 @@ protected: | |||
| 200 | bool uses_wall_clock; | 206 | bool uses_wall_clock; |
| 201 | 207 | ||
| 202 | static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out); | 208 | static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out); |
| 209 | |||
| 210 | virtual Dynarmic::HaltReason RunJit() = 0; | ||
| 211 | virtual Dynarmic::HaltReason StepJit() = 0; | ||
| 212 | virtual u32 GetSvcNumber() const = 0; | ||
| 203 | }; | 213 | }; |
| 204 | 214 | ||
| 205 | } // namespace Core | 215 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 894c1c527..7c82d0b96 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -26,10 +26,6 @@ namespace Core { | |||
| 26 | 26 | ||
| 27 | using namespace Common::Literals; | 27 | using namespace Common::Literals; |
| 28 | 28 | ||
| 29 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | ||
| 30 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||
| 31 | constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||
| 32 | |||
| 33 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | 29 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { |
| 34 | public: | 30 | public: |
| 35 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) | 31 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) |
| @@ -82,8 +78,8 @@ public: | |||
| 82 | 78 | ||
| 83 | void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { | 79 | void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { |
| 84 | if (parent.system.DebuggerEnabled()) { | 80 | if (parent.system.DebuggerEnabled()) { |
| 85 | parent.breakpoint_pc = pc; | 81 | parent.jit.load()->Regs()[15] = pc; |
| 86 | parent.jit.load()->HaltExecution(breakpoint); | 82 | parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); |
| 87 | return; | 83 | return; |
| 88 | } | 84 | } |
| 89 | 85 | ||
| @@ -95,7 +91,7 @@ public: | |||
| 95 | 91 | ||
| 96 | void CallSVC(u32 swi) override { | 92 | void CallSVC(u32 swi) override { |
| 97 | parent.svc_swi = swi; | 93 | parent.svc_swi = swi; |
| 98 | parent.jit.load()->HaltExecution(svc_call); | 94 | parent.jit.load()->HaltExecution(ARM_Interface::svc_call); |
| 99 | } | 95 | } |
| 100 | 96 | ||
| 101 | void AddTicks(u64 ticks) override { | 97 | void AddTicks(u64 ticks) override { |
| @@ -240,35 +236,16 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 240 | return std::make_unique<Dynarmic::A32::Jit>(config); | 236 | return std::make_unique<Dynarmic::A32::Jit>(config); |
| 241 | } | 237 | } |
| 242 | 238 | ||
| 243 | void ARM_Dynarmic_32::Run() { | 239 | Dynarmic::HaltReason ARM_Dynarmic_32::RunJit() { |
| 244 | while (true) { | 240 | return jit.load()->Run(); |
| 245 | const auto hr = ShouldStep() ? jit.load()->Step() : jit.load()->Run(); | 241 | } |
| 246 | if (Has(hr, svc_call)) { | ||
| 247 | Kernel::Svc::Call(system, svc_swi); | ||
| 248 | } | ||
| 249 | |||
| 250 | // Check to see if breakpoint is triggered. | ||
| 251 | // Recheck step condition in case stop is no longer desired. | ||
| 252 | Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread(); | ||
| 253 | if (Has(hr, breakpoint)) { | ||
| 254 | jit.load()->Regs()[15] = breakpoint_pc; | ||
| 255 | 242 | ||
| 256 | if (system.GetDebugger().NotifyThreadStopped(current_thread)) { | 243 | Dynarmic::HaltReason ARM_Dynarmic_32::StepJit() { |
| 257 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | 244 | return jit.load()->Step(); |
| 258 | } | 245 | } |
| 259 | break; | ||
| 260 | } | ||
| 261 | if (ShouldStep()) { | ||
| 262 | // When stepping, this should be the only thread running. | ||
| 263 | ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread)); | ||
| 264 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | 246 | ||
| 268 | if (Has(hr, break_loop) || !uses_wall_clock) { | 247 | u32 ARM_Dynarmic_32::GetSvcNumber() const { |
| 269 | break; | 248 | return svc_swi; |
| 270 | } | ||
| 271 | } | ||
| 272 | } | 249 | } |
| 273 | 250 | ||
| 274 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, | 251 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 0557d5940..5b1d60005 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -41,7 +41,6 @@ public: | |||
| 41 | void SetVectorReg(int index, u128 value) override; | 41 | void SetVectorReg(int index, u128 value) override; |
| 42 | u32 GetPSTATE() const override; | 42 | u32 GetPSTATE() const override; |
| 43 | void SetPSTATE(u32 pstate) override; | 43 | void SetPSTATE(u32 pstate) override; |
| 44 | void Run() override; | ||
| 45 | VAddr GetTlsAddress() const override; | 44 | VAddr GetTlsAddress() const override; |
| 46 | void SetTlsAddress(VAddr address) override; | 45 | void SetTlsAddress(VAddr address) override; |
| 47 | void SetTPIDR_EL0(u64 value) override; | 46 | void SetTPIDR_EL0(u64 value) override; |
| @@ -69,6 +68,11 @@ public: | |||
| 69 | 68 | ||
| 70 | std::vector<BacktraceEntry> GetBacktrace() const override; | 69 | std::vector<BacktraceEntry> GetBacktrace() const override; |
| 71 | 70 | ||
| 71 | protected: | ||
| 72 | Dynarmic::HaltReason RunJit() override; | ||
| 73 | Dynarmic::HaltReason StepJit() override; | ||
| 74 | u32 GetSvcNumber() const override; | ||
| 75 | |||
| 72 | private: | 76 | private: |
| 73 | std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; | 77 | std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; |
| 74 | 78 | ||
| @@ -94,9 +98,6 @@ private: | |||
| 94 | 98 | ||
| 95 | // SVC callback | 99 | // SVC callback |
| 96 | u32 svc_swi{}; | 100 | u32 svc_swi{}; |
| 97 | |||
| 98 | // Debug restart address | ||
| 99 | u32 breakpoint_pc{}; | ||
| 100 | }; | 101 | }; |
| 101 | 102 | ||
| 102 | } // namespace Core | 103 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 1f596cfef..d4c67eafd 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -26,10 +26,6 @@ namespace Core { | |||
| 26 | using Vector = Dynarmic::A64::Vector; | 26 | using Vector = Dynarmic::A64::Vector; |
| 27 | using namespace Common::Literals; | 27 | using namespace Common::Literals; |
| 28 | 28 | ||
| 29 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | ||
| 30 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||
| 31 | constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||
| 32 | |||
| 33 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | 29 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 34 | public: | 30 | public: |
| 35 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) | 31 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) |
| @@ -123,8 +119,8 @@ public: | |||
| 123 | return; | 119 | return; |
| 124 | default: | 120 | default: |
| 125 | if (parent.system.DebuggerEnabled()) { | 121 | if (parent.system.DebuggerEnabled()) { |
| 126 | parent.breakpoint_pc = pc; | 122 | parent.jit.load()->SetPC(pc); |
| 127 | parent.jit.load()->HaltExecution(breakpoint); | 123 | parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); |
| 128 | return; | 124 | return; |
| 129 | } | 125 | } |
| 130 | 126 | ||
| @@ -136,7 +132,7 @@ public: | |||
| 136 | 132 | ||
| 137 | void CallSVC(u32 swi) override { | 133 | void CallSVC(u32 swi) override { |
| 138 | parent.svc_swi = swi; | 134 | parent.svc_swi = swi; |
| 139 | parent.jit.load()->HaltExecution(svc_call); | 135 | parent.jit.load()->HaltExecution(ARM_Interface::svc_call); |
| 140 | } | 136 | } |
| 141 | 137 | ||
| 142 | void AddTicks(u64 ticks) override { | 138 | void AddTicks(u64 ticks) override { |
| @@ -300,35 +296,16 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 300 | return std::make_shared<Dynarmic::A64::Jit>(config); | 296 | return std::make_shared<Dynarmic::A64::Jit>(config); |
| 301 | } | 297 | } |
| 302 | 298 | ||
| 303 | void ARM_Dynarmic_64::Run() { | 299 | Dynarmic::HaltReason ARM_Dynarmic_64::RunJit() { |
| 304 | while (true) { | 300 | return jit.load()->Run(); |
| 305 | const auto hr = jit.load()->Run(); | 301 | } |
| 306 | if (Has(hr, svc_call)) { | ||
| 307 | Kernel::Svc::Call(system, svc_swi); | ||
| 308 | } | ||
| 309 | |||
| 310 | // Check to see if breakpoint is triggered. | ||
| 311 | // Recheck step condition in case stop is no longer desired. | ||
| 312 | Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread(); | ||
| 313 | if (Has(hr, breakpoint)) { | ||
| 314 | jit.load()->SetPC(breakpoint_pc); | ||
| 315 | 302 | ||
| 316 | if (system.GetDebugger().NotifyThreadStopped(current_thread)) { | 303 | Dynarmic::HaltReason ARM_Dynarmic_64::StepJit() { |
| 317 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | 304 | return jit.load()->Step(); |
| 318 | } | 305 | } |
| 319 | break; | ||
| 320 | } | ||
| 321 | if (ShouldStep()) { | ||
| 322 | // When stepping, this should be the only thread running. | ||
| 323 | ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread)); | ||
| 324 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | 306 | ||
| 328 | if (Has(hr, break_loop) || !uses_wall_clock) { | 307 | u32 ARM_Dynarmic_64::GetSvcNumber() const { |
| 329 | break; | 308 | return svc_swi; |
| 330 | } | ||
| 331 | } | ||
| 332 | } | 309 | } |
| 333 | 310 | ||
| 334 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, | 311 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index aa7054e0c..abfbc3c3f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -39,7 +39,6 @@ public: | |||
| 39 | void SetVectorReg(int index, u128 value) override; | 39 | void SetVectorReg(int index, u128 value) override; |
| 40 | u32 GetPSTATE() const override; | 40 | u32 GetPSTATE() const override; |
| 41 | void SetPSTATE(u32 pstate) override; | 41 | void SetPSTATE(u32 pstate) override; |
| 42 | void Run() override; | ||
| 43 | VAddr GetTlsAddress() const override; | 42 | VAddr GetTlsAddress() const override; |
| 44 | void SetTlsAddress(VAddr address) override; | 43 | void SetTlsAddress(VAddr address) override; |
| 45 | void SetTPIDR_EL0(u64 value) override; | 44 | void SetTPIDR_EL0(u64 value) override; |
| @@ -63,6 +62,11 @@ public: | |||
| 63 | 62 | ||
| 64 | std::vector<BacktraceEntry> GetBacktrace() const override; | 63 | std::vector<BacktraceEntry> GetBacktrace() const override; |
| 65 | 64 | ||
| 65 | protected: | ||
| 66 | Dynarmic::HaltReason RunJit() override; | ||
| 67 | Dynarmic::HaltReason StepJit() override; | ||
| 68 | u32 GetSvcNumber() const override; | ||
| 69 | |||
| 66 | private: | 70 | private: |
| 67 | std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, | 71 | std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, |
| 68 | std::size_t address_space_bits) const; | 72 | std::size_t address_space_bits) const; |
| @@ -87,9 +91,6 @@ private: | |||
| 87 | 91 | ||
| 88 | // SVC callback | 92 | // SVC callback |
| 89 | u32 svc_swi{}; | 93 | u32 svc_swi{}; |
| 90 | |||
| 91 | // Debug restart address | ||
| 92 | u64 breakpoint_pc{}; | ||
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 95 | } // namespace Core | 96 | } // namespace Core |