summaryrefslogtreecommitdiff
path: root/src/core/arm
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2016-09-15 20:14:18 -0700
committerGravatar GitHub2016-09-15 20:14:18 -0700
commitf196924dddb68f4e47ab6da36552840f82616b90 (patch)
treebb57f41d9d26c4a75059f28165acaff88cfde652 /src/core/arm
parentMerge pull request #2064 from linkmauve/remove-readdir_r (diff)
parentarm_dynarmic: Implement GetVFPSystemReg/SetVFPSystemReg. (diff)
downloadyuzu-f196924dddb68f4e47ab6da36552840f82616b90.tar.gz
yuzu-f196924dddb68f4e47ab6da36552840f82616b90.tar.xz
yuzu-f196924dddb68f4e47ab6da36552840f82616b90.zip
Merge pull request #2042 from bunnei/dynarmic
Interface ARM CPU JIT (Dynarmic)
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.h9
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp174
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h50
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp17
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h3
5 files changed, 229 insertions, 24 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index de5e9c8fa..480c90e66 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -122,15 +122,6 @@ public:
122 virtual void AddTicks(u64 ticks) = 0; 122 virtual void AddTicks(u64 ticks) = 0;
123 123
124 /** 124 /**
125 * Initializes a CPU context for use on this CPU
126 * @param context Thread context to reset
127 * @param stack_top Pointer to the top of the stack
128 * @param entry_point Entry point for execution
129 * @param arg User argument for thread
130 */
131 virtual void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) = 0;
132
133 /**
134 * Saves the current CPU context 125 * Saves the current CPU context
135 * @param ctx Thread context to save 126 * @param ctx Thread context to save
136 */ 127 */
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
new file mode 100644
index 000000000..a521aec7c
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -0,0 +1,174 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "common/microprofile.h"
7
8#include <dynarmic/dynarmic.h>
9
10#include "core/arm/dynarmic/arm_dynarmic.h"
11#include "core/arm/dyncom/arm_dyncom_interpreter.h"
12#include "core/core.h"
13#include "core/core_timing.h"
14#include "core/hle/svc.h"
15#include "core/memory.h"
16
17static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void* user_arg) {
18 ARMul_State* state = static_cast<ARMul_State*>(user_arg);
19
20 state->Reg = jit->Regs();
21 state->Cpsr = jit->Cpsr();
22 state->Reg[15] = pc;
23 state->ExtReg = jit->ExtRegs();
24 state->VFP[VFP_FPSCR] = jit->Fpscr();
25 state->NumInstrsToExecute = 1;
26
27 InterpreterMainLoop(state);
28
29 bool is_thumb = (state->Cpsr & (1 << 5)) != 0;
30 state->Reg[15] &= (is_thumb ? 0xFFFFFFFE : 0xFFFFFFFC);
31
32 jit->Regs() = state->Reg;
33 jit->Cpsr() = state->Cpsr;
34 jit->ExtRegs() = state->ExtReg;
35 jit->SetFpscr(state->VFP[VFP_FPSCR]);
36}
37
38static bool IsReadOnlyMemory(u32 vaddr) {
39 // TODO(bunnei): ImplementMe
40 return false;
41}
42
43static Dynarmic::UserCallbacks GetUserCallbacks(ARMul_State* interpeter_state) {
44 Dynarmic::UserCallbacks user_callbacks{};
45 user_callbacks.InterpreterFallback = &InterpreterFallback;
46 user_callbacks.user_arg = static_cast<void*>(interpeter_state);
47 user_callbacks.CallSVC = &SVC::CallSVC;
48 user_callbacks.IsReadOnlyMemory = &IsReadOnlyMemory;
49 user_callbacks.MemoryRead8 = &Memory::Read8;
50 user_callbacks.MemoryRead16 = &Memory::Read16;
51 user_callbacks.MemoryRead32 = &Memory::Read32;
52 user_callbacks.MemoryRead64 = &Memory::Read64;
53 user_callbacks.MemoryWrite8 = &Memory::Write8;
54 user_callbacks.MemoryWrite16 = &Memory::Write16;
55 user_callbacks.MemoryWrite32 = &Memory::Write32;
56 user_callbacks.MemoryWrite64 = &Memory::Write64;
57 return user_callbacks;
58}
59
60ARM_Dynarmic::ARM_Dynarmic(PrivilegeMode initial_mode) {
61 interpreter_state = std::make_unique<ARMul_State>(initial_mode);
62 jit = std::make_unique<Dynarmic::Jit>(GetUserCallbacks(interpreter_state.get()));
63}
64
65void ARM_Dynarmic::SetPC(u32 pc) {
66 jit->Regs()[15] = pc;
67}
68
69u32 ARM_Dynarmic::GetPC() const {
70 return jit->Regs()[15];
71}
72
73u32 ARM_Dynarmic::GetReg(int index) const {
74 return jit->Regs()[index];
75}
76
77void ARM_Dynarmic::SetReg(int index, u32 value) {
78 jit->Regs()[index] = value;
79}
80
81u32 ARM_Dynarmic::GetVFPReg(int index) const {
82 return jit->ExtRegs()[index];
83}
84
85void ARM_Dynarmic::SetVFPReg(int index, u32 value) {
86 jit->ExtRegs()[index] = value;
87}
88
89u32 ARM_Dynarmic::GetVFPSystemReg(VFPSystemRegister reg) const {
90 if (reg == VFP_FPSCR) {
91 return jit->Fpscr();
92 }
93
94 // Dynarmic does not implement and/or expose other VFP registers, fallback to interpreter state
95 return interpreter_state->VFP[reg];
96}
97
98void ARM_Dynarmic::SetVFPSystemReg(VFPSystemRegister reg, u32 value) {
99 if (reg == VFP_FPSCR) {
100 jit->SetFpscr(value);
101 }
102
103 // Dynarmic does not implement and/or expose other VFP registers, fallback to interpreter state
104 interpreter_state->VFP[reg] = value;
105}
106
107u32 ARM_Dynarmic::GetCPSR() const {
108 return jit->Cpsr();
109}
110
111void ARM_Dynarmic::SetCPSR(u32 cpsr) {
112 jit->Cpsr() = cpsr;
113}
114
115u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) {
116 return interpreter_state->CP15[reg];
117}
118
119void ARM_Dynarmic::SetCP15Register(CP15Register reg, u32 value) {
120 interpreter_state->CP15[reg] = value;
121}
122
123void ARM_Dynarmic::AddTicks(u64 ticks) {
124 down_count -= ticks;
125 if (down_count < 0) {
126 CoreTiming::Advance();
127 }
128}
129
130MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64));
131
132void ARM_Dynarmic::ExecuteInstructions(int num_instructions) {
133 MICROPROFILE_SCOPE(ARM_Jit);
134
135 jit->Run(static_cast<unsigned>(num_instructions));
136
137 AddTicks(num_instructions);
138}
139
140void ARM_Dynarmic::SaveContext(Core::ThreadContext& ctx) {
141 memcpy(ctx.cpu_registers, jit->Regs().data(), sizeof(ctx.cpu_registers));
142 memcpy(ctx.fpu_registers, jit->ExtRegs().data(), sizeof(ctx.fpu_registers));
143
144 ctx.sp = jit->Regs()[13];
145 ctx.lr = jit->Regs()[14];
146 ctx.pc = jit->Regs()[15];
147 ctx.cpsr = jit->Cpsr();
148
149 ctx.fpscr = jit->Fpscr();
150 ctx.fpexc = interpreter_state->VFP[VFP_FPEXC];
151}
152
153void ARM_Dynarmic::LoadContext(const Core::ThreadContext& ctx) {
154 memcpy(jit->Regs().data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
155 memcpy(jit->ExtRegs().data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));
156
157 jit->Regs()[13] = ctx.sp;
158 jit->Regs()[14] = ctx.lr;
159 jit->Regs()[15] = ctx.pc;
160 jit->Cpsr() = ctx.cpsr;
161
162 jit->SetFpscr(ctx.fpscr);
163 interpreter_state->VFP[VFP_FPEXC] = ctx.fpexc;
164}
165
166void ARM_Dynarmic::PrepareReschedule() {
167 if (jit->IsExecuting()) {
168 jit->HaltExecution();
169 }
170}
171
172void ARM_Dynarmic::ClearInstructionCache() {
173 jit->ClearCache();
174}
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
new file mode 100644
index 000000000..d493cabd5
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -0,0 +1,50 @@
1// Copyright 2016 Citra Emulator Project
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
9#include <dynarmic/dynarmic.h>
10
11#include "common/common_types.h"
12
13#include "core/arm/arm_interface.h"
14#include "core/arm/skyeye_common/armstate.h"
15
16namespace Core {
17struct ThreadContext;
18}
19
20class ARM_Dynarmic final : public ARM_Interface {
21public:
22 ARM_Dynarmic(PrivilegeMode initial_mode);
23
24 void SetPC(u32 pc) override;
25 u32 GetPC() const override;
26 u32 GetReg(int index) const override;
27 void SetReg(int index, u32 value) override;
28 u32 GetVFPReg(int index) const override;
29 void SetVFPReg(int index, u32 value) override;
30 u32 GetVFPSystemReg(VFPSystemRegister reg) const override;
31 void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
32 u32 GetCPSR() const override;
33 void SetCPSR(u32 cpsr) override;
34 u32 GetCP15Register(CP15Register reg) override;
35 void SetCP15Register(CP15Register reg, u32 value) override;
36
37 void AddTicks(u64 ticks) override;
38
39 void SaveContext(Core::ThreadContext& ctx) override;
40 void LoadContext(const Core::ThreadContext& ctx) override;
41
42 void PrepareReschedule() override;
43 void ExecuteInstructions(int num_instructions) override;
44
45 void ClearInstructionCache() override;
46
47private:
48 std::unique_ptr<Dynarmic::Jit> jit;
49 std::unique_ptr<ARMul_State> interpreter_state;
50};
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index ab77da965..d84917529 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -93,15 +93,6 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
93 AddTicks(ticks_executed); 93 AddTicks(ticks_executed);
94} 94}
95 95
96void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) {
97 memset(&context, 0, sizeof(Core::ThreadContext));
98
99 context.cpu_registers[0] = arg;
100 context.pc = entry_point;
101 context.sp = stack_top;
102 context.cpsr = USER32MODE | ((entry_point & 1) << 5); // Usermode and THUMB mode
103}
104
105void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { 96void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
106 memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers)); 97 memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers));
107 memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers)); 98 memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers));
@@ -111,8 +102,8 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
111 ctx.pc = state->Reg[15]; 102 ctx.pc = state->Reg[15];
112 ctx.cpsr = state->Cpsr; 103 ctx.cpsr = state->Cpsr;
113 104
114 ctx.fpscr = state->VFP[1]; 105 ctx.fpscr = state->VFP[VFP_FPSCR];
115 ctx.fpexc = state->VFP[2]; 106 ctx.fpexc = state->VFP[VFP_FPEXC];
116} 107}
117 108
118void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { 109void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
@@ -124,8 +115,8 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
124 state->Reg[15] = ctx.pc; 115 state->Reg[15] = ctx.pc;
125 state->Cpsr = ctx.cpsr; 116 state->Cpsr = ctx.cpsr;
126 117
127 state->VFP[1] = ctx.fpscr; 118 state->VFP[VFP_FPSCR] = ctx.fpscr;
128 state->VFP[2] = ctx.fpexc; 119 state->VFP[VFP_FPEXC] = ctx.fpexc;
129} 120}
130 121
131void ARM_DynCom::PrepareReschedule() { 122void ARM_DynCom::PrepareReschedule() {
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index e763abc24..70f71a828 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -16,7 +16,7 @@ namespace Core {
16struct ThreadContext; 16struct ThreadContext;
17} 17}
18 18
19class ARM_DynCom final : virtual public ARM_Interface { 19class ARM_DynCom final : public ARM_Interface {
20public: 20public:
21 ARM_DynCom(PrivilegeMode initial_mode); 21 ARM_DynCom(PrivilegeMode initial_mode);
22 ~ARM_DynCom(); 22 ~ARM_DynCom();
@@ -38,7 +38,6 @@ public:
38 38
39 void AddTicks(u64 ticks) override; 39 void AddTicks(u64 ticks) override;
40 40
41 void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) override;
42 void SaveContext(Core::ThreadContext& ctx) override; 41 void SaveContext(Core::ThreadContext& ctx) override;
43 void LoadContext(const Core::ThreadContext& ctx) override; 42 void LoadContext(const Core::ThreadContext& ctx) override;
44 43