summaryrefslogtreecommitdiff
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
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 '')
-rw-r--r--.gitmodules23
-rw-r--r--CMakeLists.txt10
m---------externals/boost0
m---------externals/dynarmic0
-rw-r--r--src/citra/config.cpp1
-rw-r--r--src/citra/default_ini.h4
-rw-r--r--src/citra_qt/config.cpp2
-rw-r--r--src/citra_qt/configure_general.cpp5
-rw-r--r--src/citra_qt/configure_general.ui20
-rw-r--r--src/common/microprofile.h2
-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
19 files changed, 317 insertions, 47 deletions
diff --git a/.gitmodules b/.gitmodules
index 1f0b80768..f498a60de 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,15 +1,18 @@
1[submodule "inih"] 1[submodule "inih"]
2 path = externals/inih/inih 2 path = externals/inih/inih
3 url = https://github.com/svn2github/inih 3 url = https://github.com/svn2github/inih
4[submodule "boost"] 4[submodule "boost"]
5 path = externals/boost 5 path = externals/boost
6 url = https://github.com/citra-emu/ext-boost.git 6 url = https://github.com/citra-emu/ext-boost.git
7[submodule "nihstro"] 7[submodule "nihstro"]
8 path = externals/nihstro 8 path = externals/nihstro
9 url = https://github.com/neobrain/nihstro.git 9 url = https://github.com/neobrain/nihstro.git
10[submodule "soundtouch"] 10[submodule "soundtouch"]
11 path = externals/soundtouch 11 path = externals/soundtouch
12 url = https://github.com/citra-emu/ext-soundtouch.git 12 url = https://github.com/citra-emu/ext-soundtouch.git
13[submodule "catch"] 13[submodule "catch"]
14 path = externals/catch 14 path = externals/catch
15 url = https://github.com/philsquared/Catch.git 15 url = https://github.com/philsquared/Catch.git
16[submodule "dynarmic"]
17 path = externals/dynarmic
18 url = https://github.com/MerryMage/dynarmic.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ac3df0e0..c7a24f04f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,12 +118,11 @@ else()
118endif() 118endif()
119 119
120find_package(Boost 1.57.0 QUIET) 120find_package(Boost 1.57.0 QUIET)
121if (Boost_FOUND) 121if (NOT Boost_FOUND)
122 include_directories(${Boost_INCLUDE_DIRS})
123else()
124 message(STATUS "Boost 1.57.0 or newer not found, falling back to externals") 122 message(STATUS "Boost 1.57.0 or newer not found, falling back to externals")
125 include_directories(externals/boost) 123 set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost")
126endif() 124endif()
125include_directories(${Boost_INCLUDE_DIR})
127 126
128# Include bundled CMake modules 127# Include bundled CMake modules
129list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/cmake-modules") 128list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/cmake-modules")
@@ -227,6 +226,9 @@ set(INI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/externals/inih")
227include_directories(${INI_PREFIX}) 226include_directories(${INI_PREFIX})
228add_subdirectory(${INI_PREFIX}) 227add_subdirectory(${INI_PREFIX})
229 228
229option(DYNARMIC_TESTS OFF)
230add_subdirectory(externals/dynarmic)
231
230add_subdirectory(externals/glad) 232add_subdirectory(externals/glad)
231include_directories(externals/microprofile) 233include_directories(externals/microprofile)
232include_directories(externals/nihstro/include) 234include_directories(externals/nihstro/include)
diff --git a/externals/boost b/externals/boost
Subproject 2dcb9d979665b6aabb1635c617973e02914e60e Subproject f005c955f8147a29667aa0b65257abc3dd520b0
diff --git a/externals/dynarmic b/externals/dynarmic
new file mode 160000
Subproject 943487eceed82fbae016c333dc9fe33981e69aa
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 110b883fb..1a09f0e55 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -65,6 +65,7 @@ void Config::ReadValues() {
65 Settings::values.pad_circle_modifier_scale = (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5); 65 Settings::values.pad_circle_modifier_scale = (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5);
66 66
67 // Core 67 // Core
68 Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
68 Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0); 69 Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0);
69 70
70 // Renderer 71 // Renderer
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 2031620a5..788174508 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -38,6 +38,10 @@ pad_circle_modifier =
38pad_circle_modifier_scale = 38pad_circle_modifier_scale =
39 39
40[Core] 40[Core]
41# Whether to use the Just-In-Time (JIT) compiler for CPU emulation
42# 0: Interpreter (slow), 1 (default): JIT (fast)
43use_cpu_jit =
44
41# The applied frameskip amount. Must be a power of two. 45# The applied frameskip amount. Must be a power of two.
42# 0 (default): No frameskip, 1: x2 frameskip, 2: x4 frameskip, 3: x8 frameskip, etc. 46# 0 (default): No frameskip, 1: x2 frameskip, 2: x4 frameskip, 3: x8 frameskip, etc.
43frame_skip = 47frame_skip =
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index fa3fa210c..cf1c09930 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -41,6 +41,7 @@ void Config::ReadValues() {
41 qt_config->endGroup(); 41 qt_config->endGroup();
42 42
43 qt_config->beginGroup("Core"); 43 qt_config->beginGroup("Core");
44 Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
44 Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt(); 45 Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt();
45 qt_config->endGroup(); 46 qt_config->endGroup();
46 47
@@ -134,6 +135,7 @@ void Config::SaveValues() {
134 qt_config->endGroup(); 135 qt_config->endGroup();
135 136
136 qt_config->beginGroup("Core"); 137 qt_config->beginGroup("Core");
138 qt_config->setValue("use_cpu_jit", Settings::values.use_cpu_jit);
137 qt_config->setValue("frame_skip", Settings::values.frame_skip); 139 qt_config->setValue("frame_skip", Settings::values.frame_skip);
138 qt_config->endGroup(); 140 qt_config->endGroup();
139 141
diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp
index 95aab9f2e..e6832341a 100644
--- a/src/citra_qt/configure_general.cpp
+++ b/src/citra_qt/configure_general.cpp
@@ -7,6 +7,7 @@
7#include "ui_configure_general.h" 7#include "ui_configure_general.h"
8 8
9#include "core/settings.h" 9#include "core/settings.h"
10#include "core/system.h"
10 11
11ConfigureGeneral::ConfigureGeneral(QWidget *parent) : 12ConfigureGeneral::ConfigureGeneral(QWidget *parent) :
12 QWidget(parent), 13 QWidget(parent),
@@ -14,6 +15,8 @@ ConfigureGeneral::ConfigureGeneral(QWidget *parent) :
14{ 15{
15 ui->setupUi(this); 16 ui->setupUi(this);
16 this->setConfiguration(); 17 this->setConfiguration();
18
19 ui->toggle_cpu_jit->setEnabled(!System::IsPoweredOn());
17} 20}
18 21
19ConfigureGeneral::~ConfigureGeneral() { 22ConfigureGeneral::~ConfigureGeneral() {
@@ -22,6 +25,7 @@ ConfigureGeneral::~ConfigureGeneral() {
22void ConfigureGeneral::setConfiguration() { 25void ConfigureGeneral::setConfiguration() {
23 ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan); 26 ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
24 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); 27 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
28 ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit);
25 ui->region_combobox->setCurrentIndex(Settings::values.region_value); 29 ui->region_combobox->setCurrentIndex(Settings::values.region_value);
26} 30}
27 31
@@ -29,5 +33,6 @@ void ConfigureGeneral::applyConfiguration() {
29 UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); 33 UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
30 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); 34 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
31 Settings::values.region_value = ui->region_combobox->currentIndex(); 35 Settings::values.region_value = ui->region_combobox->currentIndex();
36 Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked();
32 Settings::Apply(); 37 Settings::Apply();
33} 38}
diff --git a/src/citra_qt/configure_general.ui b/src/citra_qt/configure_general.ui
index 343f804c0..81688113f 100644
--- a/src/citra_qt/configure_general.ui
+++ b/src/citra_qt/configure_general.ui
@@ -43,6 +43,26 @@
43 </layout> 43 </layout>
44 </widget> 44 </widget>
45 </item> 45 </item>
46 <item>
47 <widget class="QGroupBox" name="groupBox_2">
48 <property name="title">
49 <string>Performance</string>
50 </property>
51 <layout class="QHBoxLayout" name="horizontalLayout_7">
52 <item>
53 <layout class="QVBoxLayout" name="verticalLayout_5">
54 <item>
55 <widget class="QCheckBox" name="toggle_cpu_jit">
56 <property name="text">
57 <string>Enable CPU JIT</string>
58 </property>
59 </widget>
60 </item>
61 </layout>
62 </item>
63 </layout>
64 </widget>
65 </item>
46 <item> 66 <item>
47 <widget class="QGroupBox" name="groupBox_4"> 67 <widget class="QGroupBox" name="groupBox_4">
48 <property name="title"> 68 <property name="title">
diff --git a/src/common/microprofile.h b/src/common/microprofile.h
index ef312c6e1..670a58fe5 100644
--- a/src/common/microprofile.h
+++ b/src/common/microprofile.h
@@ -13,7 +13,7 @@
13#define MICROPROFILE_WEBSERVER 0 13#define MICROPROFILE_WEBSERVER 0
14#define MICROPROFILE_GPU_TIMERS 0 // TODO: Implement timer queries when we upgrade to OpenGL 3.3 14#define MICROPROFILE_GPU_TIMERS 0 // TODO: Implement timer queries when we upgrade to OpenGL 3.3
15#define MICROPROFILE_CONTEXT_SWITCH_TRACE 0 15#define MICROPROFILE_CONTEXT_SWITCH_TRACE 0
16#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (2048<<12) // 8 MB 16#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (2048<<13) // 16 MB
17 17
18#ifdef _WIN32 18#ifdef _WIN32
19// This isn't defined by the standard library in MSVC2015 19// This isn't defined by the standard library in MSVC2015
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