diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.h | 12 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 170 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.h | 16 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.cpp | 20 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.h | 5 | ||||
| -rw-r--r-- | src/core/core.cpp | 4 | 
7 files changed, 165 insertions, 64 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 025177b89..e8e98a095 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -171,7 +171,7 @@ set(HEADERS  create_directory_groups(${SRCS} ${HEADERS})  add_library(core STATIC ${SRCS} ${HEADERS}) -target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core) +target_link_libraries(core PUBLIC common PRIVATE audio_core dynarmic network video_core)  target_link_libraries(core PUBLIC Boost::boost PRIVATE cryptopp fmt lz4_static unicorn)  if (ENABLE_WEB_SERVICE)      target_link_libraries(core PUBLIC json-headers web_service) diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index c0d6e2604..531875006 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -4,6 +4,7 @@  #pragma once +#include <array>  #include "common/common_types.h"  #include "core/hle/kernel/vm_manager.h" @@ -13,15 +14,12 @@ public:      virtual ~ARM_Interface() {}      struct ThreadContext { -        u64 cpu_registers[30]; -        u64 lr; +        std::array<u64, 31> cpu_registers;          u64 sp;          u64 pc;          u64 cpsr; -        u128 fpu_registers[32]; +        std::array<u128, 32> fpu_registers;          u64 fpscr; -        u64 fpexc; -          // TODO(bunnei): Fix once we have proper support for tpidrro_el0, etc. in the JIT          VAddr tls_address; @@ -75,9 +73,9 @@ public:       */      virtual void SetReg(int index, u64 value) = 0; -    virtual const u128& GetExtReg(int index) const = 0; +    virtual u128 GetExtReg(int index) const = 0; -    virtual void SetExtReg(int index, u128& value) = 0; +    virtual void SetExtReg(int index, u128 value) = 0;      /**       * Gets the value of a VFP register diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 12b7fc926..c1a63e064 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -2,43 +2,114 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <memory> +#include <dynarmic/A64/a64.h> +#include <dynarmic/A64/config.h>  #include "core/arm/dynarmic/arm_dynarmic.h" - -ARM_Dynarmic::ARM_Dynarmic() { -    UNIMPLEMENTED(); -} - -void ARM_Dynarmic::MapBackingMemory(VAddr /*address*/, size_t /*size*/, u8* /*memory*/, -                                    Kernel::VMAPermission /*perms*/) { -    UNIMPLEMENTED(); -} - -void ARM_Dynarmic::SetPC(u64 /*pc*/) { -    UNIMPLEMENTED(); +#include "core/core_timing.h" +#include "core/hle/kernel/svc.h" +#include "core/memory.h" + +class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks { +public: +    explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {} +    ~ARM_Dynarmic_Callbacks() = default; + +    virtual u8 MemoryRead8(u64 vaddr) override { +        return Memory::Read8(vaddr); +    } +    virtual u16 MemoryRead16(u64 vaddr) override { +        return Memory::Read16(vaddr); +    } +    virtual u32 MemoryRead32(u64 vaddr) override { +        return Memory::Read32(vaddr); +    } +    virtual u64 MemoryRead64(u64 vaddr) override { +        return Memory::Read64(vaddr); +    } + +    virtual void MemoryWrite8(u64 vaddr, u8 value) override { +        Memory::Write8(vaddr, value); +    } +    virtual void MemoryWrite16(u64 vaddr, u16 value) override { +        Memory::Write16(vaddr, value); +    } +    virtual void MemoryWrite32(u64 vaddr, u32 value) override { +        Memory::Write32(vaddr, value); +    } +    virtual void MemoryWrite64(u64 vaddr, u64 value) override { +        Memory::Write64(vaddr, value); +    } + +    virtual void InterpreterFallback(u64 pc, size_t num_instructions) override { +        ARM_Interface::ThreadContext ctx; +        parent.SaveContext(ctx); +        parent.inner_unicorn.LoadContext(ctx); +        parent.inner_unicorn.ExecuteInstructions(num_instructions); +        parent.inner_unicorn.SaveContext(ctx); +        parent.LoadContext(ctx); +        num_interpreted_instructions += num_instructions; +    } + +    virtual void CallSVC(u32 swi) override { +        printf("svc %x\n", swi); +        Kernel::CallSVC(swi); +    } + +    virtual void AddTicks(u64 ticks) override { +        if (ticks > ticks_remaining) { +            ticks_remaining = 0; +            return; +        } +        ticks -= ticks_remaining; +    } +    virtual u64 GetTicksRemaining() override { +        return ticks_remaining; +    } + +    ARM_Dynarmic& parent; +    size_t ticks_remaining = 0; +    size_t num_interpreted_instructions = 0; +    u64 tpidrr0_el0 = 0; +}; + +ARM_Dynarmic::ARM_Dynarmic() +    : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), +      jit(Dynarmic::A64::UserConfig{cb.get()}) { +    ARM_Interface::ThreadContext ctx; +    inner_unicorn.SaveContext(ctx); +    LoadContext(ctx); +} + +ARM_Dynarmic::~ARM_Dynarmic() = default; + +void ARM_Dynarmic::MapBackingMemory(u64 address, size_t size, u8* memory, +                                    Kernel::VMAPermission perms) { +    inner_unicorn.MapBackingMemory(address, size, memory, perms); +} + +void ARM_Dynarmic::SetPC(u64 pc) { +    jit.SetPC(pc);  }  u64 ARM_Dynarmic::GetPC() const { -    UNIMPLEMENTED(); -    return {}; +    return jit.GetPC();  } -u64 ARM_Dynarmic::GetReg(int /*index*/) const { -    UNIMPLEMENTED(); -    return {}; +u64 ARM_Dynarmic::GetReg(int index) const { +    return jit.GetRegister(index);  } -void ARM_Dynarmic::SetReg(int /*index*/, u64 /*value*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::SetReg(int index, u64 value) { +    jit.SetRegister(index, value);  } -const u128& ARM_Dynarmic::GetExtReg(int /*index*/) const { -    UNIMPLEMENTED(); -    static constexpr u128 res{}; -    return res; +u128 ARM_Dynarmic::GetExtReg(int index) const { +    return jit.GetVector(index);  } -void ARM_Dynarmic::SetExtReg(int /*index*/, u128& /*value*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::SetExtReg(int index, u128 value) { +    jit.SetVector(index, value);  }  u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const { @@ -51,41 +122,56 @@ void ARM_Dynarmic::SetVFPReg(int /*index*/, u32 /*value*/) {  }  u32 ARM_Dynarmic::GetCPSR() const { -    UNIMPLEMENTED(); -    return {}; +    return jit.GetPstate();  } -void ARM_Dynarmic::SetCPSR(u32 /*cpsr*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::SetCPSR(u32 cpsr) { +    jit.SetPstate(cpsr);  } -VAddr ARM_Dynarmic::GetTlsAddress() const { -    UNIMPLEMENTED(); -    return {}; +u64 ARM_Dynarmic::GetTlsAddress() const { +    return cb->tpidrr0_el0;  } -void ARM_Dynarmic::SetTlsAddress(VAddr /*address*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::SetTlsAddress(u64 address) { +    cb->tpidrr0_el0 = address;  } -void ARM_Dynarmic::ExecuteInstructions(int /*num_instructions*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::ExecuteInstructions(int num_instructions) { +    cb->ticks_remaining = num_instructions; +    jit.Run(); +    CoreTiming::AddTicks(num_instructions - cb->num_interpreted_instructions); +    cb->num_interpreted_instructions = 0;  } -void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& /*ctx*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { +    ctx.cpu_registers = jit.GetRegisters(); +    ctx.sp = jit.GetSP(); +    ctx.pc = jit.GetPC(); +    ctx.cpsr = jit.GetPstate(); +    ctx.fpu_registers = jit.GetVectors(); +    ctx.fpscr = jit.GetFpcr(); +    ctx.tls_address = cb->tpidrr0_el0;  } -void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& /*ctx*/) { -    UNIMPLEMENTED(); +void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) { +    jit.SetRegisters(ctx.cpu_registers); +    jit.SetSP(ctx.sp); +    jit.SetPC(ctx.pc); +    jit.SetPstate(ctx.cpsr); +    jit.SetVectors(ctx.fpu_registers); +    jit.SetFpcr(ctx.fpscr); +    cb->tpidrr0_el0 = ctx.tls_address;  }  void ARM_Dynarmic::PrepareReschedule() { -    UNIMPLEMENTED(); +    if (jit.IsExecuting()) { +        jit.HaltExecution(); +    }  }  void ARM_Dynarmic::ClearInstructionCache() { -    UNIMPLEMENTED(); +    jit.ClearCache();  }  void ARM_Dynarmic::PageTableChanged() { diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index c62d02ec9..947fab3f4 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -4,12 +4,18 @@  #pragma once +#include <memory> +#include <dynarmic/A64/a64.h>  #include "common/common_types.h"  #include "core/arm/arm_interface.h" +#include "core/arm/unicorn/arm_unicorn.h" + +class ARM_Dynarmic_Callbacks;  class ARM_Dynarmic final : public ARM_Interface {  public:      ARM_Dynarmic(); +    ~ARM_Dynarmic();      void MapBackingMemory(VAddr address, size_t size, u8* memory,                            Kernel::VMAPermission perms) override; @@ -18,8 +24,8 @@ public:      u64 GetPC() const override;      u64 GetReg(int index) const override;      void SetReg(int index, u64 value) override; -    const u128& GetExtReg(int index) const override; -    void SetExtReg(int index, u128& value) override; +    u128 GetExtReg(int index) const override; +    void SetExtReg(int index, u128 value) override;      u32 GetVFPReg(int index) const override;      void SetVFPReg(int index, u32 value) override;      u32 GetCPSR() const override; @@ -35,4 +41,10 @@ public:      void ClearInstructionCache() override;      void PageTableChanged() override; + +private: +    friend class ARM_Dynarmic_Callbacks; +    std::unique_ptr<ARM_Dynarmic_Callbacks> cb; +    Dynarmic::A64::Jit jit; +    ARM_Unicorn inner_unicorn;  }; diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 1d15152e5..dc886a4f7 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp @@ -108,13 +108,13 @@ void ARM_Unicorn::SetReg(int regn, u64 val) {      CHECKED(uc_reg_write(uc, treg, &val));  } -const u128& ARM_Unicorn::GetExtReg(int /*index*/) const { +u128 ARM_Unicorn::GetExtReg(int /*index*/) const {      UNIMPLEMENTED();      static constexpr u128 res{};      return res;  } -void ARM_Unicorn::SetExtReg(int /*index*/, u128& /*value*/) { +void ARM_Unicorn::SetExtReg(int /*index*/, u128 /*value*/) {      UNIMPLEMENTED();  } @@ -168,10 +168,12 @@ void ARM_Unicorn::SaveContext(ARM_Interface::ThreadContext& ctx) {          uregs[i] = UC_ARM64_REG_X0 + i;          tregs[i] = &ctx.cpu_registers[i];      } +    uregs[29] = UC_ARM64_REG_X29; +    tregs[29] = (void*)&ctx.cpu_registers[29]; +    uregs[30] = UC_ARM64_REG_X30; +    tregs[30] = (void*)&ctx.cpu_registers[30]; -    CHECKED(uc_reg_read_batch(uc, uregs, tregs, 29)); -    CHECKED(uc_reg_read(uc, UC_ARM64_REG_X29, &ctx.cpu_registers[29])); -    CHECKED(uc_reg_read(uc, UC_ARM64_REG_X30, &ctx.lr)); +    CHECKED(uc_reg_read_batch(uc, uregs, tregs, 31));      ctx.tls_address = GetTlsAddress(); @@ -195,10 +197,12 @@ void ARM_Unicorn::LoadContext(const ARM_Interface::ThreadContext& ctx) {          uregs[i] = UC_ARM64_REG_X0 + i;          tregs[i] = (void*)&ctx.cpu_registers[i];      } +    uregs[29] = UC_ARM64_REG_X29; +    tregs[29] = (void*)&ctx.cpu_registers[29]; +    uregs[30] = UC_ARM64_REG_X30; +    tregs[30] = (void*)&ctx.cpu_registers[30]; -    CHECKED(uc_reg_write_batch(uc, uregs, tregs, 29)); -    CHECKED(uc_reg_write(uc, UC_ARM64_REG_X29, &ctx.cpu_registers[29])); -    CHECKED(uc_reg_write(uc, UC_ARM64_REG_X30, &ctx.lr)); +    CHECKED(uc_reg_write_batch(uc, uregs, tregs, 31));      SetTlsAddress(ctx.tls_address); diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index 90db3eb7f..81cce0721 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h @@ -9,7 +9,6 @@  #include "core/arm/arm_interface.h"  class ARM_Unicorn final : public ARM_Interface { -  public:      ARM_Unicorn();      ~ARM_Unicorn(); @@ -19,8 +18,8 @@ public:      u64 GetPC() const override;      u64 GetReg(int index) const override;      void SetReg(int index, u64 value) override; -    const u128& GetExtReg(int index) const override; -    void SetExtReg(int index, u128& value) override; +    u128 GetExtReg(int index) const override; +    void SetExtReg(int index, u128 value) override;      u32 GetVFPReg(int index) const override;      void SetVFPReg(int index, u32 value) override;      u32 GetCPSR() const override; diff --git a/src/core/core.cpp b/src/core/core.cpp index 40ef58f59..0240f946b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -6,6 +6,7 @@  #include <utility>  #include "audio_core/audio_core.h"  #include "common/logging/log.h" +#include "core/arm/dynarmic/arm_dynarmic.h"  #include "core/arm/unicorn/arm_unicorn.h"  #include "core/core.h"  #include "core/core_timing.h" @@ -139,7 +140,8 @@ void System::Reschedule() {  System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {      LOG_DEBUG(HW_Memory, "initialized OK"); -    cpu_core = std::make_unique<ARM_Unicorn>(); +    // TODO: Configuration option +    cpu_core = std::make_unique<ARM_Dynarmic>();      telemetry_session = std::make_unique<Core::TelemetrySession>();      CoreTiming::Init();  | 
