citra-emu
/
citra-canary
Archived
1
0
Fork 0

Merge pull request #4086 from MerryMage/dynarmic-update-201808

externals: Update dynarmic
This commit is contained in:
Merry 2018-09-02 09:55:32 +01:00 committed by GitHub
commit 978611e51e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 67 deletions

2
externals/dynarmic vendored

@ -1 +1 @@
Subproject commit 4b350a354a21339052c7fff88832c3f81f5624be Subproject commit 68ca03e8d4822c78e15315e67ddbb1d6bf4d3827

View File

@ -3,8 +3,8 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cstring> #include <cstring>
#include <dynarmic/context.h> #include <dynarmic/A32/a32.h>
#include <dynarmic/dynarmic.h> #include <dynarmic/A32/context.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/microprofile.h" #include "common/microprofile.h"
#include "core/arm/dynarmic/arm_dynarmic.h" #include "core/arm/dynarmic/arm_dynarmic.h"
@ -64,86 +64,101 @@ public:
private: private:
friend class ARM_Dynarmic; friend class ARM_Dynarmic;
Dynarmic::Context ctx; Dynarmic::A32::Context ctx;
u32 fpexc; u32 fpexc;
}; };
static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void* user_arg) { class DynarmicUserCallbacks final : public Dynarmic::A32::UserCallbacks {
ARMul_State* state = static_cast<ARMul_State*>(user_arg); public:
explicit DynarmicUserCallbacks(ARM_Dynarmic& parent) : parent(parent) {}
~DynarmicUserCallbacks() = default;
state->Reg = jit->Regs(); std::uint8_t MemoryRead8(VAddr vaddr) override {
state->Cpsr = jit->Cpsr(); return Memory::Read8(vaddr);
state->Reg[15] = pc; }
state->ExtReg = jit->ExtRegs(); std::uint16_t MemoryRead16(VAddr vaddr) override {
state->VFP[VFP_FPSCR] = jit->Fpscr(); return Memory::Read16(vaddr);
state->NumInstrsToExecute = 1; }
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; void InterpreterFallback(VAddr pc, size_t num_instructions) override {
state->Reg[15] &= (is_thumb ? 0xFFFFFFFE : 0xFFFFFFFC); 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; InterpreterMainLoop(parent.interpreter_state.get());
jit->SetCpsr(state->Cpsr);
jit->ExtRegs() = state->ExtReg;
jit->SetFpscr(state->VFP[VFP_FPSCR]);
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) { parent.jit->Regs() = parent.interpreter_state->Reg;
// TODO(bunnei): ImplementMe parent.jit->SetCpsr(parent.interpreter_state->Cpsr);
return false; parent.jit->ExtRegs() = parent.interpreter_state->ExtReg;
} parent.jit->SetFpscr(parent.interpreter_state->VFP[VFP_FPSCR]);
static void AddTicks(u64 ticks) { parent.interpreter_state->ServeBreak();
CoreTiming::AddTicks(ticks); }
}
static u64 GetTicksRemaining() { void CallSVC(std::uint32_t swi) override {
s64 ticks = CoreTiming::GetDowncount(); Kernel::CallSVC(swi);
return static_cast<u64>(ticks <= 0 ? 0 : ticks); }
}
static Dynarmic::UserCallbacks GetUserCallbacks( void ExceptionRaised(VAddr pc, Dynarmic::A32::Exception exception) override {
const std::shared_ptr<ARMul_State>& interpreter_state, Memory::PageTable* current_page_table) { ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
Dynarmic::UserCallbacks user_callbacks{}; static_cast<size_t>(exception), pc, MemoryReadCode(pc));
user_callbacks.InterpreterFallback = &InterpreterFallback; }
user_callbacks.user_arg = static_cast<void*>(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 = &current_page_table->pointers;
user_callbacks.coprocessors[15] = std::make_shared<DynarmicCP15>(interpreter_state);
return user_callbacks;
}
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<u64>(ticks <= 0 ? 0 : ticks);
}
ARM_Dynarmic& parent;
};
ARM_Dynarmic::ARM_Dynarmic(PrivilegeMode initial_mode)
: cb(std::make_unique<DynarmicUserCallbacks>(*this)) {
interpreter_state = std::make_shared<ARMul_State>(initial_mode); interpreter_state = std::make_shared<ARMul_State>(initial_mode);
PageTableChanged(); PageTableChanged();
} }
ARM_Dynarmic::~ARM_Dynarmic() = default;
MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64));
void ARM_Dynarmic::Run() { void ARM_Dynarmic::Run() {
ASSERT(Memory::GetCurrentPageTable() == current_page_table); ASSERT(Memory::GetCurrentPageTable() == current_page_table);
MICROPROFILE_SCOPE(ARM_Jit); MICROPROFILE_SCOPE(ARM_Jit);
jit->Run(GetTicksRemaining()); jit->Run();
} }
void ARM_Dynarmic::Step() { void ARM_Dynarmic::Step() {
InterpreterFallback(jit->Regs()[15], jit, static_cast<void*>(interpreter_state.get())); cb->InterpreterFallback(jit->Regs()[15], 1);
} }
void ARM_Dynarmic::SetPC(u32 pc) { void ARM_Dynarmic::SetPC(u32 pc) {
@ -251,6 +266,16 @@ void ARM_Dynarmic::PageTableChanged() {
return; return;
} }
jit = new Dynarmic::Jit(GetUserCallbacks(interpreter_state, current_page_table)); auto new_jit = MakeJit();
jits.emplace(current_page_table, std::unique_ptr<Dynarmic::Jit>(jit)); jit = new_jit.get();
jits.emplace(current_page_table, std::move(new_jit));
}
std::unique_ptr<Dynarmic::A32::Jit> ARM_Dynarmic::MakeJit() {
Dynarmic::A32::UserConfig config;
config.callbacks = cb.get();
config.page_table = &current_page_table->pointers;
config.coprocessors[15] = std::make_shared<DynarmicCP15>(interpreter_state);
config.define_unpredictable_behaviour = true;
return std::make_unique<Dynarmic::A32::Jit>(config);
} }

