summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt6
-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
-rw-r--r--src/core/core.cpp19
-rw-r--r--src/core/hle/kernel/thread.cpp18
-rw-r--r--src/core/settings.h1
9 files changed, 265 insertions, 32 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 174e9dc79..4a9c6fd2f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,6 +1,7 @@
1set(SRCS 1set(SRCS
2 arm/disassembler/arm_disasm.cpp 2 arm/disassembler/arm_disasm.cpp
3 arm/disassembler/load_symbol_map.cpp 3 arm/disassembler/load_symbol_map.cpp
4 arm/dynarmic/arm_dynarmic.cpp
4 arm/dyncom/arm_dyncom.cpp 5 arm/dyncom/arm_dyncom.cpp
5 arm/dyncom/arm_dyncom_dec.cpp 6 arm/dyncom/arm_dyncom_dec.cpp
6 arm/dyncom/arm_dyncom_interpreter.cpp 7 arm/dyncom/arm_dyncom_interpreter.cpp
@@ -141,6 +142,7 @@ set(HEADERS
141 arm/arm_interface.h 142 arm/arm_interface.h
142 arm/disassembler/arm_disasm.h 143 arm/disassembler/arm_disasm.h
143 arm/disassembler/load_symbol_map.h 144 arm/disassembler/load_symbol_map.h
145 arm/dynarmic/arm_dynarmic.h
144 arm/dyncom/arm_dyncom.h 146 arm/dyncom/arm_dyncom.h
145 arm/dyncom/arm_dyncom_dec.h 147 arm/dyncom/arm_dyncom_dec.h
146 arm/dyncom/arm_dyncom_interpreter.h 148 arm/dyncom/arm_dyncom_interpreter.h
@@ -285,6 +287,10 @@ set(HEADERS
285 system.h 287 system.h
286 ) 288 )
287 289
290include_directories(../../externals/dynarmic/include)
291
288create_directory_groups(${SRCS} ${HEADERS}) 292create_directory_groups(${SRCS} ${HEADERS})
289 293
290add_library(core STATIC ${SRCS} ${HEADERS}) 294add_library(core STATIC ${SRCS} ${HEADERS})
295
296target_link_libraries(core dynarmic)
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
diff --git a/src/core/core.cpp b/src/core/core.cpp
index cabab744a..a3834adae 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -6,16 +6,16 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/core.h"
10#include "core/core_timing.h"
11
12#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
10#include "core/arm/dynarmic/arm_dynarmic.h"
13#include "core/arm/dyncom/arm_dyncom.h" 11#include "core/arm/dyncom/arm_dyncom.h"
12#include "core/core.h"
13#include "core/core_timing.h"
14#include "core/gdbstub/gdbstub.h"
14#include "core/hle/hle.h" 15#include "core/hle/hle.h"
15#include "core/hle/kernel/thread.h" 16#include "core/hle/kernel/thread.h"
16#include "core/hw/hw.h" 17#include "core/hw/hw.h"
17 18#include "core/settings.h"
18#include "core/gdbstub/gdbstub.h"
19 19
20namespace Core { 20namespace Core {
21 21
@@ -73,8 +73,13 @@ void Stop() {
73 73
74/// Initialize the core 74/// Initialize the core
75void Init() { 75void Init() {
76 g_sys_core = std::make_unique<ARM_DynCom>(USER32MODE); 76 if (Settings::values.use_cpu_jit) {
77 g_app_core = std::make_unique<ARM_DynCom>(USER32MODE); 77 g_sys_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
78 g_app_core = std::make_unique<ARM_Dynarmic>(USER32MODE);
79 } else {
80 g_sys_core = std::make_unique<ARM_DynCom>(USER32MODE);
81 g_app_core = std::make_unique<ARM_DynCom>(USER32MODE);
82 }
78 83
79 LOG_DEBUG(Core, "Initialized OK"); 84 LOG_DEBUG(Core, "Initialized OK");
80} 85}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 9dea995f4..f1e5cf3cb 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -441,6 +441,22 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
441 return std::make_tuple(0, 0, true); 441 return std::make_tuple(0, 0, true);
442} 442}
443 443
444/**
445 * Resets a thread context, making it ready to be scheduled and run by the CPU
446 * @param context Thread context to reset
447 * @param stack_top Address of the top of the stack
448 * @param entry_point Address of entry point for execution
449 * @param arg User argument for thread
450 */
451static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) {
452 memset(&context, 0, sizeof(Core::ThreadContext));
453
454 context.cpu_registers[0] = arg;
455 context.pc = entry_point;
456 context.sp = stack_top;
457 context.cpsr = USER32MODE | ((entry_point & 1) << 5); // Usermode and THUMB mode
458}
459
444ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, 460ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
445 u32 arg, s32 processor_id, VAddr stack_top) { 461 u32 arg, s32 processor_id, VAddr stack_top) {
446 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 462 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
@@ -525,7 +541,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
525 541
526 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 542 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
527 // to initialize the context 543 // to initialize the context
528 Core::g_app_core->ResetContext(thread->context, stack_top, entry_point, arg); 544 ResetThreadContext(thread->context, stack_top, entry_point, arg);
529 545
530 ready_queue.push_back(thread->current_priority, thread.get()); 546 ready_queue.push_back(thread->current_priority, thread.get());
531 thread->status = THREADSTATUS_READY; 547 thread->status = THREADSTATUS_READY;
diff --git a/src/core/settings.h b/src/core/settings.h
index fb3fbe391..fcd14c6f3 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -60,6 +60,7 @@ struct Values {
60 float pad_circle_modifier_scale; 60 float pad_circle_modifier_scale;
61 61
62 // Core 62 // Core
63 bool use_cpu_jit;
63 int frame_skip; 64 int frame_skip;
64 65
65 // Data Storage 66 // Data Storage