diff --git a/externals/dynarmic b/externals/dynarmic index 4b350a354..68ca03e8d 160000 --- a/externals/dynarmic +++ b/externals/dynarmic @@ -1 +1 @@ -Subproject commit 4b350a354a21339052c7fff88832c3f81f5624be +Subproject commit 68ca03e8d4822c78e15315e67ddbb1d6bf4d3827 diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 461f1e564..c1bde8cbf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -3,8 +3,8 @@ // Refer to the license.txt file included. #include -#include -#include +#include +#include #include "common/assert.h" #include "common/microprofile.h" #include "core/arm/dynarmic/arm_dynarmic.h" @@ -64,86 +64,101 @@ public: private: friend class ARM_Dynarmic; - Dynarmic::Context ctx; + Dynarmic::A32::Context ctx; u32 fpexc; }; -static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void* user_arg) { - ARMul_State* state = static_cast(user_arg); +class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks { +public: + explicit DynarmicUserCallbacks(ARM_Dynarmic& parent) : parent(parent) {} + ~DynarmicUserCallbacks() = default; - state->Reg = jit->Regs(); - state->Cpsr = jit->Cpsr(); - state->Reg[15] = pc; - state->ExtReg = jit->ExtRegs(); - state->VFP[VFP_FPSCR] = jit->Fpscr(); - state->NumInstrsToExecute = 1; + std::uint8_t MemoryRead8(VAddr vaddr) override { + return Memory::Read8(vaddr); + } + std::uint16_t MemoryRead16(VAddr vaddr) override { + return Memory::Read16(vaddr); + } + std::uint32_t MemoryRead32(VAddr vaddr) override { + return Memory::Read32(vaddr); + } + std::uint64_t MemoryRead64(VAddr vaddr) override { + return Memory::Read64(vaddr); + } - InterpreterMainLoop(state); + void MemoryWrite8(VAddr vaddr, std::uint8_t value) override { + Memory::Write8(vaddr, value); + } + void MemoryWrite16(VAddr vaddr, std::uint16_t value) override { + Memory::Write16(vaddr, value); + } + void MemoryWrite32(VAddr vaddr, std::uint32_t value) override { + Memory::Write32(vaddr, value); + } + void MemoryWrite64(VAddr vaddr, std::uint64_t value) override { + Memory::Write64(vaddr, value); + } - bool is_thumb = (state->Cpsr & (1 << 5)) != 0; - state->Reg[15] &= (is_thumb ? 0xFFFFFFFE : 0xFFFFFFFC); + void InterpreterFallback(VAddr pc, size_t num_instructions) override { + parent.interpreter_state->Reg = parent.jit->Regs(); + parent.interpreter_state->Cpsr = parent.jit->Cpsr(); + parent.interpreter_state->Reg[15] = pc; + parent.interpreter_state->ExtReg = parent.jit->ExtRegs(); + parent.interpreter_state->VFP[VFP_FPSCR] = parent.jit->Fpscr(); + parent.interpreter_state->NumInstrsToExecute = num_instructions; - jit->Regs() = state->Reg; - jit->SetCpsr(state->Cpsr); - jit->ExtRegs() = state->ExtReg; - jit->SetFpscr(state->VFP[VFP_FPSCR]); + InterpreterMainLoop(parent.interpreter_state.get()); - state->ServeBreak(); -} + bool is_thumb = (parent.interpreter_state->Cpsr & (1 << 5)) != 0; + parent.interpreter_state->Reg[15] &= (is_thumb ? 0xFFFFFFFE : 0xFFFFFFFC); -static bool IsReadOnlyMemory(u32 vaddr) { - // TODO(bunnei): ImplementMe - return false; -} + parent.jit->Regs() = parent.interpreter_state->Reg; + parent.jit->SetCpsr(parent.interpreter_state->Cpsr); + parent.jit->ExtRegs() = parent.interpreter_state->ExtReg; + parent.jit->SetFpscr(parent.interpreter_state->VFP[VFP_FPSCR]); -static void AddTicks(u64 ticks) { - CoreTiming::AddTicks(ticks); -} + parent.interpreter_state->ServeBreak(); + } -static u64 GetTicksRemaining() { - s64 ticks = CoreTiming::GetDowncount(); - return static_cast(ticks <= 0 ? 0 : ticks); -} + void CallSVC(std::uint32_t swi) override { + Kernel::CallSVC(swi); + } -static Dynarmic::UserCallbacks GetUserCallbacks( - const std::shared_ptr& interpreter_state, Memory::PageTable* current_page_table) { - Dynarmic::UserCallbacks user_callbacks{}; - user_callbacks.InterpreterFallback = &InterpreterFallback; - user_callbacks.user_arg = static_cast(interpreter_state.get()); - user_callbacks.CallSVC = &Kernel::CallSVC; - user_callbacks.memory.IsReadOnlyMemory = &IsReadOnlyMemory; - user_callbacks.memory.ReadCode = &Memory::Read32; - user_callbacks.memory.Read8 = &Memory::Read8; - user_callbacks.memory.Read16 = &Memory::Read16; - user_callbacks.memory.Read32 = &Memory::Read32; - user_callbacks.memory.Read64 = &Memory::Read64; - user_callbacks.memory.Write8 = &Memory::Write8; - user_callbacks.memory.Write16 = &Memory::Write16; - user_callbacks.memory.Write32 = &Memory::Write32; - user_callbacks.memory.Write64 = &Memory::Write64; - user_callbacks.AddTicks = &AddTicks; - user_callbacks.GetTicksRemaining = &GetTicksRemaining; - user_callbacks.page_table = ¤t_page_table->pointers; - user_callbacks.coprocessors[15] = std::make_shared(interpreter_state); - return user_callbacks; -} + void ExceptionRaised(VAddr pc, Dynarmic::A32::Exception exception) override { + ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:X})", + static_cast(exception), pc); + } -ARM_Dynarmic::ARM_Dynarmic(PrivilegeMode initial_mode) { + void AddTicks(std::uint64_t ticks) override { + CoreTiming::AddTicks(ticks); + } + std::uint64_t GetTicksRemaining() override { + s64 ticks = CoreTiming::GetDowncount(); + return static_cast(ticks <= 0 ? 0 : ticks); + } + + ARM_Dynarmic& parent; +}; + +ARM_Dynarmic::ARM_Dynarmic(PrivilegeMode initial_mode) + : cb(std::make_unique(*this)) { interpreter_state = std::make_shared(initial_mode); PageTableChanged(); } +ARM_Dynarmic::~ARM_Dynarmic() = default; + MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); void ARM_Dynarmic::Run() { ASSERT(Memory::GetCurrentPageTable() == current_page_table); MICROPROFILE_SCOPE(ARM_Jit); - jit->Run(GetTicksRemaining()); + jit->Run(); } void ARM_Dynarmic::Step() { - InterpreterFallback(jit->Regs()[15], jit, static_cast(interpreter_state.get())); + cb->InterpreterFallback(jit->Regs()[15], 1); } void ARM_Dynarmic::SetPC(u32 pc) { @@ -251,6 +266,16 @@ void ARM_Dynarmic::PageTableChanged() { return; } - jit = new Dynarmic::Jit(GetUserCallbacks(interpreter_state, current_page_table)); - jits.emplace(current_page_table, std::unique_ptr(jit)); + auto new_jit = MakeJit(); + jit = new_jit.get(); + jits.emplace(current_page_table, std::move(new_jit)); +} + +std::unique_ptr ARM_Dynarmic::MakeJit() { + Dynarmic::A32::UserConfig config; + config.callbacks = cb.get(); + config.page_table = ¤t_page_table->pointers; + config.coprocessors[15] = std::make_shared(interpreter_state); + config.define_unpredictable_behaviour = true; + return std::make_unique(config); } diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index fa3023cb9..f8c395d0f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include "common/common_types.h" #include "core/arm/arm_interface.h" #include "core/arm/skyeye_common/armstate.h" @@ -15,9 +15,12 @@ namespace Memory { struct PageTable; } // namespace Memory +class DynarmicUserCallbacks; + class ARM_Dynarmic final : public ARM_Interface { public: explicit ARM_Dynarmic(PrivilegeMode initial_mode); + ~ARM_Dynarmic(); void Run() override; void Step() override; @@ -46,8 +49,12 @@ public: void PageTableChanged() override; private: - Dynarmic::Jit* jit = nullptr; + friend class DynarmicUserCallbacks; + std::unique_ptr cb; + std::unique_ptr MakeJit(); + + Dynarmic::A32::Jit* jit = nullptr; Memory::PageTable* current_page_table = nullptr; - std::map> jits; + std::map> jits; std::shared_ptr interpreter_state; }; diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp index b1fdce096..119aefac7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp @@ -6,9 +6,9 @@ #include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/armstate.h" -using Callback = Dynarmic::Coprocessor::Callback; -using CallbackOrAccessOneWord = Dynarmic::Coprocessor::CallbackOrAccessOneWord; -using CallbackOrAccessTwoWords = Dynarmic::Coprocessor::CallbackOrAccessTwoWords; +using Callback = Dynarmic::A32::Coprocessor::Callback; +using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; +using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; DynarmicCP15::DynarmicCP15(const std::shared_ptr& state) : interpreter_state(state) {} diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index 1d270870c..66740ea71 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h @@ -5,13 +5,15 @@ #pragma once #include -#include +#include #include "common/common_types.h" struct ARMul_State; -class DynarmicCP15 final : public Dynarmic::Coprocessor { +class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { public: + using CoprocReg = Dynarmic::A32::CoprocReg; + explicit DynarmicCP15(const std::shared_ptr&); ~DynarmicCP15() override;