diff options
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 | ||
| 596 | if (ARCHITECTURE_x86_64) | 596 | if (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) |
| 602 | endif() | 606 | endif() |
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 | |||
| 20 | namespace Core { | ||
| 21 | |||
| 22 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | ||
| 23 | public: | ||
| 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 | |||
| 96 | std::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 | |||
| 107 | MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_32, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); | ||
| 108 | |||
| 109 | void ARM_Dynarmic_32::Run() { | ||
| 110 | MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_32); | ||
| 111 | jit->Run(); | ||
| 112 | } | ||
| 113 | |||
| 114 | void ARM_Dynarmic_32::Step() { | ||
| 115 | cb->InterpreterFallback(jit->Regs()[15], 1); | ||
| 116 | } | ||
| 117 | |||
| 118 | ARM_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 | |||
| 124 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; | ||
| 125 | |||
| 126 | void ARM_Dynarmic_32::SetPC(u64 pc) { | ||
| 127 | jit->Regs()[15] = static_cast<u32>(pc); | ||
| 128 | } | ||
| 129 | |||
| 130 | u64 ARM_Dynarmic_32::GetPC() const { | ||
| 131 | return jit->Regs()[15]; | ||
| 132 | } | ||
| 133 | |||
| 134 | u64 ARM_Dynarmic_32::GetReg(int index) const { | ||
| 135 | return jit->Regs()[index]; | ||
| 136 | } | ||
| 137 | |||
| 138 | void ARM_Dynarmic_32::SetReg(int index, u64 value) { | ||
| 139 | jit->Regs()[index] = static_cast<u32>(value); | ||
| 140 | } | ||
| 141 | |||
| 142 | u128 ARM_Dynarmic_32::GetVectorReg(int index) const { | ||
| 143 | return {}; | ||
| 144 | } | ||
| 145 | |||
| 146 | void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {} | ||
| 147 | |||
| 148 | u32 ARM_Dynarmic_32::GetPSTATE() const { | ||
| 149 | return jit->Cpsr(); | ||
| 150 | } | ||
| 151 | |||
| 152 | void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) { | ||
| 153 | jit->SetCpsr(cpsr); | ||
| 154 | } | ||
| 155 | |||
| 156 | u64 ARM_Dynarmic_32::GetTlsAddress() const { | ||
| 157 | return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; | ||
| 158 | } | ||
| 159 | |||
| 160 | void ARM_Dynarmic_32::SetTlsAddress(VAddr address) { | ||
| 161 | CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address); | ||
| 162 | } | ||
| 163 | |||
| 164 | u64 ARM_Dynarmic_32::GetTPIDR_EL0() const { | ||
| 165 | return cb->tpidr_el0; | ||
| 166 | } | ||
| 167 | |||
| 168 | void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { | ||
| 169 | cb->tpidr_el0 = value; | ||
| 170 | } | ||
| 171 | |||
| 172 | void 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 | |||
| 179 | void 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 | |||
| 186 | void ARM_Dynarmic_32::PrepareReschedule() { | ||
| 187 | jit->HaltExecution(); | ||
| 188 | } | ||
| 189 | |||
| 190 | void ARM_Dynarmic_32::ClearInstructionCache() { | ||
| 191 | jit->ClearCache(); | ||
| 192 | } | ||
| 193 | |||
| 194 | void ARM_Dynarmic_32::ClearExclusiveState() {} | ||
| 195 | |||
| 196 | void 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 | |||
| 18 | namespace Memory { | ||
| 19 | class Memory; | ||
| 20 | } | ||
| 21 | |||
| 22 | namespace Core { | ||
| 23 | |||
| 24 | class DynarmicCallbacks32; | ||
| 25 | class DynarmicExclusiveMonitor; | ||
| 26 | class System; | ||
| 27 | |||
| 28 | class ARM_Dynarmic_32 final : public ARM_Interface { | ||
| 29 | public: | ||
| 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 | |||
| 60 | private: | ||
| 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 | ||
| 26 | using Vector = Dynarmic::A64::Vector; | 26 | using Vector = Dynarmic::A64::Vector; |
| 27 | 27 | ||
| 28 | class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks { | 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 29 | public: | 29 | public: |
| 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 | ||
| 135 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table, | 135 | std::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 | ||
| 165 | MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); | 165 | MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64)); |
| 166 | 166 | ||
| 167 | void ARM_Dynarmic::Run() { | 167 | void 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 | ||
| 173 | void ARM_Dynarmic::Step() { | 173 | void ARM_Dynarmic_64::Step() { |
| 174 | cb->InterpreterFallback(jit->GetPC(), 1); | 174 | cb->InterpreterFallback(jit->GetPC(), 1); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, | 177 | ARM_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 | ||
| 184 | ARM_Dynarmic::~ARM_Dynarmic() = default; | 184 | ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; |
| 185 | 185 | ||
| 186 | void ARM_Dynarmic::SetPC(u64 pc) { | 186 | void ARM_Dynarmic_64::SetPC(u64 pc) { |
| 187 | jit->SetPC(pc); | 187 | jit->SetPC(pc); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | u64 ARM_Dynarmic::GetPC() const { | 190 | u64 ARM_Dynarmic_64::GetPC() const { |
| 191 | return jit->GetPC(); | 191 | return jit->GetPC(); |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | u64 ARM_Dynarmic::GetReg(int index) const { | 194 | u64 ARM_Dynarmic_64::GetReg(int index) const { |
| 195 | return jit->GetRegister(index); | 195 | return jit->GetRegister(index); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | void ARM_Dynarmic::SetReg(int index, u64 value) { | 198 | void ARM_Dynarmic_64::SetReg(int index, u64 value) { |
| 199 | jit->SetRegister(index, value); | 199 | jit->SetRegister(index, value); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | u128 ARM_Dynarmic::GetVectorReg(int index) const { | 202 | u128 ARM_Dynarmic_64::GetVectorReg(int index) const { |
| 203 | return jit->GetVector(index); | 203 | return jit->GetVector(index); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | void ARM_Dynarmic::SetVectorReg(int index, u128 value) { | 206 | void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) { |
| 207 | jit->SetVector(index, value); | 207 | jit->SetVector(index, value); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | u32 ARM_Dynarmic::GetPSTATE() const { | 210 | u32 ARM_Dynarmic_64::GetPSTATE() const { |
| 211 | return jit->GetPstate(); | 211 | return jit->GetPstate(); |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | void ARM_Dynarmic::SetPSTATE(u32 pstate) { | 214 | void ARM_Dynarmic_64::SetPSTATE(u32 pstate) { |
| 215 | jit->SetPstate(pstate); | 215 | jit->SetPstate(pstate); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | u64 ARM_Dynarmic::GetTlsAddress() const { | 218 | u64 ARM_Dynarmic_64::GetTlsAddress() const { |
| 219 | return cb->tpidrro_el0; | 219 | return cb->tpidrro_el0; |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | void ARM_Dynarmic::SetTlsAddress(VAddr address) { | 222 | void ARM_Dynarmic_64::SetTlsAddress(VAddr address) { |
| 223 | cb->tpidrro_el0 = address; | 223 | cb->tpidrro_el0 = address; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | u64 ARM_Dynarmic::GetTPIDR_EL0() const { | 226 | u64 ARM_Dynarmic_64::GetTPIDR_EL0() const { |
| 227 | return cb->tpidr_el0; | 227 | return cb->tpidr_el0; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | void ARM_Dynarmic::SetTPIDR_EL0(u64 value) { | 230 | void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) { |
| 231 | cb->tpidr_el0 = value; | 231 | cb->tpidr_el0 = value; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | void ARM_Dynarmic::SaveContext(ThreadContext& ctx) { | 234 | void 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 | ||
| 245 | void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { | 245 | void 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 | ||
| 256 | void ARM_Dynarmic::PrepareReschedule() { | 256 | void ARM_Dynarmic_64::PrepareReschedule() { |
| 257 | jit->HaltExecution(); | 257 | jit->HaltExecution(); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | void ARM_Dynarmic::ClearInstructionCache() { | 260 | void ARM_Dynarmic_64::ClearInstructionCache() { |
| 261 | jit->ClearCache(); | 261 | jit->ClearCache(); |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | void ARM_Dynarmic::ClearExclusiveState() { | 264 | void ARM_Dynarmic_64::ClearExclusiveState() { |
| 265 | jit->ClearExclusiveState(); | 265 | jit->ClearExclusiveState(); |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table, | 268 | void 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 | ||
| 280 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count) | 280 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count) |
| 281 | : monitor(core_count), memory{memory_} {} | 281 | : monitor(core_count), memory{memory} {} |
| 282 | 282 | ||
| 283 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; | 283 | DynarmicExclusiveMonitor::~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 | ||
| 22 | namespace Core { | 22 | namespace Core { |
| 23 | 23 | ||
| 24 | class ARM_Dynarmic_Callbacks; | 24 | class DynarmicCallbacks64; |
| 25 | class DynarmicExclusiveMonitor; | 25 | class DynarmicExclusiveMonitor; |
| 26 | class System; | 26 | class System; |
| 27 | 27 | ||
| 28 | using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; | 28 | class ARM_Dynarmic_64 final : public ARM_Interface { |
| 29 | using JitCacheType = | ||
| 30 | std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>; | ||
| 31 | |||
| 32 | class ARM_Dynarmic final : public ARM_Interface { | ||
| 33 | public: | 29 | public: |
| 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 | ||
| 76 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { | 78 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { |
| 77 | public: | 79 | public: |
| 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 | ||
| 90 | private: | 92 | private: |
| 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 | |||
| 7 | using Callback = Dynarmic::A32::Coprocessor::Callback; | ||
| 8 | using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; | ||
| 9 | using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; | ||
| 10 | |||
| 11 | std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1, | ||
| 12 | CoprocReg CRd, CoprocReg CRn, | ||
| 13 | CoprocReg CRm, unsigned opc2) { | ||
| 14 | return {}; | ||
| 15 | } | ||
| 16 | |||
| 17 | CallbackOrAccessOneWord 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 | |||
| 46 | CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) { | ||
| 47 | return {}; | ||
| 48 | } | ||
| 49 | |||
| 50 | CallbackOrAccessOneWord 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 | |||
| 68 | CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { | ||
| 69 | return {}; | ||
| 70 | } | ||
| 71 | |||
| 72 | std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, | ||
| 73 | std::optional<u8> option) { | ||
| 74 | return {}; | ||
| 75 | } | ||
| 76 | |||
| 77 | std::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 | |||
| 13 | enum 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 | |||
| 130 | class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { | ||
| 131 | public: | ||
| 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 | |||
| 150 | private: | ||
| 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 | ||
| 191 | void ARM_Unicorn::SaveContext(ThreadContext& ctx) { | 191 | void 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 | ||
| 218 | void ARM_Unicorn::LoadContext(const ThreadContext& ctx) { | 218 | void 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 | |||
| 44 | private: | 47 | private: |
| 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 | ||
| 32 | PhysicalCore::~PhysicalCore() = default; | 37 | PhysicalCore::~PhysicalCore() = default; |
| @@ -48,4 +53,12 @@ void PhysicalCore::Shutdown() { | |||
| 48 | scheduler->Shutdown(); | 53 | scheduler->Shutdown(); |
| 49 | } | 54 | } |
| 50 | 55 | ||
| 56 | void 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 | |||
| 71 | private: | 73 | private: |
| 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 | ||
| 386 | Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) | 386 | Scheduler::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 | ||
| 389 | Scheduler::~Scheduler() = default; | 389 | Scheduler::~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 | ||
| 182 | class Scheduler final { | 182 | class Scheduler final { |
| 183 | public: | 183 | public: |
| 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 | ||
| 190 | static 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 | |||
| 190 | static ResultCode SetMemoryPermission(Core::System& system, VAddr addr, u64 size, u32 prot) { | 197 | static 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 | ||
| 381 | static 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. |
| 375 | static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | 388 | static 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 | ||
| 406 | static 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. |
| 394 | static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) { | 411 | static 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 | ||
| 425 | static 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. |
| 409 | static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { | 437 | static 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 | ||
| 510 | static 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 |
| 483 | static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { | 517 | static 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 | ||
| 954 | static 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 |
| 921 | static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { | 967 | static 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 | ||
| 1137 | static 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 |
| 1092 | static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { | 1142 | static 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 | ||
| 1312 | static 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 | |||
| 1262 | static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address, | 1317 | static 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 | ||
| 1733 | static 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) |
| 1679 | static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value, | 1738 | static 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 | ||
| 1822 | static 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. |
| 1764 | static ResultCode ResetSignal(Core::System& system, Handle handle) { | 1827 | static 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 | ||
| 2320 | static const FunctionDef SVC_Table[] = { | 2383 | static 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 | |||
| 2510 | static 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 | ||
| 2451 | static const FunctionDef* GetSVCInfo(u32 func_num) { | 2641 | static 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 | |||
| 2649 | static 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 | ||
| 2459 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | 2657 | MICROPROFILE_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 | ||
| 18 | static 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 | ||
| 31 | static 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 | ||
| 30 | template <ResultCode func(Core::System&, u64)> | 38 | template <ResultCode func(Core::System&, u64)> |
| 31 | void SvcWrap(Core::System& system) { | 39 | void 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 | ||
| 35 | template <ResultCode func(Core::System&, u64, u64)> | 43 | template <ResultCode func(Core::System&, u64, u64)> |
| 36 | void SvcWrap(Core::System& system) { | 44 | void 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 | ||
| 40 | template <ResultCode func(Core::System&, u32)> | 48 | template <ResultCode func(Core::System&, u32)> |
| 41 | void SvcWrap(Core::System& system) { | 49 | void 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 | ||
| 45 | template <ResultCode func(Core::System&, u32, u32)> | 53 | template <ResultCode func(Core::System&, u32, u32)> |
| 46 | void SvcWrap(Core::System& system) { | 54 | void 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 | ||
| 52 | template <ResultCode func(Core::System&, u32, u64, u64, u64)> | 60 | template <ResultCode func(Core::System&, u32, u64, u64, u64)> |
| 53 | void SvcWrap(Core::System& system) { | 61 | void 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 | ||
| 59 | template <ResultCode func(Core::System&, u32*)> | 67 | template <ResultCode func(Core::System&, u32*)> |
| 60 | void SvcWrap(Core::System& system) { | 68 | void SvcWrap64(Core::System& system) { |
| 61 | u32 param = 0; | 69 | u32 param = 0; |
| 62 | const u32 retval = func(system, ¶m).raw; | 70 | const u32 retval = func(system, ¶m).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 | ||
| 67 | template <ResultCode func(Core::System&, u32*, u32)> | 75 | template <ResultCode func(Core::System&, u32*, u32)> |
| 68 | void SvcWrap(Core::System& system) { | 76 | void SvcWrap64(Core::System& system) { |
| 69 | u32 param_1 = 0; | 77 | u32 param_1 = 0; |
| 70 | const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw; | 78 | const u32 retval = func(system, ¶m_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 | ||
| 75 | template <ResultCode func(Core::System&, u32*, u32*)> | 83 | template <ResultCode func(Core::System&, u32*, u32*)> |
| 76 | void SvcWrap(Core::System& system) { | 84 | void 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, ¶m_1, ¶m_2).raw; | 87 | const u32 retval = func(system, ¶m_1, ¶m_2).raw; |
| @@ -86,7 +94,7 @@ void SvcWrap(Core::System& system) { | |||
| 86 | } | 94 | } |
| 87 | 95 | ||
| 88 | template <ResultCode func(Core::System&, u32*, u64)> | 96 | template <ResultCode func(Core::System&, u32*, u64)> |
| 89 | void SvcWrap(Core::System& system) { | 97 | void SvcWrap64(Core::System& system) { |
| 90 | u32 param_1 = 0; | 98 | u32 param_1 = 0; |
| 91 | const u32 retval = func(system, ¶m_1, Param(system, 1)).raw; | 99 | const u32 retval = func(system, ¶m_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 | ||
| 96 | template <ResultCode func(Core::System&, u32*, u64, u32)> | 104 | template <ResultCode func(Core::System&, u32*, u64, u32)> |
| 97 | void SvcWrap(Core::System& system) { | 105 | void 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, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw; | 108 | func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw; |
| @@ -104,7 +112,7 @@ void SvcWrap(Core::System& system) { | |||
| 104 | } | 112 | } |
| 105 | 113 | ||
| 106 | template <ResultCode func(Core::System&, u64*, u32)> | 114 | template <ResultCode func(Core::System&, u64*, u32)> |
| 107 | void SvcWrap(Core::System& system) { | 115 | void SvcWrap64(Core::System& system) { |
| 108 | u64 param_1 = 0; | 116 | u64 param_1 = 0; |
| 109 | const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw; | 117 | const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1))).raw; |
| 110 | 118 | ||
| @@ -113,12 +121,12 @@ void SvcWrap(Core::System& system) { | |||
| 113 | } | 121 | } |
| 114 | 122 | ||
| 115 | template <ResultCode func(Core::System&, u64, u32)> | 123 | template <ResultCode func(Core::System&, u64, u32)> |
| 116 | void SvcWrap(Core::System& system) { | 124 | void 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 | ||
| 120 | template <ResultCode func(Core::System&, u64*, u64)> | 128 | template <ResultCode func(Core::System&, u64*, u64)> |
| 121 | void SvcWrap(Core::System& system) { | 129 | void SvcWrap64(Core::System& system) { |
| 122 | u64 param_1 = 0; | 130 | u64 param_1 = 0; |
| 123 | const u32 retval = func(system, ¶m_1, Param(system, 1)).raw; | 131 | const u32 retval = func(system, ¶m_1, Param(system, 1)).raw; |
| 124 | 132 | ||
| @@ -127,7 +135,7 @@ void SvcWrap(Core::System& system) { | |||
| 127 | } | 135 | } |
| 128 | 136 | ||
| 129 | template <ResultCode func(Core::System&, u64*, u32, u32)> | 137 | template <ResultCode func(Core::System&, u64*, u32, u32)> |
| 130 | void SvcWrap(Core::System& system) { | 138 | void SvcWrap64(Core::System& system) { |
| 131 | u64 param_1 = 0; | 139 | u64 param_1 = 0; |
| 132 | const u32 retval = func(system, ¶m_1, static_cast<u32>(Param(system, 1)), | 140 | const u32 retval = func(system, ¶m_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 | ||
| 140 | template <ResultCode func(Core::System&, u32, u64)> | 148 | template <ResultCode func(Core::System&, u32, u64)> |
| 141 | void SvcWrap(Core::System& system) { | 149 | void 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 | ||
| 145 | template <ResultCode func(Core::System&, u32, u32, u64)> | 153 | template <ResultCode func(Core::System&, u32, u32, u64)> |
| 146 | void SvcWrap(Core::System& system) { | 154 | void 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 | ||
| 152 | template <ResultCode func(Core::System&, u32, u32*, u64*)> | 160 | template <ResultCode func(Core::System&, u32, u32*, u64*)> |
| 153 | void SvcWrap(Core::System& system) { | 161 | void 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)), ¶m_1, ¶m_2); | 164 | const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), ¶m_1, ¶m_2); |
| @@ -161,54 +169,54 @@ void SvcWrap(Core::System& system) { | |||
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | template <ResultCode func(Core::System&, u64, u64, u32, u32)> | 171 | template <ResultCode func(Core::System&, u64, u64, u32, u32)> |
| 164 | void SvcWrap(Core::System& system) { | 172 | void 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 | ||
| 170 | template <ResultCode func(Core::System&, u64, u64, u32, u64)> | 178 | template <ResultCode func(Core::System&, u64, u64, u32, u64)> |
| 171 | void SvcWrap(Core::System& system) { | 179 | void 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 | ||
| 177 | template <ResultCode func(Core::System&, u32, u64, u32)> | 185 | template <ResultCode func(Core::System&, u32, u64, u32)> |
| 178 | void SvcWrap(Core::System& system) { | 186 | void 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 | ||
| 184 | template <ResultCode func(Core::System&, u64, u64, u64)> | 192 | template <ResultCode func(Core::System&, u64, u64, u64)> |
| 185 | void SvcWrap(Core::System& system) { | 193 | void 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 | ||
| 189 | template <ResultCode func(Core::System&, u64, u64, u32)> | 197 | template <ResultCode func(Core::System&, u64, u64, u32)> |
| 190 | void SvcWrap(Core::System& system) { | 198 | void 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 | ||
| 196 | template <ResultCode func(Core::System&, u32, u64, u64, u32)> | 204 | template <ResultCode func(Core::System&, u32, u64, u64, u32)> |
| 197 | void SvcWrap(Core::System& system) { | 205 | void 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 | ||
| 203 | template <ResultCode func(Core::System&, u32, u64, u64)> | 211 | template <ResultCode func(Core::System&, u32, u64, u64)> |
| 204 | void SvcWrap(Core::System& system) { | 212 | void 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 | ||
| 210 | template <ResultCode func(Core::System&, u32*, u64, u64, s64)> | 218 | template <ResultCode func(Core::System&, u32*, u64, u64, s64)> |
| 211 | void SvcWrap(Core::System& system) { | 219 | void SvcWrap64(Core::System& system) { |
| 212 | u32 param_1 = 0; | 220 | u32 param_1 = 0; |
| 213 | const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2)), | 221 | const u32 retval = func(system, ¶m_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 | ||
| 221 | template <ResultCode func(Core::System&, u64, u64, u32, s64)> | 229 | template <ResultCode func(Core::System&, u64, u64, u32, s64)> |
| 222 | void SvcWrap(Core::System& system) { | 230 | void 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 | ||
| 228 | template <ResultCode func(Core::System&, u64*, u64, u64, u64)> | 236 | template <ResultCode func(Core::System&, u64*, u64, u64, u64)> |
| 229 | void SvcWrap(Core::System& system) { | 237 | void 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, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw; | 240 | func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3)).raw; |
| @@ -236,7 +244,7 @@ void SvcWrap(Core::System& system) { | |||
| 236 | } | 244 | } |
| 237 | 245 | ||
| 238 | template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)> | 246 | template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)> |
| 239 | void SvcWrap(Core::System& system) { | 247 | void SvcWrap64(Core::System& system) { |
| 240 | u32 param_1 = 0; | 248 | u32 param_1 = 0; |
| 241 | const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), Param(system, 3), | 249 | const u32 retval = func(system, ¶m_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 | ||
| 249 | template <ResultCode func(Core::System&, u32*, u64, u64, u32)> | 257 | template <ResultCode func(Core::System&, u32*, u64, u64, u32)> |
| 250 | void SvcWrap(Core::System& system) { | 258 | void SvcWrap64(Core::System& system) { |
| 251 | u32 param_1 = 0; | 259 | u32 param_1 = 0; |
| 252 | const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2), | 260 | const u32 retval = func(system, ¶m_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 | ||
| 260 | template <ResultCode func(Core::System&, Handle*, u64, u32, u32)> | 268 | template <ResultCode func(Core::System&, Handle*, u64, u32, u32)> |
| 261 | void SvcWrap(Core::System& system) { | 269 | void SvcWrap64(Core::System& system) { |
| 262 | u32 param_1 = 0; | 270 | u32 param_1 = 0; |
| 263 | const u32 retval = func(system, ¶m_1, Param(system, 1), static_cast<u32>(Param(system, 2)), | 271 | const u32 retval = func(system, ¶m_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 | ||
| 271 | template <ResultCode func(Core::System&, u64, u32, s32, s64)> | 279 | template <ResultCode func(Core::System&, u64, u32, s32, s64)> |
| 272 | void SvcWrap(Core::System& system) { | 280 | void 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 | ||
| 278 | template <ResultCode func(Core::System&, u64, u32, s32, s32)> | 286 | template <ResultCode func(Core::System&, u64, u32, s32, s32)> |
| 279 | void SvcWrap(Core::System& system) { | 287 | void 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 | ||
| 288 | template <u32 func(Core::System&)> | 296 | template <u32 func(Core::System&)> |
| 289 | void SvcWrap(Core::System& system) { | 297 | void 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 | ||
| 296 | template <u64 func(Core::System&)> | 304 | template <u64 func(Core::System&)> |
| 297 | void SvcWrap(Core::System& system) { | 305 | void 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 | ||
| 304 | template <void func(Core::System&)> | 312 | template <void func(Core::System&)> |
| 305 | void SvcWrap(Core::System& system) { | 313 | void SvcWrap64(Core::System& system) { |
| 306 | func(system); | 314 | func(system); |
| 307 | } | 315 | } |
| 308 | 316 | ||
| 309 | template <void func(Core::System&, u32)> | 317 | template <void func(Core::System&, u32)> |
| 310 | void SvcWrap(Core::System& system) { | 318 | void 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 | ||
| 314 | template <void func(Core::System&, u32, u64, u64, u64)> | 322 | template <void func(Core::System&, u32, u64, u64, u64)> |
| 315 | void SvcWrap(Core::System& system) { | 323 | void 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 | ||
| 320 | template <void func(Core::System&, s64)> | 328 | template <void func(Core::System&, s64)> |
| 321 | void SvcWrap(Core::System& system) { | 329 | void 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 | ||
| 325 | template <void func(Core::System&, u64, s32)> | 333 | template <void func(Core::System&, u64, s32)> |
| 326 | void SvcWrap(Core::System& system) { | 334 | void 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 | ||
| 330 | template <void func(Core::System&, u64, u64)> | 338 | template <void func(Core::System&, u64, u64)> |
| 331 | void SvcWrap(Core::System& system) { | 339 | void 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 | ||
| 335 | template <void func(Core::System&, u64, u64, u64)> | 343 | template <void func(Core::System&, u64, u64, u64)> |
| 336 | void SvcWrap(Core::System& system) { | 344 | void 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 | ||
| 340 | template <void func(Core::System&, u32, u64, u64)> | 348 | template <void func(Core::System&, u32, u64, u64)> |
| 341 | void SvcWrap(Core::System& system) { | 349 | void 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 | ||
| 354 | template <ResultCode func(Core::System&, u32, u32, u32)> | ||
| 355 | void 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 | ||
| 361 | template <ResultCode func(Core::System&, u32*, u32*, u32, u32, u32, u32)> | ||
| 362 | void SvcWrap32(Core::System& system) { | ||
| 363 | u32 param_1 = 0; | ||
| 364 | u32 param_2 = 0; | ||
| 365 | |||
| 366 | const u32 retval = func(system, ¶m_1, ¶m_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 | ||
| 376 | template <ResultCode func(Core::System&, u32*, u32)> | ||
| 377 | void SvcWrap32(Core::System& system) { | ||
| 378 | u32 param_1 = 0; | ||
| 379 | const u32 retval = func(system, ¶m_1, Param32(system, 1)).raw; | ||
| 380 | system.CurrentArmInterface().SetReg(1, param_1); | ||
| 381 | FuncReturn(system, retval); | ||
| 382 | } | ||
| 383 | |||
| 384 | // Used by GetThreadId32 | ||
| 385 | template <ResultCode func(Core::System&, u32*, u32*, u32)> | ||
| 386 | void SvcWrap32(Core::System& system) { | ||
| 387 | u32 param_1 = 0; | ||
| 388 | u32 param_2 = 0; | ||
| 389 | |||
| 390 | const u32 retval = func(system, ¶m_1, ¶m_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 | ||
| 397 | template <void func(Core::System&, u32, s32)> | ||
| 398 | void 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 | ||
| 403 | template <ResultCode func(Core::System&, u32)> | ||
| 404 | void SvcWrap32(Core::System& system) { | ||
| 405 | FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw); | ||
| 406 | } | ||
| 407 | |||
| 408 | // Used by WaitSynchronization32 | ||
| 409 | template <ResultCode func(Core::System&, u32, u32, s32, u32, Handle*)> | ||
| 410 | void 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), ¶m_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 | /** | 136 | static 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 | } |
| 143 | static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAddr stack_top, | 143 | |
| 144 | VAddr entry_point, u64 arg) { | 144 | static 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 | ||
| 215 | void Thread::SetWaitSynchronizationResult(ResultCode result) { | 216 | void 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 | ||
| 219 | void Thread::SetWaitSynchronizationOutput(s32 output) { | 221 | void 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 | ||
| 223 | s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { | 226 | s32 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'}); |