View File

@ -6,7 +6,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <dynarmic/dynarmic.h> #include <dynarmic/A32/a32.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armstate.h"
@ -15,9 +15,12 @@ namespace Memory {
struct PageTable; struct PageTable;
} // namespace Memory } // namespace Memory
class DynarmicUserCallbacks;
class ARM_Dynarmic final : public ARM_Interface { class ARM_Dynarmic final : public ARM_Interface {
public: public:
explicit ARM_Dynarmic(PrivilegeMode initial_mode); explicit ARM_Dynarmic(PrivilegeMode initial_mode);
~ARM_Dynarmic();
void Run() override; void Run() override;
void Step() override; void Step() override;
@ -46,8 +49,12 @@ public:
void PageTableChanged() override; void PageTableChanged() override;
private: private:
Dynarmic::Jit* jit = nullptr; friend class DynarmicUserCallbacks;
std::unique_ptr<DynarmicUserCallbacks> cb;
std::unique_ptr<Dynarmic::A32::Jit> MakeJit();
Dynarmic::A32::Jit* jit = nullptr;
Memory::PageTable* current_page_table = nullptr; Memory::PageTable* current_page_table = nullptr;
std::map<Memory::PageTable*, std::unique_ptr<Dynarmic::Jit>> jits; std::map<Memory::PageTable*, std::unique_ptr<Dynarmic::A32::Jit>> jits;
std::shared_ptr<ARMul_State> interpreter_state; std::shared_ptr<ARMul_State> interpreter_state;
}; };

View File

@ -6,9 +6,9 @@
#include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/arm_regformat.h"
#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/armstate.h"
using Callback = Dynarmic::Coprocessor::Callback; using Callback = Dynarmic::A32::Coprocessor::Callback;
using CallbackOrAccessOneWord = Dynarmic::Coprocessor::CallbackOrAccessOneWord; using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
using CallbackOrAccessTwoWords = Dynarmic::Coprocessor::CallbackOrAccessTwoWords; using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
DynarmicCP15::DynarmicCP15(const std::shared_ptr<ARMul_State>& state) : interpreter_state(state) {} DynarmicCP15::DynarmicCP15(const std::shared_ptr<ARMul_State>& state) : interpreter_state(state) {}

View File

@ -5,13 +5,15 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <dynarmic/coprocessor.h> #include <dynarmic/A32/coprocessor.h>
#include "common/common_types.h" #include "common/common_types.h"
struct ARMul_State; struct ARMul_State;
class DynarmicCP15 final : public Dynarmic::Coprocessor { class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {
public: public:
using CoprocReg = Dynarmic::A32::CoprocReg;
explicit DynarmicCP15(const std::shared_ptr<ARMul_State>&); explicit DynarmicCP15(const std::shared_ptr<ARMul_State>&);
~DynarmicCP15() override; ~DynarmicCP15() override;