summaryrefslogtreecommitdiff
path: root/src/core/arm
diff options
context:
space:
mode:
authorGravatar bunnei2020-03-01 23:46:10 -0500
committerGravatar bunnei2020-03-02 21:51:57 -0500
commitc083ea7d7846ee40cfc889ed1d415f73ec78364c (patch)
treec58a597921953ad17f5b233c7e23996f78c2521b /src/core/arm
parentcore: loader: Remove check for 32-bit. (diff)
downloadyuzu-c083ea7d7846ee40cfc889ed1d415f73ec78364c.tar.gz
yuzu-c083ea7d7846ee40cfc889ed1d415f73ec78364c.tar.xz
yuzu-c083ea7d7846ee40cfc889ed1d415f73ec78364c.zip
core: Implement separate A32/A64 ARM interfaces.
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.h32
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp208
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h77
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp (renamed from src/core/arm/dynarmic/arm_dynarmic.cpp)74
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h (renamed from src/core/arm/dynarmic/arm_dynarmic.h)30
-rw-r--r--src/core/arm/exclusive_monitor.cpp2
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp8
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h7
8 files changed, 367 insertions, 71 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 47b964eb7..57eae839e 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -25,7 +25,20 @@ public:
25 explicit ARM_Interface(System& system_) : system{system_} {} 25 explicit ARM_Interface(System& system_) : system{system_} {}
26 virtual ~ARM_Interface() = default; 26 virtual ~ARM_Interface() = default;
27 27
28 struct ThreadContext { 28 struct ThreadContext32 {
29 std::array<u32, 16> cpu_registers;
30 u32 cpsr;
31 std::array<u8, 4> padding;
32 std::array<u64, 32> fprs;
33 u32 fpscr;
34 u32 fpexc;
35 u32 tpidr;
36 };
37 // Internally within the kernel, it expects the AArch32 version of the
38 // thread context to be 344 bytes in size.
39 static_assert(sizeof(ThreadContext32) == 0x158);
40
41 struct ThreadContext64 {
29 std::array<u64, 31> cpu_registers; 42 std::array<u64, 31> cpu_registers;
30 u64 sp; 43 u64 sp;
31 u64 pc; 44 u64 pc;
@@ -38,7 +51,7 @@ public:
38 }; 51 };
39 // Internally within the kernel, it expects the AArch64 version of the 52 // Internally within the kernel, it expects the AArch64 version of the
40 // thread context to be 800 bytes in size. 53 // thread context to be 800 bytes in size.
41 static_assert(sizeof(ThreadContext) == 0x320); 54 static_assert(sizeof(ThreadContext64) == 0x320);
42 55
43 /// Runs the CPU until an event happens 56 /// Runs the CPU until an event happens
44 virtual void Run() = 0; 57 virtual void Run() = 0;
@@ -130,17 +143,10 @@ public:
130 */ 143 */
131 virtual void SetTPIDR_EL0(u64 value) = 0; 144 virtual void SetTPIDR_EL0(u64 value) = 0;
132 145
133 /** 146 virtual void SaveContext(ThreadContext32& ctx) = 0;
134 * Saves the current CPU context 147 virtual void SaveContext(ThreadContext64& ctx) = 0;
135 * @param ctx Thread context to save 148 virtual void LoadContext(const ThreadContext32& ctx) = 0;
136 */ 149 virtual void LoadContext(const ThreadContext64& ctx) = 0;
137 virtual void SaveContext(ThreadContext& ctx) = 0;
138
139 /**
140 * Loads a CPU context
141 * @param ctx Thread context to load
142 */
143 virtual void LoadContext(const ThreadContext& ctx) = 0;
144 150
145 /// Clears the exclusive monitor's state. 151 /// Clears the exclusive monitor's state.
146 virtual void ClearExclusiveState() = 0; 152 virtual void ClearExclusiveState() = 0;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
new file mode 100644
index 000000000..187a972ac
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -0,0 +1,208 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cinttypes>
6#include <memory>
7#include <dynarmic/A32/a32.h>
8#include <dynarmic/A32/config.h>
9#include <dynarmic/A32/context.h>
10#include "common/microprofile.h"
11#include "core/arm/dynarmic/arm_dynarmic_32.h"
12#include "core/arm/dynarmic/arm_dynarmic_64.h"
13#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
14#include "core/core.h"
15#include "core/core_manager.h"
16#include "core/core_timing.h"
17#include "core/hle/kernel/svc.h"
18#include "core/memory.h"
19
20namespace Core {
21
22class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
23public:
24 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent) : parent(parent) {}
25
26 u8 MemoryRead8(u32 vaddr) override {
27 return parent.system.Memory().Read8(vaddr);
28 }
29 u16 MemoryRead16(u32 vaddr) override {
30 return parent.system.Memory().Read16(vaddr);
31 }
32 u32 MemoryRead32(u32 vaddr) override {
33 return parent.system.Memory().Read32(vaddr);
34 }
35 u64 MemoryRead64(u32 vaddr) override {
36 return parent.system.Memory().Read64(vaddr);
37 }
38
39 void MemoryWrite8(u32 vaddr, u8 value) override {
40 parent.system.Memory().Write8(vaddr, value);
41 }
42 void MemoryWrite16(u32 vaddr, u16 value) override {
43 parent.system.Memory().Write16(vaddr, value);
44 }
45 void MemoryWrite32(u32 vaddr, u32 value) override {
46 parent.system.Memory().Write32(vaddr, value);
47 }
48 void MemoryWrite64(u32 vaddr, u64 value) override {
49 parent.system.Memory().Write64(vaddr, value);
50 }
51
52 void InterpreterFallback(u32 pc, std::size_t num_instructions) override {
53 UNIMPLEMENTED();
54 }
55
56 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
57 switch (exception) {
58 case Dynarmic::A32::Exception::UndefinedInstruction:
59 case Dynarmic::A32::Exception::UnpredictableInstruction:
60 break;
61 case Dynarmic::A32::Exception::Breakpoint:
62 break;
63 }
64 LOG_CRITICAL(HW_GPU, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
65 static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
66 UNIMPLEMENTED();
67 }
68
69 void CallSVC(u32 swi) override {
70 Kernel::CallSVC(parent.system, swi);
71 }
72
73 void AddTicks(u64 ticks) override {
74 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
75 // rough approximation of the amount of executed ticks in the system, it may be thrown off
76 // if not all cores are doing a similar amount of work. Instead of doing this, we should
77 // device a way so that timing is consistent across all cores without increasing the ticks 4
78 // times.
79 u64 amortized_ticks = (ticks - num_interpreted_instructions) / Core::NUM_CPU_CORES;
80 // Always execute at least one tick.
81 amortized_ticks = std::max<u64>(amortized_ticks, 1);
82
83 parent.system.CoreTiming().AddTicks(amortized_ticks);
84 num_interpreted_instructions = 0;
85 }
86 u64 GetTicksRemaining() override {
87 return std::max(parent.system.CoreTiming().GetDowncount(), {});
88 }
89
90 ARM_Dynarmic_32& parent;
91 std::size_t num_interpreted_instructions{};
92 u64 tpidrro_el0{};
93 u64 tpidr_el0{};
94};
95
96std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table,
97 std::size_t address_space_bits) const {
98 Dynarmic::A32::UserConfig config;
99 config.callbacks = cb.get();
100 // TODO(bunnei): Implement page table for 32-bit
101 // config.page_table = &page_table.pointers;
102 config.coprocessors[15] = std::make_shared<DynarmicCP15>((u32*)&CP15_regs[0]);
103 config.define_unpredictable_behaviour = true;
104 return std::make_unique<Dynarmic::A32::Jit>(config);
105}
106
107MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_32, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
108
109void ARM_Dynarmic_32::Run() {
110 MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_32);
111 jit->Run();
112}
113
114void ARM_Dynarmic_32::Step() {
115 cb->InterpreterFallback(jit->Regs()[15], 1);
116}
117
118ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor,
119 std::size_t core_index)
120 : ARM_Interface{system},
121 cb(std::make_unique<DynarmicCallbacks32>(*this)), core_index{core_index},
122 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
123
124ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
125
126void ARM_Dynarmic_32::SetPC(u64 pc) {
127 jit->Regs()[15] = static_cast<u32>(pc);
128}
129
130u64 ARM_Dynarmic_32::GetPC() const {
131 return jit->Regs()[15];
132}
133
134u64 ARM_Dynarmic_32::GetReg(int index) const {
135 return jit->Regs()[index];
136}
137
138void ARM_Dynarmic_32::SetReg(int index, u64 value) {
139 jit->Regs()[index] = static_cast<u32>(value);
140}
141
142u128 ARM_Dynarmic_32::GetVectorReg(int index) const {
143 return {};
144}
145
146void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {}
147
148u32 ARM_Dynarmic_32::GetPSTATE() const {
149 return jit->Cpsr();
150}
151
152void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) {
153 jit->SetCpsr(cpsr);
154}
155
156u64 ARM_Dynarmic_32::GetTlsAddress() const {
157 return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
158}
159
160void ARM_Dynarmic_32::SetTlsAddress(VAddr address) {
161 CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address);
162}
163
164u64 ARM_Dynarmic_32::GetTPIDR_EL0() const {
165 return cb->tpidr_el0;
166}
167
168void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
169 cb->tpidr_el0 = value;
170}
171
172void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
173 Dynarmic::A32::Context context;
174 jit->SaveContext(context);
175 ctx.cpu_registers = context.Regs();
176 ctx.cpsr = context.Cpsr();
177}
178
179void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
180 Dynarmic::A32::Context context;
181 context.Regs() = ctx.cpu_registers;
182 context.SetCpsr(ctx.cpsr);
183 jit->LoadContext(context);
184}
185
186void ARM_Dynarmic_32::PrepareReschedule() {
187 jit->HaltExecution();
188}
189
190void ARM_Dynarmic_32::ClearInstructionCache() {
191 jit->ClearCache();
192}
193
194void ARM_Dynarmic_32::ClearExclusiveState() {}
195
196void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
197 std::size_t new_address_space_size_in_bits) {
198 auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
199 auto iter = jit_cache.find(key);
200 if (iter != jit_cache.end()) {
201 jit = iter->second;
202 return;
203 }
204 jit = MakeJit(page_table, new_address_space_size_in_bits);
205 jit_cache.emplace(key, jit);
206}
207
208} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
new file mode 100644
index 000000000..143e46e4d
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -0,0 +1,77 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <unordered_map>
9
10#include <dynarmic/A32/a32.h>
11#include <dynarmic/A64/a64.h>
12#include <dynarmic/A64/exclusive_monitor.h>
13#include "common/common_types.h"
14#include "common/hash.h"
15#include "core/arm/arm_interface.h"
16#include "core/arm/exclusive_monitor.h"
17
18namespace Memory {
19class Memory;
20}
21
22namespace Core {
23
24class DynarmicCallbacks32;
25class DynarmicExclusiveMonitor;
26class System;
27
28class ARM_Dynarmic_32 final : public ARM_Interface {
29public:
30 ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
31 ~ARM_Dynarmic_32() override;
32
33 void SetPC(u64 pc) override;
34 u64 GetPC() const override;
35 u64 GetReg(int index) const override;
36 void SetReg(int index, u64 value) override;
37 u128 GetVectorReg(int index) const override;
38 void SetVectorReg(int index, u128 value) override;
39 u32 GetPSTATE() const override;
40 void SetPSTATE(u32 pstate) override;
41 void Run() override;
42 void Step() override;
43 VAddr GetTlsAddress() const override;
44 void SetTlsAddress(VAddr address) override;
45 void SetTPIDR_EL0(u64 value) override;
46 u64 GetTPIDR_EL0() const override;
47
48 void SaveContext(ThreadContext32& ctx) override;
49 void SaveContext(ThreadContext64& ctx) override {}
50 void LoadContext(const ThreadContext32& ctx) override;
51 void LoadContext(const ThreadContext64& ctx) override {}
52
53 void PrepareReschedule() override;
54 void ClearExclusiveState() override;
55
56 void ClearInstructionCache() override;
57 void PageTableChanged(Common::PageTable& new_page_table,
58 std::size_t new_address_space_size_in_bits) override;
59
60private:
61 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable& page_table,
62 std::size_t address_space_bits) const;
63
64 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
65 using JitCacheType =
66 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>;
67
68 friend class DynarmicCallbacks32;
69 std::unique_ptr<DynarmicCallbacks32> cb;
70 JitCacheType jit_cache;
71 std::shared_ptr<Dynarmic::A32::Jit> jit;
72 std::size_t core_index;
73 DynarmicExclusiveMonitor& exclusive_monitor;
74 std::array<u32, 84> CP15_regs{};
75};
76
77} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 7c9d59ab8..a53a58ba0 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -8,7 +8,7 @@
8#include <dynarmic/A64/config.h> 8#include <dynarmic/A64/config.h>
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "core/arm/dynarmic/arm_dynarmic.h" 11#include "core/arm/dynarmic/arm_dynarmic_64.h"
12#include "core/core.h" 12#include "core/core.h"
13#include "core/core_manager.h" 13#include "core/core_manager.h"
14#include "core/core_timing.h" 14#include "core/core_timing.h"
@@ -25,9 +25,9 @@ namespace Core {
25 25
26using Vector = Dynarmic::A64::Vector; 26using Vector = Dynarmic::A64::Vector;
27 27
28class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks { 28class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
29public: 29public:
30 explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {} 30 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {}
31 31
32 u8 MemoryRead8(u64 vaddr) override { 32 u8 MemoryRead8(u64 vaddr) override {
33 return parent.system.Memory().Read8(vaddr); 33 return parent.system.Memory().Read8(vaddr);
@@ -68,7 +68,7 @@ public:
68 LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc, 68 LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc,
69 num_instructions, MemoryReadCode(pc)); 69 num_instructions, MemoryReadCode(pc));
70 70
71 ARM_Interface::ThreadContext ctx; 71 ARM_Interface::ThreadContext64 ctx;
72 parent.SaveContext(ctx); 72 parent.SaveContext(ctx);
73 parent.inner_unicorn.LoadContext(ctx); 73 parent.inner_unicorn.LoadContext(ctx);
74 parent.inner_unicorn.ExecuteInstructions(num_instructions); 74 parent.inner_unicorn.ExecuteInstructions(num_instructions);
@@ -90,7 +90,7 @@ public:
90 parent.jit->HaltExecution(); 90 parent.jit->HaltExecution();
91 parent.SetPC(pc); 91 parent.SetPC(pc);
92 Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread(); 92 Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread();
93 parent.SaveContext(thread->GetContext()); 93 parent.SaveContext(thread->GetContext64());
94 GDBStub::Break(); 94 GDBStub::Break();
95 GDBStub::SendTrap(thread, 5); 95 GDBStub::SendTrap(thread, 5);
96 return; 96 return;
@@ -126,14 +126,14 @@ public:
126 return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks()); 126 return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks());
127 } 127 }
128 128
129 ARM_Dynarmic& parent; 129 ARM_Dynarmic_64& parent;
130 std::size_t num_interpreted_instructions = 0; 130 std::size_t num_interpreted_instructions = 0;
131 u64 tpidrro_el0 = 0; 131 u64 tpidrro_el0 = 0;
132 u64 tpidr_el0 = 0; 132 u64 tpidr_el0 = 0;
133}; 133};
134 134
135std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table, 135std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table,
136 std::size_t address_space_bits) const { 136 std::size_t address_space_bits) const {
137 Dynarmic::A64::UserConfig config; 137 Dynarmic::A64::UserConfig config;
138 138
139 // Callbacks 139 // Callbacks
@@ -162,76 +162,76 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag
162 return std::make_shared<Dynarmic::A64::Jit>(config); 162 return std::make_shared<Dynarmic::A64::Jit>(config);
163} 163}
164 164
165MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); 165MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
166 166
167void ARM_Dynarmic::Run() { 167void ARM_Dynarmic_64::Run() {
168 MICROPROFILE_SCOPE(ARM_Jit_Dynarmic); 168 MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_64);
169 169
170 jit->Run(); 170 jit->Run();
171} 171}
172 172
173void ARM_Dynarmic::Step() { 173void ARM_Dynarmic_64::Step() {
174 cb->InterpreterFallback(jit->GetPC(), 1); 174 cb->InterpreterFallback(jit->GetPC(), 1);
175} 175}
176 176
177ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, 177ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor,
178 std::size_t core_index) 178 std::size_t core_index)
179 : ARM_Interface{system}, 179 : ARM_Interface{system},
180 cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system}, 180 cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system},
181 core_index{core_index}, exclusive_monitor{ 181 core_index{core_index}, exclusive_monitor{
182 dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} 182 dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
183 183
184ARM_Dynarmic::~ARM_Dynarmic() = default; 184ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
185 185
186void ARM_Dynarmic::SetPC(u64 pc) { 186void ARM_Dynarmic_64::SetPC(u64 pc) {
187 jit->SetPC(pc); 187 jit->SetPC(pc);
188} 188}
189 189
190u64 ARM_Dynarmic::GetPC() const { 190u64 ARM_Dynarmic_64::GetPC() const {
191 return jit->GetPC(); 191 return jit->GetPC();
192} 192}
193 193
194u64 ARM_Dynarmic::GetReg(int index) const { 194u64 ARM_Dynarmic_64::GetReg(int index) const {
195 return jit->GetRegister(index); 195 return jit->GetRegister(index);
196} 196}
197 197
198void ARM_Dynarmic::SetReg(int index, u64 value) { 198void ARM_Dynarmic_64::SetReg(int index, u64 value) {
199 jit->SetRegister(index, value); 199 jit->SetRegister(index, value);
200} 200}
201 201
202u128 ARM_Dynarmic::GetVectorReg(int index) const { 202u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
203 return jit->GetVector(index); 203 return jit->GetVector(index);
204} 204}
205 205
206void ARM_Dynarmic::SetVectorReg(int index, u128 value) { 206void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
207 jit->SetVector(index, value); 207 jit->SetVector(index, value);
208} 208}
209 209
210u32 ARM_Dynarmic::GetPSTATE() const { 210u32 ARM_Dynarmic_64::GetPSTATE() const {
211 return jit->GetPstate(); 211 return jit->GetPstate();
212} 212}
213 213
214void ARM_Dynarmic::SetPSTATE(u32 pstate) { 214void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
215 jit->SetPstate(pstate); 215 jit->SetPstate(pstate);
216} 216}
217 217
218u64 ARM_Dynarmic::GetTlsAddress() const { 218u64 ARM_Dynarmic_64::GetTlsAddress() const {
219 return cb->tpidrro_el0; 219 return cb->tpidrro_el0;
220} 220}
221 221
222void ARM_Dynarmic::SetTlsAddress(VAddr address) { 222void ARM_Dynarmic_64::SetTlsAddress(VAddr address) {
223 cb->tpidrro_el0 = address; 223 cb->tpidrro_el0 = address;
224} 224}
225 225
226u64 ARM_Dynarmic::GetTPIDR_EL0() const { 226u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {
227 return cb->tpidr_el0; 227 return cb->tpidr_el0;
228} 228}
229 229
230void ARM_Dynarmic::SetTPIDR_EL0(u64 value) { 230void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
231 cb->tpidr_el0 = value; 231 cb->tpidr_el0 = value;
232} 232}
233 233
234void ARM_Dynarmic::SaveContext(ThreadContext& ctx) { 234void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
235 ctx.cpu_registers = jit->GetRegisters(); 235 ctx.cpu_registers = jit->GetRegisters();
236 ctx.sp = jit->GetSP(); 236 ctx.sp = jit->GetSP();
237 ctx.pc = jit->GetPC(); 237 ctx.pc = jit->GetPC();
@@ -242,7 +242,7 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
242 ctx.tpidr = cb->tpidr_el0; 242 ctx.tpidr = cb->tpidr_el0;
243} 243}
244 244
245void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { 245void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
246 jit->SetRegisters(ctx.cpu_registers); 246 jit->SetRegisters(ctx.cpu_registers);
247 jit->SetSP(ctx.sp); 247 jit->SetSP(ctx.sp);
248 jit->SetPC(ctx.pc); 248 jit->SetPC(ctx.pc);
@@ -253,20 +253,20 @@ void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
253 SetTPIDR_EL0(ctx.tpidr); 253 SetTPIDR_EL0(ctx.tpidr);
254} 254}
255 255
256void ARM_Dynarmic::PrepareReschedule() { 256void ARM_Dynarmic_64::PrepareReschedule() {
257 jit->HaltExecution(); 257 jit->HaltExecution();
258} 258}
259 259
260void ARM_Dynarmic::ClearInstructionCache() { 260void ARM_Dynarmic_64::ClearInstructionCache() {
261 jit->ClearCache(); 261 jit->ClearCache();
262} 262}
263 263
264void ARM_Dynarmic::ClearExclusiveState() { 264void ARM_Dynarmic_64::ClearExclusiveState() {
265 jit->ClearExclusiveState(); 265 jit->ClearExclusiveState();
266} 266}
267 267
268void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table, 268void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
269 std::size_t new_address_space_size_in_bits) { 269 std::size_t new_address_space_size_in_bits) {
270 auto key = std::make_pair(&page_table, new_address_space_size_in_bits); 270 auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
271 auto iter = jit_cache.find(key); 271 auto iter = jit_cache.find(key);
272 if (iter != jit_cache.end()) { 272 if (iter != jit_cache.end()) {
@@ -277,8 +277,8 @@ void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,
277 jit_cache.emplace(key, jit); 277 jit_cache.emplace(key, jit);
278} 278}
279 279
280DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count) 280DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count)
281 : monitor(core_count), memory{memory_} {} 281 : monitor(core_count), memory{memory} {}
282 282
283DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; 283DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
284 284
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index ffbb69d76..e71240a96 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -21,18 +21,14 @@ class Memory;
21 21
22namespace Core { 22namespace Core {
23 23
24class ARM_Dynarmic_Callbacks; 24class DynarmicCallbacks64;
25class DynarmicExclusiveMonitor; 25class DynarmicExclusiveMonitor;
26class System; 26class System;
27 27
28using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; 28class ARM_Dynarmic_64 final : public ARM_Interface {
29using JitCacheType =
30 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;
31
32class ARM_Dynarmic final : public ARM_Interface {
33public: 29public:
34 ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); 30 ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
35 ~ARM_Dynarmic() override; 31 ~ARM_Dynarmic_64() override;
36 32
37 void SetPC(u64 pc) override; 33 void SetPC(u64 pc) override;
38 u64 GetPC() const override; 34 u64 GetPC() const override;
@@ -49,8 +45,10 @@ public:
49 void SetTPIDR_EL0(u64 value) override; 45 void SetTPIDR_EL0(u64 value) override;
50 u64 GetTPIDR_EL0() const override; 46 u64 GetTPIDR_EL0() const override;
51 47
52 void SaveContext(ThreadContext& ctx) override; 48 void SaveContext(ThreadContext32& ctx) override {}
53 void LoadContext(const ThreadContext& ctx) override; 49 void SaveContext(ThreadContext64& ctx) override;
50 void LoadContext(const ThreadContext32& ctx) override {}
51 void LoadContext(const ThreadContext64& ctx) override;
54 52
55 void PrepareReschedule() override; 53 void PrepareReschedule() override;
56 void ClearExclusiveState() override; 54 void ClearExclusiveState() override;
@@ -63,8 +61,12 @@ private:
63 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table, 61 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
64 std::size_t address_space_bits) const; 62 std::size_t address_space_bits) const;
65 63
66 friend class ARM_Dynarmic_Callbacks; 64 using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
67 std::unique_ptr<ARM_Dynarmic_Callbacks> cb; 65 using JitCacheType =
66 std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;
67
68 friend class DynarmicCallbacks64;
69 std::unique_ptr<DynarmicCallbacks64> cb;
68 JitCacheType jit_cache; 70 JitCacheType jit_cache;
69 std::shared_ptr<Dynarmic::A64::Jit> jit; 71 std::shared_ptr<Dynarmic::A64::Jit> jit;
70 ARM_Unicorn inner_unicorn; 72 ARM_Unicorn inner_unicorn;
@@ -75,7 +77,7 @@ private:
75 77
76class DynarmicExclusiveMonitor final : public ExclusiveMonitor { 78class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
77public: 79public:
78 explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count); 80 explicit DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count);
79 ~DynarmicExclusiveMonitor() override; 81 ~DynarmicExclusiveMonitor() override;
80 82
81 void SetExclusive(std::size_t core_index, VAddr addr) override; 83 void SetExclusive(std::size_t core_index, VAddr addr) override;
@@ -88,7 +90,7 @@ public:
88 bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override; 90 bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override;
89 91
90private: 92private:
91 friend class ARM_Dynarmic; 93 friend class ARM_Dynarmic_64;
92 Dynarmic::A64::ExclusiveMonitor monitor; 94 Dynarmic::A64::ExclusiveMonitor monitor;
93 Memory::Memory& memory; 95 Memory::Memory& memory;
94}; 96};
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
index 94570e520..b32401e0b 100644
--- a/src/core/arm/exclusive_monitor.cpp
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -3,7 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#ifdef ARCHITECTURE_x86_64 5#ifdef ARCHITECTURE_x86_64
6#include "core/arm/dynarmic/arm_dynarmic.h" 6#include "core/arm/dynarmic/arm_dynarmic_64.h"
7#endif 7#endif
8#include "core/arm/exclusive_monitor.h" 8#include "core/arm/exclusive_monitor.h"
9#include "core/memory.h" 9#include "core/memory.h"
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index f99ad5802..8a9800a96 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -53,7 +53,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
53 void* user_data) { 53 void* user_data) {
54 auto* const system = static_cast<System*>(user_data); 54 auto* const system = static_cast<System*>(user_data);
55 55
56 ARM_Interface::ThreadContext ctx{}; 56 ARM_Interface::ThreadContext64 ctx{};
57 system->CurrentArmInterface().SaveContext(ctx); 57 system->CurrentArmInterface().SaveContext(ctx);
58 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr, 58 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
59 ctx.pc, ctx.cpu_registers[30]); 59 ctx.pc, ctx.cpu_registers[30]);
@@ -179,7 +179,7 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
179 } 179 }
180 180
181 Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread(); 181 Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread();
182 SaveContext(thread->GetContext()); 182 SaveContext(thread->GetContext64());
183 if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) { 183 if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {
184 last_bkpt_hit = false; 184 last_bkpt_hit = false;
185 GDBStub::Break(); 185 GDBStub::Break();
@@ -188,7 +188,7 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
188 } 188 }
189} 189}
190 190
191void ARM_Unicorn::SaveContext(ThreadContext& ctx) { 191void ARM_Unicorn::SaveContext(ThreadContext64& ctx) {
192 int uregs[32]; 192 int uregs[32];
193 void* tregs[32]; 193 void* tregs[32];
194 194
@@ -215,7 +215,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
215 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32)); 215 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
216} 216}
217 217
218void ARM_Unicorn::LoadContext(const ThreadContext& ctx) { 218void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) {
219 int uregs[32]; 219 int uregs[32];
220 void* tregs[32]; 220 void* tregs[32];
221 221
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index 3c5b155f9..f30d13cb6 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -30,8 +30,6 @@ public:
30 void SetTlsAddress(VAddr address) override; 30 void SetTlsAddress(VAddr address) override;
31 void SetTPIDR_EL0(u64 value) override; 31 void SetTPIDR_EL0(u64 value) override;
32 u64 GetTPIDR_EL0() const override; 32 u64 GetTPIDR_EL0() const override;
33 void SaveContext(ThreadContext& ctx) override;
34 void LoadContext(const ThreadContext& ctx) override;
35 void PrepareReschedule() override; 33 void PrepareReschedule() override;
36 void ClearExclusiveState() override; 34 void ClearExclusiveState() override;
37 void ExecuteInstructions(std::size_t num_instructions); 35 void ExecuteInstructions(std::size_t num_instructions);
@@ -41,6 +39,11 @@ public:
41 void PageTableChanged(Common::PageTable&, std::size_t) override {} 39 void PageTableChanged(Common::PageTable&, std::size_t) override {}
42 void RecordBreak(GDBStub::BreakpointAddress bkpt); 40 void RecordBreak(GDBStub::BreakpointAddress bkpt);
43 41
42 void SaveContext(ThreadContext32& ctx) override {}
43 void SaveContext(ThreadContext64& ctx) override;
44 void LoadContext(const ThreadContext32& ctx) override {}
45 void LoadContext(const ThreadContext64& ctx) override;
46
44private: 47private:
45 static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data); 48 static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data);
46 49