citra-emu
/
citra
Archived
1
0
Fork 0

ARM_Interface: added SaveContext and LoadContext functions for HLE thread switching

This commit is contained in:
bunnei 2014-05-20 18:50:16 -04:00
parent 143bba2045
commit 49dc2ce8ac
4 changed files with 65 additions and 37 deletions

View File

@ -7,6 +7,8 @@
#include "common/common.h" #include "common/common.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/svc.h"
/// Generic ARM11 CPU interface /// Generic ARM11 CPU interface
class ARM_Interface : NonCopyable { class ARM_Interface : NonCopyable {
public: public:
@ -75,6 +77,18 @@ public:
*/ */
virtual u64 GetTicks() const = 0; 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 /// Getter for m_num_instructions
u64 GetNumInstructions() { u64 GetNumInstructions() {
return m_num_instructions; return m_num_instructions;
@ -90,6 +104,6 @@ protected:
private: private:
u64 m_num_instructions; ///< Number of instructions executed u64 m_num_instructions; ///< Number of instructions executed
}; };

View File

@ -101,3 +101,39 @@ void ARM_Interpreter::ExecuteInstructions(int num_instructions) {
m_state->NumInstrsToExecute = num_instructions; m_state->NumInstrsToExecute = num_instructions;
ARMul_Emulate32(m_state); 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;
}

View File

@ -60,6 +60,18 @@ public:
*/ */
u64 GetTicks() const; 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: protected:
/** /**

View File

@ -98,46 +98,12 @@ inline void __SetCurrentThread(Thread* t) {
/// Saves the current CPU context /// Saves the current CPU context
void __KernelSaveContext(ThreadContext& ctx) { void __KernelSaveContext(ThreadContext& ctx) {
ctx.cpu_registers[0] = Core::g_app_core->GetReg(0); Core::g_app_core->SaveContext(ctx);
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();
} }
/// Loads a CPU context /// Loads a CPU context
void __KernelLoadContext(const ThreadContext& ctx) { void __KernelLoadContext(const ThreadContext& ctx) {
Core::g_app_core->SetReg(0, ctx.cpu_registers[0]); Core::g_app_core->LoadContext(ctx);
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);
} }
/// Resets a thread /// Resets a thread