From 49dc2ce8ac4fc37a008fa28e0771c8c74c576b05 Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
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