diff options
Diffstat (limited to 'src')
21 files changed, 454 insertions, 122 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index df1e62d4f..b31a0328c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -595,8 +595,10 @@ 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 | ||
| 600 | arm/dynarmic/arm_dynarmic_cp15.cpp | 602 | arm/dynarmic/arm_dynarmic_cp15.cpp |
| 601 | arm/dynarmic/arm_dynarmic_cp15.h | 603 | arm/dynarmic/arm_dynarmic_cp15.h |
| 602 | ) | 604 | ) |
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/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/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/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'}); |