summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt8
-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/dynarmic/arm_dynarmic_cp15.cpp80
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.h152
-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
-rw-r--r--src/core/core_manager.cpp3
-rw-r--r--src/core/gdbstub/gdbstub.cpp14
-rw-r--r--src/core/hle/kernel/kernel.cpp4
-rw-r--r--src/core/hle/kernel/physical_core.cpp19
-rw-r--r--src/core/hle/kernel/physical_core.h6
-rw-r--r--src/core/hle/kernel/process.cpp3
-rw-r--r--src/core/hle/kernel/scheduler.cpp21
-rw-r--r--src/core/hle/kernel/scheduler.h3
-rw-r--r--src/core/hle/kernel/svc.cpp329
-rw-r--r--src/core/hle/kernel/svc_wrap.h158
-rw-r--r--src/core/hle/kernel/thread.cpp31
-rw-r--r--src/core/hle/kernel/thread.h22
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp6
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
26 files changed, 1068 insertions, 235 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 54be7dc0c..b31a0328c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -595,8 +595,12 @@ endif()
595 595
596if (ARCHITECTURE_x86_64) 596if (ARCHITECTURE_x86_64)
597 target_sources(core PRIVATE 597 target_sources(core PRIVATE
598 arm/dynarmic/arm_dynarmic.cpp 598 arm/dynarmic/arm_dynarmic_32.cpp
599 arm/dynarmic/arm_dynarmic.h 599 arm/dynarmic/arm_dynarmic_32.h
600 arm/dynarmic/arm_dynarmic_64.cpp
601 arm/dynarmic/arm_dynarmic_64.h
602 arm/dynarmic/arm_dynarmic_cp15.cpp
603 arm/dynarmic/arm_dynarmic_cp15.h
600 ) 604 )
601 target_link_libraries(core PRIVATE dynarmic) 605 target_link_libraries(core PRIVATE dynarmic)
602endif() 606endif()
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/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
new file mode 100644
index 000000000..3fdcdebde
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
@@ -0,0 +1,80 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
6
7using Callback = Dynarmic::A32::Coprocessor::Callback;
8using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
9using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
10
11std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1,
12 CoprocReg CRd, CoprocReg CRn,
13 CoprocReg CRm, unsigned opc2) {
14 return {};
15}
16
17CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
18 CoprocReg CRm, unsigned opc2) {
19 // TODO(merry): Privileged CP15 registers
20
21 if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) {
22 // This is a dummy write, we ignore the value written here.
23 return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)];
24 }
25
26 if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) {
27 switch (opc2) {
28 case 4:
29 // This is a dummy write, we ignore the value written here.
30 return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)];
31 case 5:
32 // This is a dummy write, we ignore the value written here.
33 return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_MEMORY_BARRIER)];
34 default:
35 return {};
36 }
37 }
38
39 if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) {
40 return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
41 }
42
43 return {};
44}
45
46CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) {
47 return {};
48}
49
50CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn,
51 CoprocReg CRm, unsigned opc2) {
52 // TODO(merry): Privileged CP15 registers
53
54 if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) {
55 switch (opc2) {
56 case 2:
57 return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
58 case 3:
59 return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
60 default:
61 return {};
62 }
63 }
64
65 return {};
66}
67
68CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) {
69 return {};
70}
71
72std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
73 std::optional<u8> option) {
74 return {};
75}
76
77std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
78 std::optional<u8> option) {
79 return {};
80}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
new file mode 100644
index 000000000..07bcde5f9
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
@@ -0,0 +1,152 @@
1// Copyright 2017 Citra Emulator Project
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 <optional>
9
10#include <dynarmic/A32/coprocessor.h>
11#include "common/common_types.h"
12
13enum class CP15Register {
14 // c0 - Information registers
15 CP15_MAIN_ID,
16 CP15_CACHE_TYPE,
17 CP15_TCM_STATUS,
18 CP15_TLB_TYPE,
19 CP15_CPU_ID,
20 CP15_PROCESSOR_FEATURE_0,
21 CP15_PROCESSOR_FEATURE_1,
22 CP15_DEBUG_FEATURE_0,
23 CP15_AUXILIARY_FEATURE_0,
24 CP15_MEMORY_MODEL_FEATURE_0,
25 CP15_MEMORY_MODEL_FEATURE_1,
26 CP15_MEMORY_MODEL_FEATURE_2,
27 CP15_MEMORY_MODEL_FEATURE_3,
28 CP15_ISA_FEATURE_0,
29 CP15_ISA_FEATURE_1,
30 CP15_ISA_FEATURE_2,
31 CP15_ISA_FEATURE_3,
32 CP15_ISA_FEATURE_4,
33
34 // c1 - Control registers
35 CP15_CONTROL,
36 CP15_AUXILIARY_CONTROL,
37 CP15_COPROCESSOR_ACCESS_CONTROL,
38
39 // c2 - Translation table registers
40 CP15_TRANSLATION_BASE_TABLE_0,
41 CP15_TRANSLATION_BASE_TABLE_1,
42 CP15_TRANSLATION_BASE_CONTROL,
43 CP15_DOMAIN_ACCESS_CONTROL,
44 CP15_RESERVED,
45
46 // c5 - Fault status registers
47 CP15_FAULT_STATUS,
48 CP15_INSTR_FAULT_STATUS,
49 CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
50 CP15_INST_FSR,
51
52 // c6 - Fault Address registers
53 CP15_FAULT_ADDRESS,
54 CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
55 CP15_WFAR,
56 CP15_IFAR,
57
58 // c7 - Cache operation registers
59 CP15_WAIT_FOR_INTERRUPT,
60 CP15_PHYS_ADDRESS,
61 CP15_INVALIDATE_INSTR_CACHE,
62 CP15_INVALIDATE_INSTR_CACHE_USING_MVA,
63 CP15_INVALIDATE_INSTR_CACHE_USING_INDEX,
64 CP15_FLUSH_PREFETCH_BUFFER,
65 CP15_FLUSH_BRANCH_TARGET_CACHE,
66 CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY,
67 CP15_INVALIDATE_DATA_CACHE,
68 CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
69 CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
70 CP15_INVALIDATE_DATA_AND_INSTR_CACHE,
71 CP15_CLEAN_DATA_CACHE,
72 CP15_CLEAN_DATA_CACHE_LINE_USING_MVA,
73 CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX,
74 CP15_DATA_SYNC_BARRIER,
75 CP15_DATA_MEMORY_BARRIER,
76 CP15_CLEAN_AND_INVALIDATE_DATA_CACHE,
77 CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
78 CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
79
80 // c8 - TLB operations
81 CP15_INVALIDATE_ITLB,
82 CP15_INVALIDATE_ITLB_SINGLE_ENTRY,
83 CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH,
84 CP15_INVALIDATE_ITLB_ENTRY_ON_MVA,
85 CP15_INVALIDATE_DTLB,
86 CP15_INVALIDATE_DTLB_SINGLE_ENTRY,
87 CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH,
88 CP15_INVALIDATE_DTLB_ENTRY_ON_MVA,
89 CP15_INVALIDATE_UTLB,
90 CP15_INVALIDATE_UTLB_SINGLE_ENTRY,
91 CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH,
92 CP15_INVALIDATE_UTLB_ENTRY_ON_MVA,
93
94 // c9 - Data cache lockdown register
95 CP15_DATA_CACHE_LOCKDOWN,
96
97 // c10 - TLB/Memory map registers
98 CP15_TLB_LOCKDOWN,
99 CP15_PRIMARY_REGION_REMAP,
100 CP15_NORMAL_REGION_REMAP,
101
102 // c13 - Thread related registers
103 CP15_PID,
104 CP15_CONTEXT_ID,
105 CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
106 CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W)
107 CP15_THREAD_PRW, // Thread ID register - Privileged R/W only.
108
109 // c15 - Performance and TLB lockdown registers
110 CP15_PERFORMANCE_MONITOR_CONTROL,
111 CP15_CYCLE_COUNTER,
112 CP15_COUNT_0,
113 CP15_COUNT_1,
114 CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY,
115 CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY,
116 CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS,
117 CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS,
118 CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE,
119 CP15_TLB_DEBUG_CONTROL,
120
121 // Skyeye defined
122 CP15_TLB_FAULT_ADDR,
123 CP15_TLB_FAULT_STATUS,
124
125 // Not an actual register.
126 // All registers should be defined above this.
127 CP15_REGISTER_COUNT,
128};
129
130class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {
131public:
132 using CoprocReg = Dynarmic::A32::CoprocReg;
133
134 explicit DynarmicCP15(u32* cp15) : CP15(cp15){};
135
136 std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,
137 CoprocReg CRn, CoprocReg CRm,
138 unsigned opc2) override;
139 CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
140 CoprocReg CRm, unsigned opc2) override;
141 CallbackOrAccessTwoWords CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
142 CallbackOrAccessOneWord CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, CoprocReg CRm,
143 unsigned opc2) override;
144 CallbackOrAccessTwoWords CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
145 std::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
146 std::optional<u8> option) override;
147 std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
148 std::optional<u8> option) override;
149
150private:
151 u32* CP15{};
152};
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
diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp
index 8eacf92dd..b6b797c80 100644
--- a/src/core/core_manager.cpp
+++ b/src/core/core_manager.cpp
@@ -6,9 +6,6 @@
6#include <mutex> 6#include <mutex>
7 7
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#ifdef ARCHITECTURE_x86_64
10#include "core/arm/dynarmic/arm_dynarmic.h"
11#endif
12#include "core/arm/exclusive_monitor.h" 9#include "core/arm/exclusive_monitor.h"
13#include "core/arm/unicorn/arm_unicorn.h" 10#include "core/arm/unicorn/arm_unicorn.h"
14#include "core/core.h" 11#include "core/core.h"
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 67e95999d..e8d8871a7 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -217,7 +217,7 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
217 return 0; 217 return 0;
218 } 218 }
219 219
220 const auto& thread_context = thread->GetContext(); 220 const auto& thread_context = thread->GetContext64();
221 221
222 if (id < SP_REGISTER) { 222 if (id < SP_REGISTER) {
223 return thread_context.cpu_registers[id]; 223 return thread_context.cpu_registers[id];
@@ -239,7 +239,7 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
239 return; 239 return;
240 } 240 }
241 241
242 auto& thread_context = thread->GetContext(); 242 auto& thread_context = thread->GetContext64();
243 243
244 if (id < SP_REGISTER) { 244 if (id < SP_REGISTER) {
245 thread_context.cpu_registers[id] = val; 245 thread_context.cpu_registers[id] = val;
@@ -259,7 +259,7 @@ static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {
259 return u128{0}; 259 return u128{0};
260 } 260 }
261 261
262 auto& thread_context = thread->GetContext(); 262 auto& thread_context = thread->GetContext64();
263 263
264 if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { 264 if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
265 return thread_context.vector_registers[id - UC_ARM64_REG_Q0]; 265 return thread_context.vector_registers[id - UC_ARM64_REG_Q0];
@@ -275,7 +275,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
275 return; 275 return;
276 } 276 }
277 277
278 auto& thread_context = thread->GetContext(); 278 auto& thread_context = thread->GetContext64();
279 279
280 if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { 280 if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
281 thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val; 281 thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
@@ -916,7 +916,7 @@ static void WriteRegister() {
916 // Update ARM context, skipping scheduler - no running threads at this point 916 // Update ARM context, skipping scheduler - no running threads at this point
917 Core::System::GetInstance() 917 Core::System::GetInstance()
918 .ArmInterface(current_core) 918 .ArmInterface(current_core)
919 .LoadContext(current_thread->GetContext()); 919 .LoadContext(current_thread->GetContext64());
920 920
921 SendReply("OK"); 921 SendReply("OK");
922} 922}
@@ -947,7 +947,7 @@ static void WriteRegisters() {
947 // Update ARM context, skipping scheduler - no running threads at this point 947 // Update ARM context, skipping scheduler - no running threads at this point
948 Core::System::GetInstance() 948 Core::System::GetInstance()
949 .ArmInterface(current_core) 949 .ArmInterface(current_core)
950 .LoadContext(current_thread->GetContext()); 950 .LoadContext(current_thread->GetContext64());
951 951
952 SendReply("OK"); 952 SendReply("OK");
953} 953}
@@ -1019,7 +1019,7 @@ static void Step() {
1019 // Update ARM context, skipping scheduler - no running threads at this point 1019 // Update ARM context, skipping scheduler - no running threads at this point
1020 Core::System::GetInstance() 1020 Core::System::GetInstance()
1021 .ArmInterface(current_core) 1021 .ArmInterface(current_core)
1022 .LoadContext(current_thread->GetContext()); 1022 .LoadContext(current_thread->GetContext64());
1023 } 1023 }
1024 step_loop = true; 1024 step_loop = true;
1025 halt_loop = true; 1025 halt_loop = true;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 9232f4d7e..e47f1deed 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -186,6 +186,10 @@ struct KernelCore::Impl {
186 return; 186 return;
187 } 187 }
188 188
189 for (auto& core : cores) {
190 core.SetIs64Bit(process->Is64BitProcess());
191 }
192
189 system.Memory().SetCurrentPageTable(*process); 193 system.Memory().SetCurrentPageTable(*process);
190 } 194 }
191 195
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index 9303dd273..aa2787467 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -5,7 +5,8 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/arm/arm_interface.h" 6#include "core/arm/arm_interface.h"
7#ifdef ARCHITECTURE_x86_64 7#ifdef ARCHITECTURE_x86_64
8#include "core/arm/dynarmic/arm_dynarmic.h" 8#include "core/arm/dynarmic/arm_dynarmic_32.h"
9#include "core/arm/dynarmic/arm_dynarmic_64.h"
9#endif 10#endif
10#include "core/arm/exclusive_monitor.h" 11#include "core/arm/exclusive_monitor.h"
11#include "core/arm/unicorn/arm_unicorn.h" 12#include "core/arm/unicorn/arm_unicorn.h"
@@ -20,13 +21,17 @@ PhysicalCore::PhysicalCore(Core::System& system, std::size_t id,
20 Core::ExclusiveMonitor& exclusive_monitor) 21 Core::ExclusiveMonitor& exclusive_monitor)
21 : core_index{id} { 22 : core_index{id} {
22#ifdef ARCHITECTURE_x86_64 23#ifdef ARCHITECTURE_x86_64
23 arm_interface = std::make_unique<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index); 24 arm_interface_32 =
25 std::make_unique<Core::ARM_Dynarmic_32>(system, exclusive_monitor, core_index);
26 arm_interface_64 =
27 std::make_unique<Core::ARM_Dynarmic_64>(system, exclusive_monitor, core_index);
28
24#else 29#else
25 arm_interface = std::make_shared<Core::ARM_Unicorn>(system); 30 arm_interface = std::make_shared<Core::ARM_Unicorn>(system);
26 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); 31 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
27#endif 32#endif
28 33
29 scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index); 34 scheduler = std::make_unique<Kernel::Scheduler>(system, core_index);
30} 35}
31 36
32PhysicalCore::~PhysicalCore() = default; 37PhysicalCore::~PhysicalCore() = default;
@@ -48,4 +53,12 @@ void PhysicalCore::Shutdown() {
48 scheduler->Shutdown(); 53 scheduler->Shutdown();
49} 54}
50 55
56void PhysicalCore::SetIs64Bit(bool is_64_bit) {
57 if (is_64_bit) {
58 arm_interface = arm_interface_64.get();
59 } else {
60 arm_interface = arm_interface_32.get();
61 }
62}
63
51} // namespace Kernel 64} // namespace Kernel
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h
index 4c32c0f1b..3269166be 100644
--- a/src/core/hle/kernel/physical_core.h
+++ b/src/core/hle/kernel/physical_core.h
@@ -68,10 +68,14 @@ public:
68 return *scheduler; 68 return *scheduler;
69 } 69 }
70 70
71 void SetIs64Bit(bool is_64_bit);
72
71private: 73private:
72 std::size_t core_index; 74 std::size_t core_index;
73 std::unique_ptr<Core::ARM_Interface> arm_interface; 75 std::unique_ptr<Core::ARM_Interface> arm_interface_32;
76 std::unique_ptr<Core::ARM_Interface> arm_interface_64;
74 std::unique_ptr<Kernel::Scheduler> scheduler; 77 std::unique_ptr<Kernel::Scheduler> scheduler;
78 Core::ARM_Interface* arm_interface{};
75}; 79};
76 80
77} // namespace Kernel 81} // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 2fcb7326c..edc414d69 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -42,7 +42,8 @@ void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
42 42
43 // Register 1 must be a handle to the main thread 43 // Register 1 must be a handle to the main thread
44 const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); 44 const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
45 thread->GetContext().cpu_registers[1] = thread_handle; 45 thread->GetContext32().cpu_registers[1] = thread_handle;
46 thread->GetContext64().cpu_registers[1] = thread_handle;
46 47
47 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires 48 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
48 thread->ResumeFromWait(); 49 thread->ResumeFromWait();
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index c65f82fb7..1140c72a3 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -383,8 +383,8 @@ void GlobalScheduler::Unlock() {
383 // TODO(Blinkhawk): Setup the interrupts and change context on current core. 383 // TODO(Blinkhawk): Setup the interrupts and change context on current core.
384} 384}
385 385
386Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) 386Scheduler::Scheduler(Core::System& system, std::size_t core_id)
387 : system(system), cpu_core(cpu_core), core_id(core_id) {} 387 : system{system}, core_id{core_id} {}
388 388
389Scheduler::~Scheduler() = default; 389Scheduler::~Scheduler() = default;
390 390
@@ -422,9 +422,10 @@ void Scheduler::UnloadThread() {
422 422
423 // Save context for previous thread 423 // Save context for previous thread
424 if (previous_thread) { 424 if (previous_thread) {
425 cpu_core.SaveContext(previous_thread->GetContext()); 425 system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32());
426 system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());
426 // Save the TPIDR_EL0 system register in case it was modified. 427 // Save the TPIDR_EL0 system register in case it was modified.
427 previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); 428 previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());
428 429
429 if (previous_thread->GetStatus() == ThreadStatus::Running) { 430 if (previous_thread->GetStatus() == ThreadStatus::Running) {
430 // This is only the case when a reschedule is triggered without the current thread 431 // This is only the case when a reschedule is triggered without the current thread
@@ -451,9 +452,10 @@ void Scheduler::SwitchContext() {
451 452
452 // Save context for previous thread 453 // Save context for previous thread
453 if (previous_thread) { 454 if (previous_thread) {
454 cpu_core.SaveContext(previous_thread->GetContext()); 455 system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32());
456 system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64());
455 // Save the TPIDR_EL0 system register in case it was modified. 457 // Save the TPIDR_EL0 system register in case it was modified.
456 previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); 458 previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0());
457 459
458 if (previous_thread->GetStatus() == ThreadStatus::Running) { 460 if (previous_thread->GetStatus() == ThreadStatus::Running) {
459 // This is only the case when a reschedule is triggered without the current thread 461 // This is only the case when a reschedule is triggered without the current thread
@@ -481,9 +483,10 @@ void Scheduler::SwitchContext() {
481 system.Kernel().MakeCurrentProcess(thread_owner_process); 483 system.Kernel().MakeCurrentProcess(thread_owner_process);
482 } 484 }
483 485
484 cpu_core.LoadContext(new_thread->GetContext()); 486 system.ArmInterface(core_id).LoadContext(new_thread->GetContext32());
485 cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); 487 system.ArmInterface(core_id).LoadContext(new_thread->GetContext64());
486 cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); 488 system.ArmInterface(core_id).SetTlsAddress(new_thread->GetTLSAddress());
489 system.ArmInterface(core_id).SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
487 } else { 490 } else {
488 current_thread = nullptr; 491 current_thread = nullptr;
489 // Note: We do not reset the current process and current page table when idling because 492 // Note: We do not reset the current process and current page table when idling because
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index 1c93a838c..07df33f9c 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -181,7 +181,7 @@ private:
181 181
182class Scheduler final { 182class Scheduler final {
183public: 183public:
184 explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id); 184 explicit Scheduler(Core::System& system, std::size_t core_id);
185 ~Scheduler(); 185 ~Scheduler();
186 186
187 /// Returns whether there are any threads that are ready to run. 187 /// Returns whether there are any threads that are ready to run.
@@ -235,7 +235,6 @@ private:
235 std::shared_ptr<Thread> selected_thread = nullptr; 235 std::shared_ptr<Thread> selected_thread = nullptr;
236 236
237 Core::System& system; 237 Core::System& system;
238 Core::ARM_Interface& cpu_core;
239 u64 last_context_switch_time = 0; 238 u64 last_context_switch_time = 0;
240 u64 idle_selection_count = 0; 239 u64 idle_selection_count = 0;
241 const std::size_t core_id; 240 const std::size_t core_id;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index fd91779a3..4ffc113c2 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -187,6 +187,13 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s
187 return RESULT_SUCCESS; 187 return RESULT_SUCCESS;
188} 188}
189 189
190static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) {
191 VAddr temp_heap_addr{};
192 const ResultCode result{SetHeapSize(system, &temp_heap_addr, heap_size)};
193 *heap_addr = static_cast<u32>(temp_heap_addr);
194 return result;
195}
196
190static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) { 197static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) {
191 LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot); 198 LOG_TRACE(Kernel_SVC, "called, addr=0x{:X}, size=0x{:X}, prot=0x{:X}", addr, size, prot);
192 199
@@ -371,6 +378,12 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
371 return RESULT_SUCCESS; 378 return RESULT_SUCCESS;
372} 379}
373 380
381static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle,
382 u32 port_name_address) {
383
384 return ConnectToNamedPort(system, out_handle, port_name_address);
385}
386
374/// Makes a blocking IPC call to an OS service. 387/// Makes a blocking IPC call to an OS service.
375static ResultCode SendSyncRequest(Core::System& system, Handle handle) { 388static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
376 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 389 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
@@ -390,6 +403,10 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
390 return session->SendSyncRequest(SharedFrom(thread), system.Memory()); 403 return session->SendSyncRequest(SharedFrom(thread), system.Memory());
391} 404}
392 405
406static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
407 return SendSyncRequest(system, handle);
408}
409
393/// Get the ID for the specified thread. 410/// Get the ID for the specified thread.
394static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) { 411static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) {
395 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); 412 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
@@ -405,6 +422,17 @@ static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle threa
405 return RESULT_SUCCESS; 422 return RESULT_SUCCESS;
406} 423}
407 424
425static ResultCode GetThreadId32(Core::System& system, u32* thread_id_low, u32* thread_id_high,
426 Handle thread_handle) {
427 u64 thread_id{};
428 const ResultCode result{GetThreadId(system, &thread_id, thread_handle)};
429
430 *thread_id_low = static_cast<u32>(thread_id >> 32);
431 *thread_id_high = static_cast<u32>(thread_id & std::numeric_limits<u32>::max());
432
433 return result;
434}
435
408/// Gets the ID of the specified process or a specified thread's owning process. 436/// Gets the ID of the specified process or a specified thread's owning process.
409static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { 437static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) {
410 LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); 438 LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
@@ -479,6 +507,12 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
479 return result; 507 return result;
480} 508}
481 509
510static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
511 s32 handle_count, u32 timeout_high, Handle* index) {
512 const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)};
513 return WaitSynchronization(system, index, handles_address, handle_count, nano_seconds);
514}
515
482/// Resumes a thread waiting on WaitSynchronization 516/// Resumes a thread waiting on WaitSynchronization
483static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { 517static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
484 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); 518 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
@@ -917,6 +951,18 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
917 } 951 }
918} 952}
919 953
954static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
955 u32 info_id, u32 handle, u32 sub_id_high) {
956 const u64 sub_id{static_cast<u64>(sub_id_low | (static_cast<u64>(sub_id_high) << 32))};
957 u64 res_value{};
958
959 const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)};
960 *result_high = static_cast<u32>(res_value >> 32);
961 *result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max());
962
963 return result;
964}
965
920/// Maps memory at a desired address 966/// Maps memory at a desired address
921static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 967static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
922 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 968 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
@@ -1058,7 +1104,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H
1058 return ERR_BUSY; 1104 return ERR_BUSY;
1059 } 1105 }
1060 1106
1061 Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); 1107 Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64();
1062 // Mask away mode bits, interrupt bits, IL bit, and other reserved bits. 1108 // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
1063 ctx.pstate &= 0xFF0FFE20; 1109 ctx.pstate &= 0xFF0FFE20;
1064 1110
@@ -1088,6 +1134,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle
1088 return RESULT_SUCCESS; 1134 return RESULT_SUCCESS;
1089} 1135}
1090 1136
1137static ResultCode GetThreadPriority32(Core::System& system, u32* priority, Handle handle) {
1138 return GetThreadPriority(system, priority, handle);
1139}
1140
1091/// Sets the priority for the specified thread 1141/// Sets the priority for the specified thread
1092static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { 1142static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
1093 LOG_TRACE(Kernel_SVC, "called"); 1143 LOG_TRACE(Kernel_SVC, "called");
@@ -1259,6 +1309,11 @@ static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,
1259 query_address); 1309 query_address);
1260} 1310}
1261 1311
1312static ResultCode QueryMemory32(Core::System& system, u32 memory_info_address,
1313 u32 page_info_address, u32 query_address) {
1314 return QueryMemory(system, memory_info_address, page_info_address, query_address);
1315}
1316
1262static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address, 1317static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
1263 u64 src_address, u64 size) { 1318 u64 src_address, u64 size) {
1264 LOG_DEBUG(Kernel_SVC, 1319 LOG_DEBUG(Kernel_SVC,
@@ -1675,6 +1730,10 @@ static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_
1675 } 1730 }
1676} 1731}
1677 1732
1733static void SignalProcessWideKey32(Core::System& system, u32 condition_variable_addr, s32 target) {
1734 SignalProcessWideKey(system, condition_variable_addr, target);
1735}
1736
1678// Wait for an address (via Address Arbiter) 1737// Wait for an address (via Address Arbiter)
1679static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value, 1738static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value,
1680 s64 timeout) { 1739 s64 timeout) {
@@ -1760,6 +1819,10 @@ static ResultCode CloseHandle(Core::System& system, Handle handle) {
1760 return handle_table.Close(handle); 1819 return handle_table.Close(handle);
1761} 1820}
1762 1821
1822static ResultCode CloseHandle32(Core::System& system, Handle handle) {
1823 return CloseHandle(system, handle);
1824}
1825
1763/// Clears the signaled state of an event or process. 1826/// Clears the signaled state of an event or process.
1764static ResultCode ResetSignal(Core::System& system, Handle handle) { 1827static ResultCode ResetSignal(Core::System& system, Handle handle) {
1765 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); 1828 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
@@ -2317,69 +2380,196 @@ struct FunctionDef {
2317}; 2380};
2318} // namespace 2381} // namespace
2319 2382
2320static const FunctionDef SVC_Table[] = { 2383static const FunctionDef SVC_Table_32[] = {
2321 {0x00, nullptr, "Unknown"}, 2384 {0x00, nullptr, "Unknown"},
2322 {0x01, SvcWrap<SetHeapSize>, "SetHeapSize"}, 2385 {0x01, SvcWrap32<SetHeapSize32>, "SetHeapSize32"},
2323 {0x02, SvcWrap<SetMemoryPermission>, "SetMemoryPermission"}, 2386 {0x02, nullptr, "Unknown"},
2324 {0x03, SvcWrap<SetMemoryAttribute>, "SetMemoryAttribute"}, 2387 {0x03, nullptr, "SetMemoryAttribute32"},
2325 {0x04, SvcWrap<MapMemory>, "MapMemory"}, 2388 {0x04, nullptr, "MapMemory32"},
2326 {0x05, SvcWrap<UnmapMemory>, "UnmapMemory"}, 2389 {0x05, nullptr, "UnmapMemory32"},
2327 {0x06, SvcWrap<QueryMemory>, "QueryMemory"}, 2390 {0x06, SvcWrap32<QueryMemory32>, "QueryMemory32"},
2328 {0x07, SvcWrap<ExitProcess>, "ExitProcess"}, 2391 {0x07, nullptr, "ExitProcess32"},
2329 {0x08, SvcWrap<CreateThread>, "CreateThread"}, 2392 {0x08, nullptr, "CreateThread32"},
2330 {0x09, SvcWrap<StartThread>, "StartThread"}, 2393 {0x09, nullptr, "StartThread32"},
2331 {0x0A, SvcWrap<ExitThread>, "ExitThread"}, 2394 {0x0a, nullptr, "ExitThread32"},
2332 {0x0B, SvcWrap<SleepThread>, "SleepThread"}, 2395 {0x0b, nullptr, "SleepThread32"},
2333 {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, 2396 {0x0c, SvcWrap32<GetThreadPriority32>, "GetThreadPriority32"},
2334 {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, 2397 {0x0d, nullptr, "SetThreadPriority32"},
2335 {0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"}, 2398 {0x0e, nullptr, "GetThreadCoreMask32"},
2336 {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, 2399 {0x0f, nullptr, "SetThreadCoreMask32"},
2337 {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, 2400 {0x10, nullptr, "GetCurrentProcessorNumber32"},
2338 {0x11, SvcWrap<SignalEvent>, "SignalEvent"}, 2401 {0x11, nullptr, "SignalEvent32"},
2339 {0x12, SvcWrap<ClearEvent>, "ClearEvent"}, 2402 {0x12, nullptr, "ClearEvent32"},
2340 {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"}, 2403 {0x13, nullptr, "MapSharedMemory32"},
2341 {0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"}, 2404 {0x14, nullptr, "UnmapSharedMemory32"},
2342 {0x15, SvcWrap<CreateTransferMemory>, "CreateTransferMemory"}, 2405 {0x15, nullptr, "CreateTransferMemory32"},
2343 {0x16, SvcWrap<CloseHandle>, "CloseHandle"}, 2406 {0x16, SvcWrap32<CloseHandle32>, "CloseHandle32"},
2344 {0x17, SvcWrap<ResetSignal>, "ResetSignal"}, 2407 {0x17, nullptr, "ResetSignal32"},
2345 {0x18, SvcWrap<WaitSynchronization>, "WaitSynchronization"}, 2408 {0x18, SvcWrap32<WaitSynchronization32>, "WaitSynchronization32"},
2346 {0x19, SvcWrap<CancelSynchronization>, "CancelSynchronization"}, 2409 {0x19, nullptr, "CancelSynchronization32"},
2347 {0x1A, SvcWrap<ArbitrateLock>, "ArbitrateLock"}, 2410 {0x1a, nullptr, "ArbitrateLock32"},
2348 {0x1B, SvcWrap<ArbitrateUnlock>, "ArbitrateUnlock"}, 2411 {0x1b, nullptr, "ArbitrateUnlock32"},
2349 {0x1C, SvcWrap<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"}, 2412 {0x1c, nullptr, "WaitProcessWideKeyAtomic32"},
2350 {0x1D, SvcWrap<SignalProcessWideKey>, "SignalProcessWideKey"}, 2413 {0x1d, SvcWrap32<SignalProcessWideKey32>, "SignalProcessWideKey32"},
2351 {0x1E, SvcWrap<GetSystemTick>, "GetSystemTick"}, 2414 {0x1e, nullptr, "GetSystemTick32"},
2352 {0x1F, SvcWrap<ConnectToNamedPort>, "ConnectToNamedPort"}, 2415 {0x1f, SvcWrap32<ConnectToNamedPort32>, "ConnectToNamedPort32"},
2416 {0x20, nullptr, "Unknown"},
2417 {0x21, SvcWrap32<SendSyncRequest32>, "SendSyncRequest32"},
2418 {0x22, nullptr, "SendSyncRequestWithUserBuffer32"},
2419 {0x23, nullptr, "Unknown"},
2420 {0x24, nullptr, "GetProcessId32"},
2421 {0x25, SvcWrap32<GetThreadId32>, "GetThreadId32"},
2422 {0x26, nullptr, "Break32"},
2423 {0x27, nullptr, "OutputDebugString32"},
2424 {0x28, nullptr, "Unknown"},
2425 {0x29, SvcWrap32<GetInfo32>, "GetInfo32"},
2426 {0x2a, nullptr, "Unknown"},
2427 {0x2b, nullptr, "Unknown"},
2428 {0x2c, nullptr, "MapPhysicalMemory32"},
2429 {0x2d, nullptr, "UnmapPhysicalMemory32"},
2430 {0x2e, nullptr, "Unknown"},
2431 {0x2f, nullptr, "Unknown"},
2432 {0x30, nullptr, "Unknown"},
2433 {0x31, nullptr, "Unknown"},
2434 {0x32, nullptr, "SetThreadActivity32"},
2435 {0x33, nullptr, "GetThreadContext32"},
2436 {0x34, nullptr, "WaitForAddress32"},
2437 {0x35, nullptr, "SignalToAddress32"},
2438 {0x36, nullptr, "Unknown"},
2439 {0x37, nullptr, "Unknown"},
2440 {0x38, nullptr, "Unknown"},
2441 {0x39, nullptr, "Unknown"},
2442 {0x3a, nullptr, "Unknown"},
2443 {0x3b, nullptr, "Unknown"},
2444 {0x3c, nullptr, "Unknown"},
2445 {0x3d, nullptr, "Unknown"},
2446 {0x3e, nullptr, "Unknown"},
2447 {0x3f, nullptr, "Unknown"},
2448 {0x40, nullptr, "CreateSession32"},
2449 {0x41, nullptr, "AcceptSession32"},
2450 {0x42, nullptr, "Unknown"},
2451 {0x43, nullptr, "ReplyAndReceive32"},
2452 {0x44, nullptr, "Unknown"},
2453 {0x45, nullptr, "CreateEvent32"},
2454 {0x46, nullptr, "Unknown"},
2455 {0x47, nullptr, "Unknown"},
2456 {0x48, nullptr, "Unknown"},
2457 {0x49, nullptr, "Unknown"},
2458 {0x4a, nullptr, "Unknown"},
2459 {0x4b, nullptr, "Unknown"},
2460 {0x4c, nullptr, "Unknown"},
2461 {0x4d, nullptr, "Unknown"},
2462 {0x4e, nullptr, "Unknown"},
2463 {0x4f, nullptr, "Unknown"},
2464 {0x50, nullptr, "Unknown"},
2465 {0x51, nullptr, "Unknown"},
2466 {0x52, nullptr, "Unknown"},
2467 {0x53, nullptr, "Unknown"},
2468 {0x54, nullptr, "Unknown"},
2469 {0x55, nullptr, "Unknown"},
2470 {0x56, nullptr, "Unknown"},
2471 {0x57, nullptr, "Unknown"},
2472 {0x58, nullptr, "Unknown"},
2473 {0x59, nullptr, "Unknown"},
2474 {0x5a, nullptr, "Unknown"},
2475 {0x5b, nullptr, "Unknown"},
2476 {0x5c, nullptr, "Unknown"},
2477 {0x5d, nullptr, "Unknown"},
2478 {0x5e, nullptr, "Unknown"},
2479 {0x5F, nullptr, "FlushProcessDataCache32"},
2480 {0x60, nullptr, "Unknown"},
2481 {0x61, nullptr, "Unknown"},
2482 {0x62, nullptr, "Unknown"},
2483 {0x63, nullptr, "Unknown"},
2484 {0x64, nullptr, "Unknown"},
2485 {0x65, nullptr, "GetProcessList32"},
2486 {0x66, nullptr, "Unknown"},
2487 {0x67, nullptr, "Unknown"},
2488 {0x68, nullptr, "Unknown"},
2489 {0x69, nullptr, "Unknown"},
2490 {0x6A, nullptr, "Unknown"},
2491 {0x6B, nullptr, "Unknown"},
2492 {0x6C, nullptr, "Unknown"},
2493 {0x6D, nullptr, "Unknown"},
2494 {0x6E, nullptr, "Unknown"},
2495 {0x6f, nullptr, "GetSystemInfo32"},
2496 {0x70, nullptr, "CreatePort32"},
2497 {0x71, nullptr, "ManageNamedPort32"},
2498 {0x72, nullptr, "ConnectToPort32"},
2499 {0x73, nullptr, "SetProcessMemoryPermission32"},
2500 {0x74, nullptr, "Unknown"},
2501 {0x75, nullptr, "Unknown"},
2502 {0x76, nullptr, "Unknown"},
2503 {0x77, nullptr, "MapProcessCodeMemory32"},
2504 {0x78, nullptr, "UnmapProcessCodeMemory32"},
2505 {0x79, nullptr, "Unknown"},
2506 {0x7A, nullptr, "Unknown"},
2507 {0x7B, nullptr, "TerminateProcess32"},
2508};
2509
2510static const FunctionDef SVC_Table_64[] = {
2511 {0x00, nullptr, "Unknown"},
2512 {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
2513 {0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
2514 {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
2515 {0x04, SvcWrap64<MapMemory>, "MapMemory"},
2516 {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
2517 {0x06, SvcWrap64<QueryMemory>, "QueryMemory"},
2518 {0x07, SvcWrap64<ExitProcess>, "ExitProcess"},
2519 {0x08, SvcWrap64<CreateThread>, "CreateThread"},
2520 {0x09, SvcWrap64<StartThread>, "StartThread"},
2521 {0x0A, SvcWrap64<ExitThread>, "ExitThread"},
2522 {0x0B, SvcWrap64<SleepThread>, "SleepThread"},
2523 {0x0C, SvcWrap64<GetThreadPriority>, "GetThreadPriority"},
2524 {0x0D, SvcWrap64<SetThreadPriority>, "SetThreadPriority"},
2525 {0x0E, SvcWrap64<GetThreadCoreMask>, "GetThreadCoreMask"},
2526 {0x0F, SvcWrap64<SetThreadCoreMask>, "SetThreadCoreMask"},
2527 {0x10, SvcWrap64<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},
2528 {0x11, SvcWrap64<SignalEvent>, "SignalEvent"},
2529 {0x12, SvcWrap64<ClearEvent>, "ClearEvent"},
2530 {0x13, SvcWrap64<MapSharedMemory>, "MapSharedMemory"},
2531 {0x14, SvcWrap64<UnmapSharedMemory>, "UnmapSharedMemory"},
2532 {0x15, SvcWrap64<CreateTransferMemory>, "CreateTransferMemory"},
2533 {0x16, SvcWrap64<CloseHandle>, "CloseHandle"},
2534 {0x17, SvcWrap64<ResetSignal>, "ResetSignal"},
2535 {0x18, SvcWrap64<WaitSynchronization>, "WaitSynchronization"},
2536 {0x19, SvcWrap64<CancelSynchronization>, "CancelSynchronization"},
2537 {0x1A, SvcWrap64<ArbitrateLock>, "ArbitrateLock"},
2538 {0x1B, SvcWrap64<ArbitrateUnlock>, "ArbitrateUnlock"},
2539 {0x1C, SvcWrap64<WaitProcessWideKeyAtomic>, "WaitProcessWideKeyAtomic"},
2540 {0x1D, SvcWrap64<SignalProcessWideKey>, "SignalProcessWideKey"},
2541 {0x1E, SvcWrap64<GetSystemTick>, "GetSystemTick"},
2542 {0x1F, SvcWrap64<ConnectToNamedPort>, "ConnectToNamedPort"},
2353 {0x20, nullptr, "SendSyncRequestLight"}, 2543 {0x20, nullptr, "SendSyncRequestLight"},
2354 {0x21, SvcWrap<SendSyncRequest>, "SendSyncRequest"}, 2544 {0x21, SvcWrap64<SendSyncRequest>, "SendSyncRequest"},
2355 {0x22, nullptr, "SendSyncRequestWithUserBuffer"}, 2545 {0x22, nullptr, "SendSyncRequestWithUserBuffer"},
2356 {0x23, nullptr, "SendAsyncRequestWithUserBuffer"}, 2546 {0x23, nullptr, "SendAsyncRequestWithUserBuffer"},
2357 {0x24, SvcWrap<GetProcessId>, "GetProcessId"}, 2547 {0x24, SvcWrap64<GetProcessId>, "GetProcessId"},
2358 {0x25, SvcWrap<GetThreadId>, "GetThreadId"}, 2548 {0x25, SvcWrap64<GetThreadId>, "GetThreadId"},
2359 {0x26, SvcWrap<Break>, "Break"}, 2549 {0x26, SvcWrap64<Break>, "Break"},
2360 {0x27, SvcWrap<OutputDebugString>, "OutputDebugString"}, 2550 {0x27, SvcWrap64<OutputDebugString>, "OutputDebugString"},
2361 {0x28, nullptr, "ReturnFromException"}, 2551 {0x28, nullptr, "ReturnFromException"},
2362 {0x29, SvcWrap<GetInfo>, "GetInfo"}, 2552 {0x29, SvcWrap64<GetInfo>, "GetInfo"},
2363 {0x2A, nullptr, "FlushEntireDataCache"}, 2553 {0x2A, nullptr, "FlushEntireDataCache"},
2364 {0x2B, nullptr, "FlushDataCache"}, 2554 {0x2B, nullptr, "FlushDataCache"},
2365 {0x2C, SvcWrap<MapPhysicalMemory>, "MapPhysicalMemory"}, 2555 {0x2C, SvcWrap64<MapPhysicalMemory>, "MapPhysicalMemory"},
2366 {0x2D, SvcWrap<UnmapPhysicalMemory>, "UnmapPhysicalMemory"}, 2556 {0x2D, SvcWrap64<UnmapPhysicalMemory>, "UnmapPhysicalMemory"},
2367 {0x2E, nullptr, "GetFutureThreadInfo"}, 2557 {0x2E, nullptr, "GetFutureThreadInfo"},
2368 {0x2F, nullptr, "GetLastThreadInfo"}, 2558 {0x2F, nullptr, "GetLastThreadInfo"},
2369 {0x30, SvcWrap<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"}, 2559 {0x30, SvcWrap64<GetResourceLimitLimitValue>, "GetResourceLimitLimitValue"},
2370 {0x31, SvcWrap<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"}, 2560 {0x31, SvcWrap64<GetResourceLimitCurrentValue>, "GetResourceLimitCurrentValue"},
2371 {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, 2561 {0x32, SvcWrap64<SetThreadActivity>, "SetThreadActivity"},
2372 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, 2562 {0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"},
2373 {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, 2563 {0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
2374 {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, 2564 {0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
2375 {0x36, nullptr, "SynchronizePreemptionState"}, 2565 {0x36, nullptr, "SynchronizePreemptionState"},
2376 {0x37, nullptr, "Unknown"}, 2566 {0x37, nullptr, "Unknown"},
2377 {0x38, nullptr, "Unknown"}, 2567 {0x38, nullptr, "Unknown"},
2378 {0x39, nullptr, "Unknown"}, 2568 {0x39, nullptr, "Unknown"},
2379 {0x3A, nullptr, "Unknown"}, 2569 {0x3A, nullptr, "Unknown"},
2380 {0x3B, nullptr, "Unknown"}, 2570 {0x3B, nullptr, "Unknown"},
2381 {0x3C, SvcWrap<KernelDebug>, "KernelDebug"}, 2571 {0x3C, SvcWrap64<KernelDebug>, "KernelDebug"},
2382 {0x3D, SvcWrap<ChangeKernelTraceState>, "ChangeKernelTraceState"}, 2572 {0x3D, SvcWrap64<ChangeKernelTraceState>, "ChangeKernelTraceState"},
2383 {0x3E, nullptr, "Unknown"}, 2573 {0x3E, nullptr, "Unknown"},
2384 {0x3F, nullptr, "Unknown"}, 2574 {0x3F, nullptr, "Unknown"},
2385 {0x40, nullptr, "CreateSession"}, 2575 {0x40, nullptr, "CreateSession"},
@@ -2387,7 +2577,7 @@ static const FunctionDef SVC_Table[] = {
2387 {0x42, nullptr, "ReplyAndReceiveLight"}, 2577 {0x42, nullptr, "ReplyAndReceiveLight"},
2388 {0x43, nullptr, "ReplyAndReceive"}, 2578 {0x43, nullptr, "ReplyAndReceive"},
2389 {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, 2579 {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"},
2390 {0x45, SvcWrap<CreateEvent>, "CreateEvent"}, 2580 {0x45, SvcWrap64<CreateEvent>, "CreateEvent"},
2391 {0x46, nullptr, "Unknown"}, 2581 {0x46, nullptr, "Unknown"},
2392 {0x47, nullptr, "Unknown"}, 2582 {0x47, nullptr, "Unknown"},
2393 {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, 2583 {0x48, nullptr, "MapPhysicalMemoryUnsafe"},
@@ -2398,9 +2588,9 @@ static const FunctionDef SVC_Table[] = {
2398 {0x4D, nullptr, "SleepSystem"}, 2588 {0x4D, nullptr, "SleepSystem"},
2399 {0x4E, nullptr, "ReadWriteRegister"}, 2589 {0x4E, nullptr, "ReadWriteRegister"},
2400 {0x4F, nullptr, "SetProcessActivity"}, 2590 {0x4F, nullptr, "SetProcessActivity"},
2401 {0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"}, 2591 {0x50, SvcWrap64<CreateSharedMemory>, "CreateSharedMemory"},
2402 {0x51, SvcWrap<MapTransferMemory>, "MapTransferMemory"}, 2592 {0x51, SvcWrap64<MapTransferMemory>, "MapTransferMemory"},
2403 {0x52, SvcWrap<UnmapTransferMemory>, "UnmapTransferMemory"}, 2593 {0x52, SvcWrap64<UnmapTransferMemory>, "UnmapTransferMemory"},
2404 {0x53, nullptr, "CreateInterruptEvent"}, 2594 {0x53, nullptr, "CreateInterruptEvent"},
2405 {0x54, nullptr, "QueryPhysicalAddress"}, 2595 {0x54, nullptr, "QueryPhysicalAddress"},
2406 {0x55, nullptr, "QueryIoMapping"}, 2596 {0x55, nullptr, "QueryIoMapping"},
@@ -2419,8 +2609,8 @@ static const FunctionDef SVC_Table[] = {
2419 {0x62, nullptr, "TerminateDebugProcess"}, 2609 {0x62, nullptr, "TerminateDebugProcess"},
2420 {0x63, nullptr, "GetDebugEvent"}, 2610 {0x63, nullptr, "GetDebugEvent"},
2421 {0x64, nullptr, "ContinueDebugEvent"}, 2611 {0x64, nullptr, "ContinueDebugEvent"},
2422 {0x65, SvcWrap<GetProcessList>, "GetProcessList"}, 2612 {0x65, SvcWrap64<GetProcessList>, "GetProcessList"},
2423 {0x66, SvcWrap<GetThreadList>, "GetThreadList"}, 2613 {0x66, SvcWrap64<GetThreadList>, "GetThreadList"},
2424 {0x67, nullptr, "GetDebugThreadContext"}, 2614 {0x67, nullptr, "GetDebugThreadContext"},
2425 {0x68, nullptr, "SetDebugThreadContext"}, 2615 {0x68, nullptr, "SetDebugThreadContext"},
2426 {0x69, nullptr, "QueryDebugProcessMemory"}, 2616 {0x69, nullptr, "QueryDebugProcessMemory"},
@@ -2436,24 +2626,32 @@ static const FunctionDef SVC_Table[] = {
2436 {0x73, nullptr, "SetProcessMemoryPermission"}, 2626 {0x73, nullptr, "SetProcessMemoryPermission"},
2437 {0x74, nullptr, "MapProcessMemory"}, 2627 {0x74, nullptr, "MapProcessMemory"},
2438 {0x75, nullptr, "UnmapProcessMemory"}, 2628 {0x75, nullptr, "UnmapProcessMemory"},
2439 {0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"}, 2629 {0x76, SvcWrap64<QueryProcessMemory>, "QueryProcessMemory"},
2440 {0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"}, 2630 {0x77, SvcWrap64<MapProcessCodeMemory>, "MapProcessCodeMemory"},
2441 {0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"}, 2631 {0x78, SvcWrap64<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
2442 {0x79, nullptr, "CreateProcess"}, 2632 {0x79, nullptr, "CreateProcess"},
2443 {0x7A, nullptr, "StartProcess"}, 2633 {0x7A, nullptr, "StartProcess"},
2444 {0x7B, nullptr, "TerminateProcess"}, 2634 {0x7B, nullptr, "TerminateProcess"},
2445 {0x7C, SvcWrap<GetProcessInfo>, "GetProcessInfo"}, 2635 {0x7C, SvcWrap64<GetProcessInfo>, "GetProcessInfo"},
2446 {0x7D, SvcWrap<CreateResourceLimit>, "CreateResourceLimit"}, 2636 {0x7D, SvcWrap64<CreateResourceLimit>, "CreateResourceLimit"},
2447 {0x7E, SvcWrap<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"}, 2637 {0x7E, SvcWrap64<SetResourceLimitLimitValue>, "SetResourceLimitLimitValue"},
2448 {0x7F, nullptr, "CallSecureMonitor"}, 2638 {0x7F, nullptr, "CallSecureMonitor"},
2449}; 2639};
2450 2640
2451static const FunctionDef* GetSVCInfo(u32 func_num) { 2641static const FunctionDef* GetSVCInfo32(u32 func_num) {
2452 if (func_num >= std::size(SVC_Table)) { 2642 if (func_num >= std::size(SVC_Table_32)) {
2643 LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);
2644 return nullptr;
2645 }
2646 return &SVC_Table_32[func_num];
2647}
2648
2649static const FunctionDef* GetSVCInfo64(u32 func_num) {
2650 if (func_num >= std::size(SVC_Table_64)) {
2453 LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num); 2651 LOG_ERROR(Kernel_SVC, "Unknown svc=0x{:02X}", func_num);
2454 return nullptr; 2652 return nullptr;
2455 } 2653 }
2456 return &SVC_Table[func_num]; 2654 return &SVC_Table_64[func_num];
2457} 2655}
2458 2656
2459MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); 2657MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
@@ -2464,7 +2662,8 @@ void CallSVC(Core::System& system, u32 immediate) {
2464 // Lock the global kernel mutex when we enter the kernel HLE. 2662 // Lock the global kernel mutex when we enter the kernel HLE.
2465 std::lock_guard lock{HLE::g_hle_lock}; 2663 std::lock_guard lock{HLE::g_hle_lock};
2466 2664
2467 const FunctionDef* info = GetSVCInfo(immediate); 2665 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
2666 : GetSVCInfo32(immediate);
2468 if (info) { 2667 if (info) {
2469 if (info->func) { 2668 if (info->func) {
2470 info->func(system); 2669 info->func(system);
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 29a2cfa9d..7d735e3fa 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -15,6 +15,10 @@ static inline u64 Param(const Core::System& system, int n) {
15 return system.CurrentArmInterface().GetReg(n); 15 return system.CurrentArmInterface().GetReg(n);
16} 16}
17 17
18static inline u32 Param32(const Core::System& system, int n) {
19 return static_cast<u32>(system.CurrentArmInterface().GetReg(n));
20}
21
18/** 22/**
19 * HLE a function return from the current ARM userland process 23 * HLE a function return from the current ARM userland process
20 * @param system System context 24 * @param system System context
@@ -24,40 +28,44 @@ static inline void FuncReturn(Core::System& system, u64 result) {
24 system.CurrentArmInterface().SetReg(0, result); 28 system.CurrentArmInterface().SetReg(0, result);
25} 29}
26 30
31static inline void FuncReturn32(Core::System& system, u32 result) {
32 system.CurrentArmInterface().SetReg(0, (u64)result);
33}
34
27//////////////////////////////////////////////////////////////////////////////////////////////////// 35////////////////////////////////////////////////////////////////////////////////////////////////////
28// Function wrappers that return type ResultCode 36// Function wrappers that return type ResultCode
29 37
30template <ResultCode func(Core::System&, u64)> 38template <ResultCode func(Core::System&, u64)>
31void SvcWrap(Core::System& system) { 39void SvcWrap64(Core::System& system) {
32 FuncReturn(system, func(system, Param(system, 0)).raw); 40 FuncReturn(system, func(system, Param(system, 0)).raw);
33} 41}
34 42
35template <ResultCode func(Core::System&, u64, u64)> 43template <ResultCode func(Core::System&, u64, u64)>
36void SvcWrap(Core::System& system) { 44void SvcWrap64(Core::System& system) {
37 FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw); 45 FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);
38} 46}
39 47
40template <ResultCode func(Core::System&, u32)> 48template <ResultCode func(Core::System&, u32)>
41void SvcWrap(Core::System& system) { 49void SvcWrap64(Core::System& system) {
42 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw); 50 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
43} 51}
44 52
45template <ResultCode func(Core::System&, u32, u32)> 53template <ResultCode func(Core::System&, u32, u32)>
46void SvcWrap(Core::System& system) { 54void SvcWrap64(Core::System& system) {
47 FuncReturn( 55 FuncReturn(
48 system, 56 system,
49 func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw); 57 func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
50} 58}
51 59
52template <ResultCode func(Core::System&, u32, u64, u64, u64)> 60template <ResultCode func(Core::System&, u32, u64, u64, u64)>
53void SvcWrap(Core::System& system) { 61void SvcWrap64(Core::System& system) {
54 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), 62 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
55 Param(system, 2), Param(system, 3)) 63 Param(system, 2), Param(system, 3))
56 .raw); 64 .raw);
57} 65}
58 66
59template <ResultCode func(Core::System&, u32*)> 67template <ResultCode func(Core::System&, u32*)>
60void SvcWrap(Core::System& system) { 68void SvcWrap64(Core::System& system) {
61 u32 param = 0; 69 u32 param = 0;
62 const u32 retval = func(system, &param).raw; 70 const u32 retval = func(system, &param).raw;
63 system.CurrentArmInterface().SetReg(1, param); 71 system.CurrentArmInterface().SetReg(1, param);
@@ -65,7 +73,7 @@ void SvcWrap(Core::System& system) {
65} 73}
66 74
67template <ResultCode func(Core::System&, u32*, u32)> 75template <ResultCode func(Core::System&, u32*, u32)>
68void SvcWrap(Core::System& system) { 76void SvcWrap64(Core::System& system) {
69 u32 param_1 = 0; 77 u32 param_1 = 0;
70 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw; 78 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
71 system.CurrentArmInterface().SetReg(1, param_1); 79 system.CurrentArmInterface().SetReg(1, param_1);
@@ -73,7 +81,7 @@ void SvcWrap(Core::System& system) {
73} 81}
74 82
75template <ResultCode func(Core::System&, u32*, u32*)> 83template <ResultCode func(Core::System&, u32*, u32*)>
76void SvcWrap(Core::System& system) { 84void SvcWrap64(Core::System& system) {
77 u32 param_1 = 0; 85 u32 param_1 = 0;
78 u32 param_2 = 0; 86 u32 param_2 = 0;
79 const u32 retval = func(system, &param_1, &param_2).raw; 87 const u32 retval = func(system, &param_1, &param_2).raw;
@@ -86,7 +94,7 @@ void SvcWrap(Core::System& system) {
86} 94}
87 95
88template <ResultCode func(Core::System&, u32*, u64)> 96template <ResultCode func(Core::System&, u32*, u64)>
89void SvcWrap(Core::System& system) { 97void SvcWrap64(Core::System& system) {
90 u32 param_1 = 0; 98 u32 param_1 = 0;
91 const u32 retval = func(system, &param_1, Param(system, 1)).raw; 99 const u32 retval = func(system, &param_1, Param(system, 1)).raw;
92 system.CurrentArmInterface().SetReg(1, param_1); 100 system.CurrentArmInterface().SetReg(1, param_1);
@@ -94,7 +102,7 @@ void SvcWrap(Core::System& system) {
94} 102}
95 103
96template <ResultCode func(Core::System&, u32*, u64, u32)> 104template <ResultCode func(Core::System&, u32*, u64, u32)>
97void SvcWrap(Core::System& system) { 105void SvcWrap64(Core::System& system) {
98 u32 param_1 = 0; 106 u32 param_1 = 0;
99 const u32 retval = 107 const u32 retval =
100 func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw; 108 func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw;
@@ -104,7 +112,7 @@ void SvcWrap(Core::System& system) {
104} 112}
105 113
106template <ResultCode func(Core::System&, u64*, u32)> 114template <ResultCode func(Core::System&, u64*, u32)>
107void SvcWrap(Core::System& system) { 115void SvcWrap64(Core::System& system) {
108 u64 param_1 = 0; 116 u64 param_1 = 0;
109 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw; 117 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
110 118
@@ -113,12 +121,12 @@ void SvcWrap(Core::System& system) {
113} 121}
114 122
115template <ResultCode func(Core::System&, u64, u32)> 123template <ResultCode func(Core::System&, u64, u32)>
116void SvcWrap(Core::System& system) { 124void SvcWrap64(Core::System& system) {
117 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw); 125 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
118} 126}
119 127
120template <ResultCode func(Core::System&, u64*, u64)> 128template <ResultCode func(Core::System&, u64*, u64)>
121void SvcWrap(Core::System& system) { 129void SvcWrap64(Core::System& system) {
122 u64 param_1 = 0; 130 u64 param_1 = 0;
123 const u32 retval = func(system, &param_1, Param(system, 1)).raw; 131 const u32 retval = func(system, &param_1, Param(system, 1)).raw;
124 132
@@ -127,7 +135,7 @@ void SvcWrap(Core::System& system) {
127} 135}
128 136
129template <ResultCode func(Core::System&, u64*, u32, u32)> 137template <ResultCode func(Core::System&, u64*, u32, u32)>
130void SvcWrap(Core::System& system) { 138void SvcWrap64(Core::System& system) {
131 u64 param_1 = 0; 139 u64 param_1 = 0;
132 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)), 140 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)),
133 static_cast<u32>(Param(system, 2))) 141 static_cast<u32>(Param(system, 2)))
@@ -138,19 +146,19 @@ void SvcWrap(Core::System& system) {
138} 146}
139 147
140template <ResultCode func(Core::System&, u32, u64)> 148template <ResultCode func(Core::System&, u32, u64)>
141void SvcWrap(Core::System& system) { 149void SvcWrap64(Core::System& system) {
142 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); 150 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
143} 151}
144 152
145template <ResultCode func(Core::System&, u32, u32, u64)> 153template <ResultCode func(Core::System&, u32, u32, u64)>
146void SvcWrap(Core::System& system) { 154void SvcWrap64(Core::System& system) {
147 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), 155 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
148 static_cast<u32>(Param(system, 1)), Param(system, 2)) 156 static_cast<u32>(Param(system, 1)), Param(system, 2))
149 .raw); 157 .raw);
150} 158}
151 159
152template <ResultCode func(Core::System&, u32, u32*, u64*)> 160template <ResultCode func(Core::System&, u32, u32*, u64*)>
153void SvcWrap(Core::System& system) { 161void SvcWrap64(Core::System& system) {
154 u32 param_1 = 0; 162 u32 param_1 = 0;
155 u64 param_2 = 0; 163 u64 param_2 = 0;
156 const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2); 164 const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2);
@@ -161,54 +169,54 @@ void SvcWrap(Core::System& system) {
161} 169}
162 170
163template <ResultCode func(Core::System&, u64, u64, u32, u32)> 171template <ResultCode func(Core::System&, u64, u64, u32, u32)>
164void SvcWrap(Core::System& system) { 172void SvcWrap64(Core::System& system) {
165 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 173 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
166 static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3))) 174 static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
167 .raw); 175 .raw);
168} 176}
169 177
170template <ResultCode func(Core::System&, u64, u64, u32, u64)> 178template <ResultCode func(Core::System&, u64, u64, u32, u64)>
171void SvcWrap(Core::System& system) { 179void SvcWrap64(Core::System& system) {
172 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 180 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
173 static_cast<u32>(Param(system, 2)), Param(system, 3)) 181 static_cast<u32>(Param(system, 2)), Param(system, 3))
174 .raw); 182 .raw);
175} 183}
176 184
177template <ResultCode func(Core::System&, u32, u64, u32)> 185template <ResultCode func(Core::System&, u32, u64, u32)>
178void SvcWrap(Core::System& system) { 186void SvcWrap64(Core::System& system) {
179 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), 187 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
180 static_cast<u32>(Param(system, 2))) 188 static_cast<u32>(Param(system, 2)))
181 .raw); 189 .raw);
182} 190}
183 191
184template <ResultCode func(Core::System&, u64, u64, u64)> 192template <ResultCode func(Core::System&, u64, u64, u64)>
185void SvcWrap(Core::System& system) { 193void SvcWrap64(Core::System& system) {
186 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw); 194 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);
187} 195}
188 196
189template <ResultCode func(Core::System&, u64, u64, u32)> 197template <ResultCode func(Core::System&, u64, u64, u32)>
190void SvcWrap(Core::System& system) { 198void SvcWrap64(Core::System& system) {
191 FuncReturn( 199 FuncReturn(
192 system, 200 system,
193 func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); 201 func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
194} 202}
195 203
196template <ResultCode func(Core::System&, u32, u64, u64, u32)> 204template <ResultCode func(Core::System&, u32, u64, u64, u32)>
197void SvcWrap(Core::System& system) { 205void SvcWrap64(Core::System& system) {
198 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), 206 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
199 Param(system, 2), static_cast<u32>(Param(system, 3))) 207 Param(system, 2), static_cast<u32>(Param(system, 3)))
200 .raw); 208 .raw);
201} 209}
202 210
203template <ResultCode func(Core::System&, u32, u64, u64)> 211template <ResultCode func(Core::System&, u32, u64, u64)>
204void SvcWrap(Core::System& system) { 212void SvcWrap64(Core::System& system) {
205 FuncReturn( 213 FuncReturn(
206 system, 214 system,
207 func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw); 215 func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw);
208} 216}
209 217
210template <ResultCode func(Core::System&, u32*, u64, u64, s64)> 218template <ResultCode func(Core::System&, u32*, u64, u64, s64)>
211void SvcWrap(Core::System& system) { 219void SvcWrap64(Core::System& system) {
212 u32 param_1 = 0; 220 u32 param_1 = 0;
213 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)), 221 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
214 static_cast<s64>(Param(system, 3))) 222 static_cast<s64>(Param(system, 3)))
@@ -219,14 +227,14 @@ void SvcWrap(Core::System& system) {
219} 227}
220 228
221template <ResultCode func(Core::System&, u64, u64, u32, s64)> 229template <ResultCode func(Core::System&, u64, u64, u32, s64)>
222void SvcWrap(Core::System& system) { 230void SvcWrap64(Core::System& system) {
223 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 231 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
224 static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3))) 232 static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
225 .raw); 233 .raw);
226} 234}
227 235
228template <ResultCode func(Core::System&, u64*, u64, u64, u64)> 236template <ResultCode func(Core::System&, u64*, u64, u64, u64)>
229void SvcWrap(Core::System& system) { 237void SvcWrap64(Core::System& system) {
230 u64 param_1 = 0; 238 u64 param_1 = 0;
231 const u32 retval = 239 const u32 retval =
232 func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw; 240 func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw;
@@ -236,7 +244,7 @@ void SvcWrap(Core::System& system) {
236} 244}
237 245
238template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)> 246template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)>
239void SvcWrap(Core::System& system) { 247void SvcWrap64(Core::System& system) {
240 u32 param_1 = 0; 248 u32 param_1 = 0;
241 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3), 249 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3),
242 static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5))) 250 static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5)))
@@ -247,7 +255,7 @@ void SvcWrap(Core::System& system) {
247} 255}
248 256
249template <ResultCode func(Core::System&, u32*, u64, u64, u32)> 257template <ResultCode func(Core::System&, u32*, u64, u64, u32)>
250void SvcWrap(Core::System& system) { 258void SvcWrap64(Core::System& system) {
251 u32 param_1 = 0; 259 u32 param_1 = 0;
252 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), 260 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
253 static_cast<u32>(Param(system, 3))) 261 static_cast<u32>(Param(system, 3)))
@@ -258,7 +266,7 @@ void SvcWrap(Core::System& system) {
258} 266}
259 267
260template <ResultCode func(Core::System&, Handle*, u64, u32, u32)> 268template <ResultCode func(Core::System&, Handle*, u64, u32, u32)>
261void SvcWrap(Core::System& system) { 269void SvcWrap64(Core::System& system) {
262 u32 param_1 = 0; 270 u32 param_1 = 0;
263 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)), 271 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
264 static_cast<u32>(Param(system, 3))) 272 static_cast<u32>(Param(system, 3)))
@@ -269,14 +277,14 @@ void SvcWrap(Core::System& system) {
269} 277}
270 278
271template <ResultCode func(Core::System&, u64, u32, s32, s64)> 279template <ResultCode func(Core::System&, u64, u32, s32, s64)>
272void SvcWrap(Core::System& system) { 280void SvcWrap64(Core::System& system) {
273 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)), 281 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
274 static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3))) 282 static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
275 .raw); 283 .raw);
276} 284}
277 285
278template <ResultCode func(Core::System&, u64, u32, s32, s32)> 286template <ResultCode func(Core::System&, u64, u32, s32, s32)>
279void SvcWrap(Core::System& system) { 287void SvcWrap64(Core::System& system) {
280 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)), 288 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
281 static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3))) 289 static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
282 .raw); 290 .raw);
@@ -286,7 +294,7 @@ void SvcWrap(Core::System& system) {
286// Function wrappers that return type u32 294// Function wrappers that return type u32
287 295
288template <u32 func(Core::System&)> 296template <u32 func(Core::System&)>
289void SvcWrap(Core::System& system) { 297void SvcWrap64(Core::System& system) {
290 FuncReturn(system, func(system)); 298 FuncReturn(system, func(system));
291} 299}
292 300
@@ -294,7 +302,7 @@ void SvcWrap(Core::System& system) {
294// Function wrappers that return type u64 302// Function wrappers that return type u64
295 303
296template <u64 func(Core::System&)> 304template <u64 func(Core::System&)>
297void SvcWrap(Core::System& system) { 305void SvcWrap64(Core::System& system) {
298 FuncReturn(system, func(system)); 306 FuncReturn(system, func(system));
299} 307}
300 308
@@ -302,44 +310,110 @@ void SvcWrap(Core::System& system) {
302/// Function wrappers that return type void 310/// Function wrappers that return type void
303 311
304template <void func(Core::System&)> 312template <void func(Core::System&)>
305void SvcWrap(Core::System& system) { 313void SvcWrap64(Core::System& system) {
306 func(system); 314 func(system);
307} 315}
308 316
309template <void func(Core::System&, u32)> 317template <void func(Core::System&, u32)>
310void SvcWrap(Core::System& system) { 318void SvcWrap64(Core::System& system) {
311 func(system, static_cast<u32>(Param(system, 0))); 319 func(system, static_cast<u32>(Param(system, 0)));
312} 320}
313 321
314template <void func(Core::System&, u32, u64, u64, u64)> 322template <void func(Core::System&, u32, u64, u64, u64)>
315void SvcWrap(Core::System& system) { 323void SvcWrap64(Core::System& system) {
316 func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2), 324 func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2),
317 Param(system, 3)); 325 Param(system, 3));
318} 326}
319 327
320template <void func(Core::System&, s64)> 328template <void func(Core::System&, s64)>
321void SvcWrap(Core::System& system) { 329void SvcWrap64(Core::System& system) {
322 func(system, static_cast<s64>(Param(system, 0))); 330 func(system, static_cast<s64>(Param(system, 0)));
323} 331}
324 332
325template <void func(Core::System&, u64, s32)> 333template <void func(Core::System&, u64, s32)>
326void SvcWrap(Core::System& system) { 334void SvcWrap64(Core::System& system) {
327 func(system, Param(system, 0), static_cast<s32>(Param(system, 1))); 335 func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));
328} 336}
329 337
330template <void func(Core::System&, u64, u64)> 338template <void func(Core::System&, u64, u64)>
331void SvcWrap(Core::System& system) { 339void SvcWrap64(Core::System& system) {
332 func(system, Param(system, 0), Param(system, 1)); 340 func(system, Param(system, 0), Param(system, 1));
333} 341}
334 342
335template <void func(Core::System&, u64, u64, u64)> 343template <void func(Core::System&, u64, u64, u64)>
336void SvcWrap(Core::System& system) { 344void SvcWrap64(Core::System& system) {
337 func(system, Param(system, 0), Param(system, 1), Param(system, 2)); 345 func(system, Param(system, 0), Param(system, 1), Param(system, 2));
338} 346}
339 347
340template <void func(Core::System&, u32, u64, u64)> 348template <void func(Core::System&, u32, u64, u64)>
341void SvcWrap(Core::System& system) { 349void SvcWrap64(Core::System& system) {
342 func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)); 350 func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2));
343} 351}
344 352
353// Used by QueryMemory32
354template <ResultCode func(Core::System&, u32, u32, u32)>
355void SvcWrap32(Core::System& system) {
356 FuncReturn32(system,
357 func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw);
358}
359
360// Used by GetInfo32
361template <ResultCode func(Core::System&, u32*, u32*, u32, u32, u32, u32)>
362void SvcWrap32(Core::System& system) {
363 u32 param_1 = 0;
364 u32 param_2 = 0;
365
366 const u32 retval = func(system, &param_1, &param_2, Param32(system, 0), Param32(system, 1),
367 Param32(system, 2), Param32(system, 3))
368 .raw;
369
370 system.CurrentArmInterface().SetReg(1, param_1);
371 system.CurrentArmInterface().SetReg(2, param_2);
372 FuncReturn(system, retval);
373}
374
375// Used by GetThreadPriority32, ConnectToNamedPort32
376template <ResultCode func(Core::System&, u32*, u32)>
377void SvcWrap32(Core::System& system) {
378 u32 param_1 = 0;
379 const u32 retval = func(system, &param_1, Param32(system, 1)).raw;
380 system.CurrentArmInterface().SetReg(1, param_1);
381 FuncReturn(system, retval);
382}
383
384// Used by GetThreadId32
385template <ResultCode func(Core::System&, u32*, u32*, u32)>
386void SvcWrap32(Core::System& system) {
387 u32 param_1 = 0;
388 u32 param_2 = 0;
389
390 const u32 retval = func(system, &param_1, &param_2, Param32(system, 1)).raw;
391 system.CurrentArmInterface().SetReg(1, param_1);
392 system.CurrentArmInterface().SetReg(2, param_2);
393 FuncReturn(system, retval);
394}
395
396// Used by SignalProcessWideKey32
397template <void func(Core::System&, u32, s32)>
398void SvcWrap32(Core::System& system) {
399 func(system, static_cast<u32>(Param(system, 0)), static_cast<s32>(Param(system, 1)));
400}
401
402// Used by SendSyncRequest32
403template <ResultCode func(Core::System&, u32)>
404void SvcWrap32(Core::System& system) {
405 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
406}
407
408// Used by WaitSynchronization32
409template <ResultCode func(Core::System&, u32, u32, s32, u32, Handle*)>
410void SvcWrap32(Core::System& system) {
411 u32 param_1 = 0;
412 const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2),
413 Param32(system, 3), &param_1)
414 .raw;
415 system.CurrentArmInterface().SetReg(1, param_1);
416 FuncReturn(system, retval);
417}
418
345} // namespace Kernel 419} // namespace Kernel
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index bf850e0b2..83e956036 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -133,15 +133,16 @@ void Thread::CancelWait() {
133 ResumeFromWait(); 133 ResumeFromWait();
134} 134}
135 135
136/** 136static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top,
137 * Resets a thread context, making it ready to be scheduled and run by the CPU 137 u32 entry_point, u32 arg) {
138 * @param context Thread context to reset 138 context = {};
139 * @param stack_top Address of the top of the stack 139 context.cpu_registers[0] = arg;
140 * @param entry_point Address of entry point for execution 140 context.cpu_registers[15] = entry_point;
141 * @param arg User argument for thread 141 context.cpu_registers[13] = stack_top;
142 */ 142}
143static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAddr stack_top, 143
144 VAddr entry_point, u64 arg) { 144static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top,
145 VAddr entry_point, u64 arg) {
145 context = {}; 146 context = {};
146 context.cpu_registers[0] = arg; 147 context.cpu_registers[0] = arg;
147 context.pc = entry_point; 148 context.pc = entry_point;
@@ -198,9 +199,9 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin
198 199
199 thread->owner_process->RegisterThread(thread.get()); 200 thread->owner_process->RegisterThread(thread.get());
200 201
201 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 202 ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top),
202 // to initialize the context 203 static_cast<u32>(entry_point), static_cast<u32>(arg));
203 ResetThreadContext(thread->context, stack_top, entry_point, arg); 204 ResetThreadContext64(thread->context_64, stack_top, entry_point, arg);
204 205
205 return MakeResult<std::shared_ptr<Thread>>(std::move(thread)); 206 return MakeResult<std::shared_ptr<Thread>>(std::move(thread));
206} 207}
@@ -213,11 +214,13 @@ void Thread::SetPriority(u32 priority) {
213} 214}
214 215
215void Thread::SetWaitSynchronizationResult(ResultCode result) { 216void Thread::SetWaitSynchronizationResult(ResultCode result) {
216 context.cpu_registers[0] = result.raw; 217 context_32.cpu_registers[0] = result.raw;
218 context_64.cpu_registers[0] = result.raw;
217} 219}
218 220
219void Thread::SetWaitSynchronizationOutput(s32 output) { 221void Thread::SetWaitSynchronizationOutput(s32 output) {
220 context.cpu_registers[1] = output; 222 context_32.cpu_registers[1] = output;
223 context_64.cpu_registers[1] = output;
221} 224}
222 225
223s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { 226s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 129e7858a..23fdef8a4 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -102,7 +102,8 @@ public:
102 102
103 using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>; 103 using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>;
104 104
105 using ThreadContext = Core::ARM_Interface::ThreadContext; 105 using ThreadContext32 = Core::ARM_Interface::ThreadContext32;
106 using ThreadContext64 = Core::ARM_Interface::ThreadContext64;
106 107
107 using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>; 108 using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>;
108 109
@@ -273,12 +274,20 @@ public:
273 return status == ThreadStatus::WaitSynch; 274 return status == ThreadStatus::WaitSynch;
274 } 275 }
275 276
276 ThreadContext& GetContext() { 277 ThreadContext32& GetContext32() {
277 return context; 278 return context_32;
278 } 279 }
279 280
280 const ThreadContext& GetContext() const { 281 const ThreadContext32& GetContext32() const {
281 return context; 282 return context_32;
283 }
284
285 ThreadContext64& GetContext64() {
286 return context_64;
287 }
288
289 const ThreadContext64& GetContext64() const {
290 return context_64;
282 } 291 }
283 292
284 ThreadStatus GetStatus() const { 293 ThreadStatus GetStatus() const {
@@ -466,7 +475,8 @@ private:
466 void AdjustSchedulingOnPriority(u32 old_priority); 475 void AdjustSchedulingOnPriority(u32 old_priority);
467 void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); 476 void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core);
468 477
469 Core::ARM_Interface::ThreadContext context{}; 478 ThreadContext32 context_32{};
479 ThreadContext64 context_64{};
470 480
471 u64 thread_id = 0; 481 u64 thread_id = 0;
472 482
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index d19c3623c..53559e8b1 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -129,12 +129,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
129 } 129 }
130 metadata.Print(); 130 metadata.Print();
131 131
132 const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
133 if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
134 arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
135 return {ResultStatus::Error32BitISA, {}};
136 }
137
138 if (process.LoadFromMetadata(metadata).IsError()) { 132 if (process.LoadFromMetadata(metadata).IsError()) {
139 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}}; 133 return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
140 } 134 }
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index f95eee3b1..85ac81ef7 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -111,7 +111,7 @@ json GetProcessorStateDataAuto(Core::System& system) {
111 const auto& vm_manager{process->VMManager()}; 111 const auto& vm_manager{process->VMManager()};
112 auto& arm{system.CurrentArmInterface()}; 112 auto& arm{system.CurrentArmInterface()};
113 113
114 Core::ARM_Interface::ThreadContext context{}; 114 Core::ARM_Interface::ThreadContext64 context{};
115 arm.SaveContext(context); 115 arm.SaveContext(context);
116 116
117 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", 117 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 3f1a94627..c1ea25fb8 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -116,7 +116,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
116 116
117 constexpr std::size_t BaseRegister = 29; 117 constexpr std::size_t BaseRegister = 29;
118 auto& memory = Core::System::GetInstance().Memory(); 118 auto& memory = Core::System::GetInstance().Memory();
119 u64 base_pointer = thread.GetContext().cpu_registers[BaseRegister]; 119 u64 base_pointer = thread.GetContext64().cpu_registers[BaseRegister];
120 120
121 while (base_pointer != 0) { 121 while (base_pointer != 0) {
122 const u64 lr = memory.Read64(base_pointer + sizeof(u64)); 122 const u64 lr = memory.Read64(base_pointer + sizeof(u64));
@@ -240,7 +240,7 @@ QString WaitTreeThread::GetText() const {
240 break; 240 break;
241 } 241 }
242 242
243 const auto& context = thread.GetContext(); 243 const auto& context = thread.GetContext64();
244 const QString pc_info = tr(" PC = 0x%1 LR = 0x%2") 244 const QString pc_info = tr(" PC = 0x%1 LR = 0x%2")
245 .arg(context.pc, 8, 16, QLatin1Char{'0'}) 245 .arg(context.pc, 8, 16, QLatin1Char{'0'})
246 .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'}); 246 .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'});