From 49dc2ce8ac4fc37a008fa28e0771c8c74c576b05 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 20 May 2014 18:50:16 -0400 Subject: [PATCH] ARM_Interface: added SaveContext and LoadContext functions for HLE thread switching --- src/core/arm/arm_interface.h | 16 ++++++++- src/core/arm/interpreter/arm_interpreter.cpp | 36 +++++++++++++++++++ src/core/arm/interpreter/arm_interpreter.h | 12 +++++++ src/core/hle/kernel/thread.cpp | 38 ++------------------ 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 5c382ebbd..52bc82115 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -7,6 +7,8 @@ #include "common/common.h" #include "common/common_types.h" +#include "core/hle/svc.h" + /// Generic ARM11 CPU interface class ARM_Interface : NonCopyable { public: @@ -75,6 +77,18 @@ public: */ virtual u64 GetTicks() const = 0; + /** + * Saves the current CPU context + * @param ctx Thread context to save + */ + virtual void SaveContext(ThreadContext& ctx) = 0; + + /** + * Loads a CPU context + * @param ctx Thread context to load + */ + virtual void LoadContext(const ThreadContext& ctx) = 0; + /// Getter for m_num_instructions u64 GetNumInstructions() { return m_num_instructions; @@ -90,6 +104,6 @@ protected: private: - u64 m_num_instructions; ///< Number of instructions executed + u64 m_num_instructions; ///< Number of instructions executed }; diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index c21ff0464..b8c46cdfc 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp @@ -101,3 +101,39 @@ void ARM_Interpreter::ExecuteInstructions(int num_instructions) { m_state->NumInstrsToExecute = num_instructions; ARMul_Emulate32(m_state); } + +/** + * Saves the current CPU context + * @param ctx Thread context to save + * @todo Do we need to save Reg[15] and NextInstr? + */ +void ARM_Interpreter::SaveContext(ThreadContext& ctx) { + memcpy(ctx.cpu_registers, m_state->Reg, sizeof(ctx.cpu_registers)); + memcpy(ctx.fpu_registers, m_state->ExtReg, sizeof(ctx.fpu_registers)); + + ctx.sp = m_state->Reg[13]; + ctx.lr = m_state->Reg[14]; + ctx.pc = m_state->pc; + ctx.cpsr = m_state->Cpsr; + + ctx.fpscr = m_state->VFP[1]; + ctx.fpexc = m_state->VFP[2]; +} + +/** + * Loads a CPU context + * @param ctx Thread context to load + * @param Do we need to load Reg[15] and NextInstr? + */ +void ARM_Interpreter::LoadContext(const ThreadContext& ctx) { + memcpy(m_state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); + memcpy(m_state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); + + m_state->Reg[13] = ctx.sp; + m_state->Reg[14] = ctx.lr; + m_state->pc = ctx.pc; + m_state->Cpsr = ctx.cpsr; + + m_state->VFP[1] = ctx.fpscr; + m_state->VFP[2] = ctx.fpexc; +} diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h index 474ba3e45..15240568c 100644 --- a/src/core/arm/interpreter/arm_interpreter.h +++ b/src/core/arm/interpreter/arm_interpreter.h @@ -60,6 +60,18 @@ public: */ u64 GetTicks() const; + /** + * Saves the current CPU context + * @param ctx Thread context to save + */ + void SaveContext(ThreadContext& ctx); + + /** + * Loads a CPU context + * @param ctx Thread context to load + */ + void LoadContext(const ThreadContext& ctx); + protected: /** diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 136fff021..b3d306c53 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -98,46 +98,12 @@ inline void __SetCurrentThread(Thread* t) { /// Saves the current CPU context void __KernelSaveContext(ThreadContext& ctx) { - ctx.cpu_registers[0] = Core::g_app_core->GetReg(0); - ctx.cpu_registers[1] = Core::g_app_core->GetReg(1); - ctx.cpu_registers[2] = Core::g_app_core->GetReg(2); - ctx.cpu_registers[3] = Core::g_app_core->GetReg(3); - ctx.cpu_registers[4] = Core::g_app_core->GetReg(4); - ctx.cpu_registers[5] = Core::g_app_core->GetReg(5); - ctx.cpu_registers[6] = Core::g_app_core->GetReg(6); - ctx.cpu_registers[7] = Core::g_app_core->GetReg(7); - ctx.cpu_registers[8] = Core::g_app_core->GetReg(8); - ctx.cpu_registers[9] = Core::g_app_core->GetReg(9); - ctx.cpu_registers[10] = Core::g_app_core->GetReg(10); - ctx.cpu_registers[11] = Core::g_app_core->GetReg(11); - ctx.cpu_registers[12] = Core::g_app_core->GetReg(12); - ctx.sp = Core::g_app_core->GetReg(13); - ctx.lr = Core::g_app_core->GetReg(14); - ctx.pc = Core::g_app_core->GetPC(); - ctx.cpsr = Core::g_app_core->GetCPSR(); + Core::g_app_core->SaveContext(ctx); } /// Loads a CPU context void __KernelLoadContext(const ThreadContext& ctx) { - Core::g_app_core->SetReg(0, ctx.cpu_registers[0]); - Core::g_app_core->SetReg(1, ctx.cpu_registers[1]); - Core::g_app_core->SetReg(2, ctx.cpu_registers[2]); - Core::g_app_core->SetReg(3, ctx.cpu_registers[3]); - Core::g_app_core->SetReg(4, ctx.cpu_registers[4]); - Core::g_app_core->SetReg(5, ctx.cpu_registers[5]); - Core::g_app_core->SetReg(6, ctx.cpu_registers[6]); - Core::g_app_core->SetReg(7, ctx.cpu_registers[7]); - Core::g_app_core->SetReg(8, ctx.cpu_registers[8]); - Core::g_app_core->SetReg(9, ctx.cpu_registers[9]); - Core::g_app_core->SetReg(10, ctx.cpu_registers[10]); - Core::g_app_core->SetReg(11, ctx.cpu_registers[11]); - Core::g_app_core->SetReg(12, ctx.cpu_registers[12]); - Core::g_app_core->SetReg(13, ctx.sp); - Core::g_app_core->SetReg(14, ctx.lr); - //Core::g_app_core->SetReg(15, ctx.pc); - - Core::g_app_core->SetPC(ctx.pc); - Core::g_app_core->SetCPSR(ctx.cpsr); + Core::g_app_core->LoadContext(ctx); } /// Resets a thread