From 7a7457085f58739830faeacf719d174ced7fb826 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Sep 2016 18:58:36 -0400 Subject: [PATCH 1/9] externals/boost: Use latest upstream with variant. --- externals/boost | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/boost b/externals/boost index 2dcb9d979..f005c955f 160000 --- a/externals/boost +++ b/externals/boost @@ -1 +1 @@ -Subproject commit 2dcb9d979665b6aabb1635c617973e02914e60ec +Subproject commit f005c955f8147a29667aa0b65257abc3dd520b0c From 53375018a6b98279369b1ad1f878079b341f5e82 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Sep 2016 22:55:07 -0400 Subject: [PATCH 2/9] CMakeLists: Set Boost_INCLUDE_DIR. --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ac3df0e0..3932fd569 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") From f6d9456e02100f802ba26770fa43be87d5792aca Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Sep 2016 23:00:15 -0400 Subject: [PATCH 3/9] dynarmic: Add new submodule. --- .gitmodules | 23 +++++++++++++---------- CMakeLists.txt | 3 +++ externals/dynarmic | 1 + 3 files changed, 17 insertions(+), 10 deletions(-) create mode 160000 externals/dynarmic diff --git a/.gitmodules b/.gitmodules index 1f0b80768..f498a60de 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 3932fd569..c7a24f04f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,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/dynarmic b/externals/dynarmic new file mode 160000 index 000000000..cc3e7e71a --- /dev/null +++ b/externals/dynarmic @@ -0,0 +1 @@ +Subproject commit cc3e7e71aa020cb243cb24d06f7577a9fd8170fe From 79d51cffcc42924d7ea90519251f2a87886682eb Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Sep 2016 23:07:14 -0400 Subject: [PATCH 4/9] dynarmic: Implement ARM CPU interface. --- src/core/CMakeLists.txt | 6 + src/core/arm/dynarmic/arm_dynarmic.cpp | 176 +++++++++++++++++++++++++ src/core/arm/dynarmic/arm_dynarmic.h | 51 +++++++ 3 files changed, 233 insertions(+) create mode 100644 src/core/arm/dynarmic/arm_dynarmic.cpp create mode 100644 src/core/arm/dynarmic/arm_dynarmic.h 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 @@ 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/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp new file mode 100644 index 000000000..9112917e1 --- /dev/null +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -0,0 +1,176 @@ +// 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 = (bool(*)(u32)) &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 { + // TODO(bunnei): ImplementMe + UNIMPLEMENTED(); + return 0; +} + +void ARM_Dynarmic::SetVFPSystemReg(VFPSystemRegister reg, u32 value) { + // TODO(bunnei): ImplementMe + UNIMPLEMENTED(); +} + +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::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_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 000000000..6cae56737 --- /dev/null +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -0,0 +1,51 @@ +// 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 : virtual 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 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; + + void PrepareReschedule() override; + void ExecuteInstructions(int num_instructions) override; + + void ClearInstructionCache() override; + +private: + std::unique_ptr jit; + std::unique_ptr interpreter_state; +}; From 3cca4efdfd48d7fd9603fda422ff540aeba04f7e Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Sep 2016 23:18:01 -0400 Subject: [PATCH 5/9] core: Add configuration option for CPU JIT. --- src/citra/config.cpp | 1 + src/citra/default_ini.h | 4 ++++ src/citra_qt/config.cpp | 2 ++ src/core/core.cpp | 19 ++++++++++++------- src/core/settings.h | 1 + 5 files changed, 20 insertions(+), 7 deletions(-) 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() { 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 2031620a5..788174508 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 fa3fa210c..cf1c09930 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/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 @@ #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/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 { float pad_circle_modifier_scale; // Core + bool use_cpu_jit; int frame_skip; // Data Storage From a27199fe9b6fdb122c35559f27b5b9f9b836f0ee Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 Sep 2016 23:30:01 -0400 Subject: [PATCH 6/9] qt: Add UI configuration option to enable CPU JIT. --- src/citra_qt/configure_general.cpp | 5 +++++ src/citra_qt/configure_general.ui | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) 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 @@ #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 343f804c0..81688113f 100644 --- a/src/citra_qt/configure_general.ui +++ b/src/citra_qt/configure_general.ui @@ -43,6 +43,26 @@ + + + + Performance + + + + + + + + Enable CPU JIT + + + + + + + + From 0fd5a2d038ec11a9b18518c02297878b3ec967e1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 2 Sep 2016 08:39:42 -0400 Subject: [PATCH 7/9] dyncom: Use VFP_FPSCR/VFP_FPEXC. --- src/core/arm/dyncom/arm_dyncom.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index ab77da965..976e81480 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -111,8 +111,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 +124,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() { From e39b43f4fd8994f522ce3d7b228240eecccbf680 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 2 Sep 2016 08:40:49 -0400 Subject: [PATCH 8/9] arm_dynarmic/arm_dyncom: Remove unnecessary "virtual" keyword. --- src/core/arm/dynarmic/arm_dynarmic.h | 2 +- src/core/arm/dyncom/arm_dyncom.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 6cae56737..58323135d 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -17,7 +17,7 @@ namespace Core { struct ThreadContext; } -class ARM_Dynarmic final : virtual public ARM_Interface { +class ARM_Dynarmic final : public ARM_Interface { public: ARM_Dynarmic(PrivilegeMode initial_mode); diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index e763abc24..cc040b174 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(); From 13926668af8a7b95bfc1a1fb8d35b5eb52653c71 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 2 Sep 2016 08:53:42 -0400 Subject: [PATCH 9/9] arm: ResetContext shouldn't be part of ARM_Interface. --- src/core/arm/arm_interface.h | 9 --------- src/core/arm/dynarmic/arm_dynarmic.cpp | 9 --------- src/core/arm/dynarmic/arm_dynarmic.h | 1 - src/core/arm/dyncom/arm_dyncom.cpp | 9 --------- src/core/arm/dyncom/arm_dyncom.h | 1 - src/core/hle/kernel/thread.cpp | 18 +++++++++++++++++- 6 files changed, 17 insertions(+), 30 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 @@ -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 index 9112917e1..0428c5681 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -130,15 +130,6 @@ void ARM_Dynarmic::ExecuteInstructions(int num_instructions) { AddTicks(num_instructions); } -void ARM_Dynarmic::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_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)); diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 58323135d..d493cabd5 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -36,7 +36,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/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 976e81480..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) { 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)); diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index cc040b174..70f71a828 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -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/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 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;