diff --git a/.gitmodules b/.gitmodules
index 1f0b80768b..f498a60de5 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,15 +1,18 @@
[submodule "inih"]
- path = externals/inih/inih
- url = https://github.com/svn2github/inih
+ path = externals/inih/inih
+ url = https://github.com/svn2github/inih
[submodule "boost"]
- path = externals/boost
- url = https://github.com/citra-emu/ext-boost.git
+ path = externals/boost
+ url = https://github.com/citra-emu/ext-boost.git
[submodule "nihstro"]
- path = externals/nihstro
- url = https://github.com/neobrain/nihstro.git
+ path = externals/nihstro
+ url = https://github.com/neobrain/nihstro.git
[submodule "soundtouch"]
- path = externals/soundtouch
- url = https://github.com/citra-emu/ext-soundtouch.git
+ path = externals/soundtouch
+ url = https://github.com/citra-emu/ext-soundtouch.git
[submodule "catch"]
- path = externals/catch
- url = https://github.com/philsquared/Catch.git
+ path = externals/catch
+ url = https://github.com/philsquared/Catch.git
+[submodule "dynarmic"]
+ path = externals/dynarmic
+ url = https://github.com/MerryMage/dynarmic.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ac3df0e0c..c7a24f04fc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,12 +118,11 @@ else()
endif()
find_package(Boost 1.57.0 QUIET)
-if (Boost_FOUND)
- include_directories(${Boost_INCLUDE_DIRS})
-else()
+if (NOT Boost_FOUND)
message(STATUS "Boost 1.57.0 or newer not found, falling back to externals")
- include_directories(externals/boost)
+ set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost")
endif()
+include_directories(${Boost_INCLUDE_DIR})
# Include bundled CMake modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/cmake-modules")
@@ -227,6 +226,9 @@ set(INI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/externals/inih")
include_directories(${INI_PREFIX})
add_subdirectory(${INI_PREFIX})
+option(DYNARMIC_TESTS OFF)
+add_subdirectory(externals/dynarmic)
+
add_subdirectory(externals/glad)
include_directories(externals/microprofile)
include_directories(externals/nihstro/include)
diff --git a/externals/boost b/externals/boost
index 2dcb9d9796..f005c955f8 160000
--- a/externals/boost
+++ b/externals/boost
@@ -1 +1 @@
-Subproject commit 2dcb9d979665b6aabb1635c617973e02914e60ec
+Subproject commit f005c955f8147a29667aa0b65257abc3dd520b0c
diff --git a/externals/dynarmic b/externals/dynarmic
new file mode 160000
index 0000000000..943487ecee
--- /dev/null
+++ b/externals/dynarmic
@@ -0,0 +1 @@
+Subproject commit 943487eceed82fbae016c333dc9fe33981e69aa8
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 110b883fb4..1a09f0e551 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -65,6 +65,7 @@ void Config::ReadValues() {
Settings::values.pad_circle_modifier_scale = (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5);
// Core
+ Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0);
// Renderer
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 2031620a5f..7881745085 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -38,6 +38,10 @@ pad_circle_modifier =
pad_circle_modifier_scale =
[Core]
+# Whether to use the Just-In-Time (JIT) compiler for CPU emulation
+# 0: Interpreter (slow), 1 (default): JIT (fast)
+use_cpu_jit =
+
# The applied frameskip amount. Must be a power of two.
# 0 (default): No frameskip, 1: x2 frameskip, 2: x4 frameskip, 3: x8 frameskip, etc.
frame_skip =
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index fa3fa210c7..cf1c09930c 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -41,6 +41,7 @@ void Config::ReadValues() {
qt_config->endGroup();
qt_config->beginGroup("Core");
+ Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt();
qt_config->endGroup();
@@ -134,6 +135,7 @@ void Config::SaveValues() {
qt_config->endGroup();
qt_config->beginGroup("Core");
+ qt_config->setValue("use_cpu_jit", Settings::values.use_cpu_jit);
qt_config->setValue("frame_skip", Settings::values.frame_skip);
qt_config->endGroup();
diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp
index 95aab9f2eb..e6832341ab 100644
--- a/src/citra_qt/configure_general.cpp
+++ b/src/citra_qt/configure_general.cpp
@@ -7,6 +7,7 @@
#include "ui_configure_general.h"
#include "core/settings.h"
+#include "core/system.h"
ConfigureGeneral::ConfigureGeneral(QWidget *parent) :
QWidget(parent),
@@ -14,6 +15,8 @@ ConfigureGeneral::ConfigureGeneral(QWidget *parent) :
{
ui->setupUi(this);
this->setConfiguration();
+
+ ui->toggle_cpu_jit->setEnabled(!System::IsPoweredOn());
}
ConfigureGeneral::~ConfigureGeneral() {
@@ -22,6 +25,7 @@ ConfigureGeneral::~ConfigureGeneral() {
void ConfigureGeneral::setConfiguration() {
ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
+ ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit);
ui->region_combobox->setCurrentIndex(Settings::values.region_value);
}
@@ -29,5 +33,6 @@ void ConfigureGeneral::applyConfiguration() {
UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
Settings::values.region_value = ui->region_combobox->currentIndex();
+ Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked();
Settings::Apply();
}
diff --git a/src/citra_qt/configure_general.ui b/src/citra_qt/configure_general.ui
index 343f804c00..81688113f2 100644
--- a/src/citra_qt/configure_general.ui
+++ b/src/citra_qt/configure_general.ui
@@ -43,6 +43,26 @@
+ -
+
+
+ Performance
+
+
+
-
+
+
-
+
+
+ Enable CPU JIT
+
+
+
+
+
+
+
+
-
diff --git a/src/common/microprofile.h b/src/common/microprofile.h
index ef312c6e18..670a58fe57 100644
--- a/src/common/microprofile.h
+++ b/src/common/microprofile.h
@@ -13,7 +13,7 @@
#define MICROPROFILE_WEBSERVER 0
#define MICROPROFILE_GPU_TIMERS 0 // TODO: Implement timer queries when we upgrade to OpenGL 3.3
#define MICROPROFILE_CONTEXT_SWITCH_TRACE 0
-#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (2048<<12) // 8 MB
+#define MICROPROFILE_PER_THREAD_BUFFER_SIZE (2048<<13) // 16 MB
#ifdef _WIN32
// This isn't defined by the standard library in MSVC2015
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 174e9dc794..4a9c6fd2fe 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,6 +1,7 @@
set(SRCS
arm/disassembler/arm_disasm.cpp
arm/disassembler/load_symbol_map.cpp
+ arm/dynarmic/arm_dynarmic.cpp
arm/dyncom/arm_dyncom.cpp
arm/dyncom/arm_dyncom_dec.cpp
arm/dyncom/arm_dyncom_interpreter.cpp
@@ -141,6 +142,7 @@ set(HEADERS
arm/arm_interface.h
arm/disassembler/arm_disasm.h
arm/disassembler/load_symbol_map.h
+ arm/dynarmic/arm_dynarmic.h
arm/dyncom/arm_dyncom.h
arm/dyncom/arm_dyncom_dec.h
arm/dyncom/arm_dyncom_interpreter.h
@@ -285,6 +287,10 @@ set(HEADERS
system.h
)
+include_directories(../../externals/dynarmic/include)
+
create_directory_groups(${SRCS} ${HEADERS})
add_library(core STATIC ${SRCS} ${HEADERS})
+
+target_link_libraries(core dynarmic)
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index de5e9c8fac..480c90e660 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -121,15 +121,6 @@ public:
*/
virtual void AddTicks(u64 ticks) = 0;
- /**
- * Initializes a CPU context for use on this CPU
- * @param context Thread context to reset
- * @param stack_top Pointer to the top of the stack
- * @param entry_point Entry point for execution
- * @param arg User argument for thread
- */
- virtual void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) = 0;
-
/**
* Saves the current CPU context
* @param ctx Thread context to save
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
new file mode 100644
index 0000000000..a521aec7ce
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -0,0 +1,174 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+#include "common/microprofile.h"
+
+#include
+
+#include "core/arm/dynarmic/arm_dynarmic.h"
+#include "core/arm/dyncom/arm_dyncom_interpreter.h"
+#include "core/core.h"
+#include "core/core_timing.h"
+#include "core/hle/svc.h"
+#include "core/memory.h"
+
+static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void* user_arg) {
+ ARMul_State* state = static_cast(user_arg);
+
+ state->Reg = jit->Regs();
+ state->Cpsr = jit->Cpsr();
+ state->Reg[15] = pc;
+ state->ExtReg = jit->ExtRegs();
+ state->VFP[VFP_FPSCR] = jit->Fpscr();
+ state->NumInstrsToExecute = 1;
+
+ InterpreterMainLoop(state);
+
+ bool is_thumb = (state->Cpsr & (1 << 5)) != 0;
+ state->Reg[15] &= (is_thumb ? 0xFFFFFFFE : 0xFFFFFFFC);
+
+ jit->Regs() = state->Reg;
+ jit->Cpsr() = state->Cpsr;
+ jit->ExtRegs() = state->ExtReg;
+ jit->SetFpscr(state->VFP[VFP_FPSCR]);
+}
+
+static bool IsReadOnlyMemory(u32 vaddr) {
+ // TODO(bunnei): ImplementMe
+ return false;
+}
+
+static Dynarmic::UserCallbacks GetUserCallbacks(ARMul_State* interpeter_state) {
+ Dynarmic::UserCallbacks user_callbacks{};
+ user_callbacks.InterpreterFallback = &InterpreterFallback;
+ user_callbacks.user_arg = static_cast(interpeter_state);
+ user_callbacks.CallSVC = &SVC::CallSVC;
+ user_callbacks.IsReadOnlyMemory = &IsReadOnlyMemory;
+ user_callbacks.MemoryRead8 = &Memory::Read8;
+ user_callbacks.MemoryRead16 = &Memory::Read16;
+ user_callbacks.MemoryRead32 = &Memory::Read32;
+ user_callbacks.MemoryRead64 = &Memory::Read64;
+ user_callbacks.MemoryWrite8 = &Memory::Write8;
+ user_callbacks.MemoryWrite16 = &Memory::Write16;
+ user_callbacks.MemoryWrite32 = &Memory::Write32;
+ user_callbacks.MemoryWrite64 = &Memory::Write64;
+ return user_callbacks;
+}
+
+ARM_Dynarmic::ARM_Dynarmic(PrivilegeMode initial_mode) {
+ interpreter_state = std::make_unique(initial_mode);
+ jit = std::make_unique(GetUserCallbacks(interpreter_state.get()));
+}
+
+void ARM_Dynarmic::SetPC(u32 pc) {
+ jit->Regs()[15] = pc;
+}
+
+u32 ARM_Dynarmic::GetPC() const {
+ return jit->Regs()[15];
+}
+
+u32 ARM_Dynarmic::GetReg(int index) const {
+ return jit->Regs()[index];
+}
+
+void ARM_Dynarmic::SetReg(int index, u32 value) {
+ jit->Regs()[index] = value;
+}
+
+u32 ARM_Dynarmic::GetVFPReg(int index) const {
+ return jit->ExtRegs()[index];
+}
+
+void ARM_Dynarmic::SetVFPReg(int index, u32 value) {
+ jit->ExtRegs()[index] = value;
+}
+
+u32 ARM_Dynarmic::GetVFPSystemReg(VFPSystemRegister reg) const {
+ if (reg == VFP_FPSCR) {
+ return jit->Fpscr();
+ }
+
+ // Dynarmic does not implement and/or expose other VFP registers, fallback to interpreter state
+ return interpreter_state->VFP[reg];
+}
+
+void ARM_Dynarmic::SetVFPSystemReg(VFPSystemRegister reg, u32 value) {
+ if (reg == VFP_FPSCR) {
+ jit->SetFpscr(value);
+ }
+
+ // Dynarmic does not implement and/or expose other VFP registers, fallback to interpreter state
+ interpreter_state->VFP[reg] = value;
+}
+
+u32 ARM_Dynarmic::GetCPSR() const {
+ return jit->Cpsr();
+}
+
+void ARM_Dynarmic::SetCPSR(u32 cpsr) {
+ jit->Cpsr() = cpsr;
+}
+
+u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) {
+ return interpreter_state->CP15[reg];
+}
+
+void ARM_Dynarmic::SetCP15Register(CP15Register reg, u32 value) {
+ interpreter_state->CP15[reg] = value;
+}
+
+void ARM_Dynarmic::AddTicks(u64 ticks) {
+ down_count -= ticks;
+ if (down_count < 0) {
+ CoreTiming::Advance();
+ }
+}
+
+MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64));
+
+void ARM_Dynarmic::ExecuteInstructions(int num_instructions) {
+ MICROPROFILE_SCOPE(ARM_Jit);
+
+ jit->Run(static_cast(num_instructions));
+
+ AddTicks(num_instructions);
+}
+
+void ARM_Dynarmic::SaveContext(Core::ThreadContext& ctx) {
+ memcpy(ctx.cpu_registers, jit->Regs().data(), sizeof(ctx.cpu_registers));
+ memcpy(ctx.fpu_registers, jit->ExtRegs().data(), sizeof(ctx.fpu_registers));
+
+ ctx.sp = jit->Regs()[13];
+ ctx.lr = jit->Regs()[14];
+ ctx.pc = jit->Regs()[15];
+ ctx.cpsr = jit->Cpsr();
+
+ ctx.fpscr = jit->Fpscr();
+ ctx.fpexc = interpreter_state->VFP[VFP_FPEXC];
+}
+
+void ARM_Dynarmic::LoadContext(const Core::ThreadContext& ctx) {
+ memcpy(jit->Regs().data(), ctx.cpu_registers, sizeof(ctx.cpu_registers));
+ memcpy(jit->ExtRegs().data(), ctx.fpu_registers, sizeof(ctx.fpu_registers));
+
+ jit->Regs()[13] = ctx.sp;
+ jit->Regs()[14] = ctx.lr;
+ jit->Regs()[15] = ctx.pc;
+ jit->Cpsr() = ctx.cpsr;
+
+ jit->SetFpscr(ctx.fpscr);
+ interpreter_state->VFP[VFP_FPEXC] = ctx.fpexc;
+}
+
+void ARM_Dynarmic::PrepareReschedule() {
+ if (jit->IsExecuting()) {
+ jit->HaltExecution();
+ }
+}
+
+void ARM_Dynarmic::ClearInstructionCache() {
+ jit->ClearCache();
+}
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
new file mode 100644
index 0000000000..d493cabd53
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -0,0 +1,50 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+#include
+
+#include "common/common_types.h"
+
+#include "core/arm/arm_interface.h"
+#include "core/arm/skyeye_common/armstate.h"
+
+namespace Core {
+struct ThreadContext;
+}
+
+class ARM_Dynarmic final : public ARM_Interface {
+public:
+ ARM_Dynarmic(PrivilegeMode initial_mode);
+
+ void SetPC(u32 pc) override;
+ u32 GetPC() const override;
+ u32 GetReg(int index) const override;
+ void SetReg(int index, u32 value) override;
+ u32 GetVFPReg(int index) const override;
+ void SetVFPReg(int index, u32 value) override;
+ u32 GetVFPSystemReg(VFPSystemRegister reg) const override;
+ void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override;
+ u32 GetCPSR() const override;
+ void SetCPSR(u32 cpsr) override;
+ u32 GetCP15Register(CP15Register reg) override;
+ void SetCP15Register(CP15Register reg, u32 value) override;
+
+ void AddTicks(u64 ticks) override;
+
+ void SaveContext(Core::ThreadContext& ctx) override;
+ void LoadContext(const Core::ThreadContext& ctx) override;
+
+ void PrepareReschedule() override;
+ void ExecuteInstructions(int num_instructions) override;
+
+ void ClearInstructionCache() override;
+
+private:
+ std::unique_ptr jit;
+ std::unique_ptr interpreter_state;
+};
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index ab77da9657..d849175296 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) {
AddTicks(ticks_executed);
}
-void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) {
- memset(&context, 0, sizeof(Core::ThreadContext));
-
- context.cpu_registers[0] = arg;
- context.pc = entry_point;
- context.sp = stack_top;
- context.cpsr = USER32MODE | ((entry_point & 1) << 5); // Usermode and THUMB mode
-}
-
void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers));
memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers));
@@ -111,8 +102,8 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
ctx.pc = state->Reg[15];
ctx.cpsr = state->Cpsr;
- ctx.fpscr = state->VFP[1];
- ctx.fpexc = state->VFP[2];
+ ctx.fpscr = state->VFP[VFP_FPSCR];
+ ctx.fpexc = state->VFP[VFP_FPEXC];
}
void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
@@ -124,8 +115,8 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
state->Reg[15] = ctx.pc;
state->Cpsr = ctx.cpsr;
- state->VFP[1] = ctx.fpscr;
- state->VFP[2] = ctx.fpexc;
+ state->VFP[VFP_FPSCR] = ctx.fpscr;
+ state->VFP[VFP_FPEXC] = ctx.fpexc;
}
void ARM_DynCom::PrepareReschedule() {
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index e763abc24d..70f71a8280 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -16,7 +16,7 @@ namespace Core {
struct ThreadContext;
}
-class ARM_DynCom final : virtual public ARM_Interface {
+class ARM_DynCom final : public ARM_Interface {
public:
ARM_DynCom(PrivilegeMode initial_mode);
~ARM_DynCom();
@@ -38,7 +38,6 @@ public:
void AddTicks(u64 ticks) override;
- void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) override;
void SaveContext(Core::ThreadContext& ctx) override;
void LoadContext(const Core::ThreadContext& ctx) override;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index cabab744ad..a3834adae6 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -6,16 +6,16 @@
#include "common/logging/log.h"
+#include "core/arm/arm_interface.h"
+#include "core/arm/dynarmic/arm_dynarmic.h"
+#include "core/arm/dyncom/arm_dyncom.h"
#include "core/core.h"
#include "core/core_timing.h"
-
-#include "core/arm/arm_interface.h"
-#include "core/arm/dyncom/arm_dyncom.h"
+#include "core/gdbstub/gdbstub.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/thread.h"
#include "core/hw/hw.h"
-
-#include "core/gdbstub/gdbstub.h"
+#include "core/settings.h"
namespace Core {
@@ -73,8 +73,13 @@ void Stop() {
/// Initialize the core
void Init() {
- g_sys_core = std::make_unique(USER32MODE);
- g_app_core = std::make_unique(USER32MODE);
+ if (Settings::values.use_cpu_jit) {
+ g_sys_core = std::make_unique(USER32MODE);
+ g_app_core = std::make_unique(USER32MODE);
+ } else {
+ g_sys_core = std::make_unique(USER32MODE);
+ g_app_core = std::make_unique(USER32MODE);
+ }
LOG_DEBUG(Core, "Initialized OK");
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 9dea995f41..f1e5cf3cbf 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -441,6 +441,22 @@ std::tuple GetFreeThreadLocalSlot(std::vector>& t
return std::make_tuple(0, 0, true);
}
+/**
+ * Resets a thread context, making it ready to be scheduled and run by the CPU
+ * @param context Thread context to reset
+ * @param stack_top Address of the top of the stack
+ * @param entry_point Address of entry point for execution
+ * @param arg User argument for thread
+ */
+static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) {
+ memset(&context, 0, sizeof(Core::ThreadContext));
+
+ context.cpu_registers[0] = arg;
+ context.pc = entry_point;
+ context.sp = stack_top;
+ context.cpsr = USER32MODE | ((entry_point & 1) << 5); // Usermode and THUMB mode
+}
+
ResultVal> Thread::Create(std::string name, VAddr entry_point, s32 priority,
u32 arg, s32 processor_id, VAddr stack_top) {
if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
@@ -525,7 +541,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point,
// TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
// to initialize the context
- Core::g_app_core->ResetContext(thread->context, stack_top, entry_point, arg);
+ ResetThreadContext(thread->context, stack_top, entry_point, arg);
ready_queue.push_back(thread->current_priority, thread.get());
thread->status = THREADSTATUS_READY;
diff --git a/src/core/settings.h b/src/core/settings.h
index fb3fbe391d..fcd14c6f3e 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -60,6 +60,7 @@ struct Values {
float pad_circle_modifier_scale;
// Core
+ bool use_cpu_jit;
int frame_skip;
// Data Storage