summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar MerryMage2018-01-09 21:33:46 +0000
committerGravatar bunnei2018-01-12 17:48:29 -0500
commitd2fbc7832080955598c9fb6f083414eca47f0f19 (patch)
tree4f4b63aa2d37b86c39fdd17b12731bceda8bc90c /src
parentcore: Include <algorithm> where used. (diff)
downloadyuzu-d2fbc7832080955598c9fb6f083414eca47f0f19.tar.gz
yuzu-d2fbc7832080955598c9fb6f083414eca47f0f19.tar.xz
yuzu-d2fbc7832080955598c9fb6f083414eca47f0f19.zip
arm_dynarmic: Implement core
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/wait_tree.cpp2
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/arm_interface.h12
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp170
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h16
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp20
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h5
-rw-r--r--src/core/core.cpp4
8 files changed, 166 insertions, 65 deletions
diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp
index c066a3e17..eefbcb9f1 100644
--- a/src/citra_qt/debugger/wait_tree.cpp
+++ b/src/citra_qt/debugger/wait_tree.cpp
@@ -168,7 +168,7 @@ QString WaitTreeThread::GetText() const {
168 } 168 }
169 QString pc_info = tr(" PC = 0x%1 LR = 0x%2") 169 QString pc_info = tr(" PC = 0x%1 LR = 0x%2")
170 .arg(thread.context.pc, 8, 16, QLatin1Char('0')) 170 .arg(thread.context.pc, 8, 16, QLatin1Char('0'))
171 .arg(thread.context.lr, 8, 16, QLatin1Char('0')); 171 .arg(thread.context.cpu_registers[31], 8, 16, QLatin1Char('0'));
172 return WaitTreeWaitObject::GetText() + pc_info + " (" + status + ") "; 172 return WaitTreeWaitObject::GetText() + pc_info + " (" + status + ") ";
173} 173}
174 174
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
171 171
172create_directory_groups(${SRCS} ${HEADERS}) 172create_directory_groups(${SRCS} ${HEADERS})
173add_library(core STATIC ${SRCS} ${HEADERS}) 173add_library(core STATIC ${SRCS} ${HEADERS})
174target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core) 174target_link_libraries(core PUBLIC common PRIVATE audio_core dynarmic network video_core)
175target_link_libraries(core PUBLIC Boost::boost PRIVATE cryptopp fmt lz4_static unicorn) 175target_link_libraries(core PUBLIC Boost::boost PRIVATE cryptopp fmt lz4_static unicorn)
176if (ENABLE_WEB_SERVICE) 176if (ENABLE_WEB_SERVICE)
177 target_link_libraries(core PUBLIC json-headers web_service) 177 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include "common/common_types.h" 8#include "common/common_types.h"
8#include "core/hle/kernel/vm_manager.h" 9#include "core/hle/kernel/vm_manager.h"
9 10
@@ -13,15 +14,12 @@ public:
13 virtual ~ARM_Interface() {} 14 virtual ~ARM_Interface() {}
14 15
15 struct ThreadContext { 16 struct ThreadContext {
16 u64 cpu_registers[30]; 17 std::array<u64, 31> cpu_registers;
17 u64 lr;
18 u64 sp; 18 u64 sp;
19 u64 pc; 19 u64 pc;
20 u64 cpsr; 20 u64 cpsr;
21 u128 fpu_registers[32]; 21 std::array<u128, 32> fpu_registers;
22 u64 fpscr; 22 u64 fpscr;
23 u64 fpexc;
24
25 23
26 // TODO(bunnei): Fix once we have proper support for tpidrro_el0, etc. in the JIT 24 // TODO(bunnei): Fix once we have proper support for tpidrro_el0, etc. in the JIT
27 VAddr tls_address; 25 VAddr tls_address;
@@ -75,9 +73,9 @@ public:
75 */ 73 */
76 virtual void SetReg(int index, u64 value) = 0; 74 virtual void SetReg(int index, u64 value) = 0;
77 75
78 virtual const u128& GetExtReg(int index) const = 0; 76 virtual u128 GetExtReg(int index) const = 0;
79 77
80 virtual void SetExtReg(int index, u128& value) = 0; 78 virtual void SetExtReg(int index, u128 value) = 0;
81 79
82 /** 80 /**
83 * Gets the value of a VFP register 81 * 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 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory>
6#include <dynarmic/A64/a64.h>
7#include <dynarmic/A64/config.h>
5#include "core/arm/dynarmic/arm_dynarmic.h" 8#include "core/arm/dynarmic/arm_dynarmic.h"
6 9#include "core/core_timing.h"
7ARM_Dynarmic::ARM_Dynarmic() { 10#include "core/hle/kernel/svc.h"
8 UNIMPLEMENTED(); 11#include "core/memory.h"
9} 12
10 13class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks {
11void ARM_Dynarmic::MapBackingMemory(VAddr /*address*/, size_t /*size*/, u8* /*memory*/, 14public:
12 Kernel::VMAPermission /*perms*/) { 15 explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
13 UNIMPLEMENTED(); 16 ~ARM_Dynarmic_Callbacks() = default;
14} 17
15 18 virtual u8 MemoryRead8(u64 vaddr) override {
16void ARM_Dynarmic::SetPC(u64 /*pc*/) { 19 return Memory::Read8(vaddr);
17 UNIMPLEMENTED(); 20 }
21 virtual u16 MemoryRead16(u64 vaddr) override {
22 return Memory::Read16(vaddr);
23 }
24 virtual u32 MemoryRead32(u64 vaddr) override {
25 return Memory::Read32(vaddr);
26 }
27 virtual u64 MemoryRead64(u64 vaddr) override {
28 return Memory::Read64(vaddr);
29 }
30
31 virtual void MemoryWrite8(u64 vaddr, u8 value) override {
32 Memory::Write8(vaddr, value);
33 }
34 virtual void MemoryWrite16(u64 vaddr, u16 value) override {
35 Memory::Write16(vaddr, value);
36 }
37 virtual void MemoryWrite32(u64 vaddr, u32 value) override {
38 Memory::Write32(vaddr, value);
39 }
40 virtual void MemoryWrite64(u64 vaddr, u64 value) override {
41 Memory::Write64(vaddr, value);
42 }
43
44 virtual void InterpreterFallback(u64 pc, size_t num_instructions) override {
45 ARM_Interface::ThreadContext ctx;
46 parent.SaveContext(ctx);
47 parent.inner_unicorn.LoadContext(ctx);
48 parent.inner_unicorn.ExecuteInstructions(num_instructions);
49 parent.inner_unicorn.SaveContext(ctx);
50 parent.LoadContext(ctx);
51 num_interpreted_instructions += num_instructions;
52 }
53
54 virtual void CallSVC(u32 swi) override {
55 printf("svc %x\n", swi);
56 Kernel::CallSVC(swi);
57 }
58
59 virtual void AddTicks(u64 ticks) override {
60 if (ticks > ticks_remaining) {
61 ticks_remaining = 0;
62 return;
63 }
64 ticks -= ticks_remaining;
65 }
66 virtual u64 GetTicksRemaining() override {
67 return ticks_remaining;
68 }
69
70 ARM_Dynarmic& parent;
71 size_t ticks_remaining = 0;
72 size_t num_interpreted_instructions = 0;
73 u64 tpidrr0_el0 = 0;
74};
75
76ARM_Dynarmic::ARM_Dynarmic()
77 : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
78 jit(Dynarmic::A64::UserConfig{cb.get()}) {
79 ARM_Interface::ThreadContext ctx;
80 inner_unicorn.SaveContext(ctx);
81 LoadContext(ctx);
82}
83
84ARM_Dynarmic::~ARM_Dynarmic() = default;
85
86void ARM_Dynarmic::MapBackingMemory(u64 address, size_t size, u8* memory,
87 Kernel::VMAPermission perms) {
88 inner_unicorn.MapBackingMemory(address, size, memory, perms);
89}
90
91void ARM_Dynarmic::SetPC(u64 pc) {
92 jit.SetPC(pc);
18} 93}
19 94
20u64 ARM_Dynarmic::GetPC() const { 95u64 ARM_Dynarmic::GetPC() const {
21 UNIMPLEMENTED(); 96 return jit.GetPC();
22 return {};
23} 97}
24 98
25u64 ARM_Dynarmic::GetReg(int /*index*/) const { 99u64 ARM_Dynarmic::GetReg(int index) const {
26 UNIMPLEMENTED(); 100 return jit.GetRegister(index);
27 return {};
28} 101}
29 102
30void ARM_Dynarmic::SetReg(int /*index*/, u64 /*value*/) { 103void ARM_Dynarmic::SetReg(int index, u64 value) {
31 UNIMPLEMENTED(); 104 jit.SetRegister(index, value);
32} 105}
33 106
34const u128& ARM_Dynarmic::GetExtReg(int /*index*/) const { 107u128 ARM_Dynarmic::GetExtReg(int index) const {
35 UNIMPLEMENTED(); 108 return jit.GetVector(index);
36 static constexpr u128 res{};
37 return res;
38} 109}
39 110
40void ARM_Dynarmic::SetExtReg(int /*index*/, u128& /*value*/) { 111void ARM_Dynarmic::SetExtReg(int index, u128 value) {
41 UNIMPLEMENTED(); 112 jit.SetVector(index, value);
42} 113}
43 114
44u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const { 115u32 ARM_Dynarmic::GetVFPReg(int /*index*/) const {
@@ -51,41 +122,56 @@ void ARM_Dynarmic::SetVFPReg(int /*index*/, u32 /*value*/) {
51} 122}
52 123
53u32 ARM_Dynarmic::GetCPSR() const { 124u32 ARM_Dynarmic::GetCPSR() const {
54 UNIMPLEMENTED(); 125 return jit.GetPstate();
55 return {};
56} 126}
57 127
58void ARM_Dynarmic::SetCPSR(u32 /*cpsr*/) { 128void ARM_Dynarmic::SetCPSR(u32 cpsr) {
59 UNIMPLEMENTED(); 129 jit.SetPstate(cpsr);
60} 130}
61 131
62VAddr ARM_Dynarmic::GetTlsAddress() const { 132u64 ARM_Dynarmic::GetTlsAddress() const {
63 UNIMPLEMENTED(); 133 return cb->tpidrr0_el0;
64 return {};
65} 134}
66 135
67void ARM_Dynarmic::SetTlsAddress(VAddr /*address*/) { 136void ARM_Dynarmic::SetTlsAddress(u64 address) {
68 UNIMPLEMENTED(); 137 cb->tpidrr0_el0 = address;
69} 138}
70 139
71void ARM_Dynarmic::ExecuteInstructions(int /*num_instructions*/) { 140void ARM_Dynarmic::ExecuteInstructions(int num_instructions) {
72 UNIMPLEMENTED(); 141 cb->ticks_remaining = num_instructions;
142 jit.Run();
143 CoreTiming::AddTicks(num_instructions - cb->num_interpreted_instructions);
144 cb->num_interpreted_instructions = 0;
73} 145}
74 146
75void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& /*ctx*/) { 147void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
76 UNIMPLEMENTED(); 148 ctx.cpu_registers = jit.GetRegisters();
149 ctx.sp = jit.GetSP();
150 ctx.pc = jit.GetPC();
151 ctx.cpsr = jit.GetPstate();
152 ctx.fpu_registers = jit.GetVectors();
153 ctx.fpscr = jit.GetFpcr();
154 ctx.tls_address = cb->tpidrr0_el0;
77} 155}
78 156
79void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& /*ctx*/) { 157void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) {
80 UNIMPLEMENTED(); 158 jit.SetRegisters(ctx.cpu_registers);
159 jit.SetSP(ctx.sp);
160 jit.SetPC(ctx.pc);
161 jit.SetPstate(ctx.cpsr);
162 jit.SetVectors(ctx.fpu_registers);
163 jit.SetFpcr(ctx.fpscr);
164 cb->tpidrr0_el0 = ctx.tls_address;
81} 165}
82 166
83void ARM_Dynarmic::PrepareReschedule() { 167void ARM_Dynarmic::PrepareReschedule() {
84 UNIMPLEMENTED(); 168 if (jit.IsExecuting()) {
169 jit.HaltExecution();
170 }
85} 171}
86 172
87void ARM_Dynarmic::ClearInstructionCache() { 173void ARM_Dynarmic::ClearInstructionCache() {
88 UNIMPLEMENTED(); 174 jit.ClearCache();
89} 175}
90 176
91void ARM_Dynarmic::PageTableChanged() { 177void 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
8#include <dynarmic/A64/a64.h>
7#include "common/common_types.h" 9#include "common/common_types.h"
8#include "core/arm/arm_interface.h" 10#include "core/arm/arm_interface.h"
11#include "core/arm/unicorn/arm_unicorn.h"
12
13class ARM_Dynarmic_Callbacks;
9 14
10class ARM_Dynarmic final : public ARM_Interface { 15class ARM_Dynarmic final : public ARM_Interface {
11public: 16public:
12 ARM_Dynarmic(); 17 ARM_Dynarmic();
18 ~ARM_Dynarmic();
13 19
14 void MapBackingMemory(VAddr address, size_t size, u8* memory, 20 void MapBackingMemory(VAddr address, size_t size, u8* memory,
15 Kernel::VMAPermission perms) override; 21 Kernel::VMAPermission perms) override;
@@ -18,8 +24,8 @@ public:
18 u64 GetPC() const override; 24 u64 GetPC() const override;
19 u64 GetReg(int index) const override; 25 u64 GetReg(int index) const override;
20 void SetReg(int index, u64 value) override; 26 void SetReg(int index, u64 value) override;
21 const u128& GetExtReg(int index) const override; 27 u128 GetExtReg(int index) const override;
22 void SetExtReg(int index, u128& value) override; 28 void SetExtReg(int index, u128 value) override;
23 u32 GetVFPReg(int index) const override; 29 u32 GetVFPReg(int index) const override;
24 void SetVFPReg(int index, u32 value) override; 30 void SetVFPReg(int index, u32 value) override;
25 u32 GetCPSR() const override; 31 u32 GetCPSR() const override;
@@ -35,4 +41,10 @@ public:
35 41
36 void ClearInstructionCache() override; 42 void ClearInstructionCache() override;
37 void PageTableChanged() override; 43 void PageTableChanged() override;
44
45private:
46 friend class ARM_Dynarmic_Callbacks;
47 std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
48 Dynarmic::A64::Jit jit;
49 ARM_Unicorn inner_unicorn;
38}; 50};
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) {
108 CHECKED(uc_reg_write(uc, treg, &val)); 108 CHECKED(uc_reg_write(uc, treg, &val));
109} 109}
110 110
111const u128& ARM_Unicorn::GetExtReg(int /*index*/) const { 111u128 ARM_Unicorn::GetExtReg(int /*index*/) const {
112 UNIMPLEMENTED(); 112 UNIMPLEMENTED();
113 static constexpr u128 res{}; 113 static constexpr u128 res{};
114 return res; 114 return res;
115} 115}
116 116
117void ARM_Unicorn::SetExtReg(int /*index*/, u128& /*value*/) { 117void ARM_Unicorn::SetExtReg(int /*index*/, u128 /*value*/) {
118 UNIMPLEMENTED(); 118 UNIMPLEMENTED();
119} 119}
120 120
@@ -168,10 +168,12 @@ void ARM_Unicorn::SaveContext(ARM_Interface::ThreadContext& ctx) {
168 uregs[i] = UC_ARM64_REG_X0 + i; 168 uregs[i] = UC_ARM64_REG_X0 + i;
169 tregs[i] = &ctx.cpu_registers[i]; 169 tregs[i] = &ctx.cpu_registers[i];
170 } 170 }
171 uregs[29] = UC_ARM64_REG_X29;
172 tregs[29] = (void*)&ctx.cpu_registers[29];
173 uregs[30] = UC_ARM64_REG_X30;
174 tregs[30] = (void*)&ctx.cpu_registers[30];
171 175
172 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 29)); 176 CHECKED(uc_reg_read_batch(uc, uregs, tregs, 31));
173 CHECKED(uc_reg_read(uc, UC_ARM64_REG_X29, &ctx.cpu_registers[29]));
174 CHECKED(uc_reg_read(uc, UC_ARM64_REG_X30, &ctx.lr));
175 177
176 ctx.tls_address = GetTlsAddress(); 178 ctx.tls_address = GetTlsAddress();
177 179
@@ -195,10 +197,12 @@ void ARM_Unicorn::LoadContext(const ARM_Interface::ThreadContext& ctx) {
195 uregs[i] = UC_ARM64_REG_X0 + i; 197 uregs[i] = UC_ARM64_REG_X0 + i;
196 tregs[i] = (void*)&ctx.cpu_registers[i]; 198 tregs[i] = (void*)&ctx.cpu_registers[i];
197 } 199 }
200 uregs[29] = UC_ARM64_REG_X29;
201 tregs[29] = (void*)&ctx.cpu_registers[29];
202 uregs[30] = UC_ARM64_REG_X30;
203 tregs[30] = (void*)&ctx.cpu_registers[30];
198 204
199 CHECKED(uc_reg_write_batch(uc, uregs, tregs, 29)); 205 CHECKED(uc_reg_write_batch(uc, uregs, tregs, 31));
200 CHECKED(uc_reg_write(uc, UC_ARM64_REG_X29, &ctx.cpu_registers[29]));
201 CHECKED(uc_reg_write(uc, UC_ARM64_REG_X30, &ctx.lr));
202 206
203 SetTlsAddress(ctx.tls_address); 207 SetTlsAddress(ctx.tls_address);
204 208
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 @@
9#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
10 10
11class ARM_Unicorn final : public ARM_Interface { 11class ARM_Unicorn final : public ARM_Interface {
12
13public: 12public:
14 ARM_Unicorn(); 13 ARM_Unicorn();
15 ~ARM_Unicorn(); 14 ~ARM_Unicorn();
@@ -19,8 +18,8 @@ public:
19 u64 GetPC() const override; 18 u64 GetPC() const override;
20 u64 GetReg(int index) const override; 19 u64 GetReg(int index) const override;
21 void SetReg(int index, u64 value) override; 20 void SetReg(int index, u64 value) override;
22 const u128& GetExtReg(int index) const override; 21 u128 GetExtReg(int index) const override;
23 void SetExtReg(int index, u128& value) override; 22 void SetExtReg(int index, u128 value) override;
24 u32 GetVFPReg(int index) const override; 23 u32 GetVFPReg(int index) const override;
25 void SetVFPReg(int index, u32 value) override; 24 void SetVFPReg(int index, u32 value) override;
26 u32 GetCPSR() const override; 25 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 @@
6#include <utility> 6#include <utility>
7#include "audio_core/audio_core.h" 7#include "audio_core/audio_core.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/arm/dynarmic/arm_dynarmic.h"
9#include "core/arm/unicorn/arm_unicorn.h" 10#include "core/arm/unicorn/arm_unicorn.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/core_timing.h" 12#include "core/core_timing.h"
@@ -139,7 +140,8 @@ void System::Reschedule() {
139System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { 140System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
140 LOG_DEBUG(HW_Memory, "initialized OK"); 141 LOG_DEBUG(HW_Memory, "initialized OK");
141 142
142 cpu_core = std::make_unique<ARM_Unicorn>(); 143 // TODO: Configuration option
144 cpu_core = std::make_unique<ARM_Dynarmic>();
143 telemetry_session = std::make_unique<Core::TelemetrySession>(); 145 telemetry_session = std::make_unique<Core::TelemetrySession>();
144 146
145 CoreTiming::Init(); 147 CoreTiming::Init();