aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/arm/dyncom/arm_dyncom.cpp
diff options
context:
space:
mode:
authorGravatar bunnei <bunneidev@gmail.com>2014-09-12 18:34:51 -0400
committerGravatar bunnei <bunneidev@gmail.com>2014-10-25 14:11:39 -0400
commit53a22b84da9690865954f666694de885ccb7c286 (patch)
tree77fa8c9fb653173cc78ffd7b0110d695c3fbb772 /src/core/arm/dyncom/arm_dyncom.cpp
parentb5e65245948647b94dfd60c1288f030a76c69a83 (diff)
ARM: Integrate SkyEye faster "dyncom" interpreter.
Fixed typo (make protected member public) Added license header back in. I originally removed this because I mostly rewrote the file, but meh ARM: Fixed a type error in dyncom interpreter. ARM: Updated dyncom to use unique_ptr for internal ARM state.
Diffstat (limited to 'src/core/arm/dyncom/arm_dyncom.cpp')
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
new file mode 100644
index 00000000..7a65669e
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -0,0 +1,164 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "core/arm/skyeye_common/armcpu.h"
+#include "core/arm/skyeye_common/armemu.h"
+#include "core/arm/skyeye_common/vfp/vfp.h"
+
+#include "core/arm/dyncom/arm_dyncom.h"
+#include "core/arm/dyncom/arm_dyncom_interpreter.h"
+
+const static cpu_config_t s_arm11_cpu_info = {
+ "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
+};
+
+ARM_DynCom::ARM_DynCom() : ticks(0) {
+ state = std::unique_ptr<ARMul_State>(new ARMul_State);
+
+ ARMul_EmulateInit();
+ memset(state.get(), 0, sizeof(ARMul_State));
+
+ ARMul_NewState((ARMul_State*)state.get());
+
+ state->abort_model = 0;
+ state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
+ state->bigendSig = LOW;
+
+ ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop);
+ state->lateabtSig = LOW;
+ mmu_init(state);
+
+ // Reset the core to initial state
+ ARMul_CoProInit(state.get());
+ ARMul_Reset(state.get());
+ state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
+ state->Emulate = 3;
+
+ state->pc = state->Reg[15] = 0x00000000;
+ state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
+ state->servaddr = 0xFFFF0000;
+ state->NirqSig = HIGH;
+
+ VFPInit(state.get()); // Initialize the VFP
+
+ ARMul_EmulateInit();
+}
+
+ARM_DynCom::~ARM_DynCom() {
+}
+
+/**
+ * Set the Program Counter to an address
+ * @param addr Address to set PC to
+ */
+void ARM_DynCom::SetPC(u32 pc) {
+ state->pc = state->Reg[15] = pc;
+}
+
+/*
+ * Get the current Program Counter
+ * @return Returns current PC
+ */
+u32 ARM_DynCom::GetPC() const {
+ return state->pc;
+}
+
+/**
+ * Get an ARM register
+ * @param index Register index (0-15)
+ * @return Returns the value in the register
+ */
+u32 ARM_DynCom::GetReg(int index) const {
+ return state->Reg[index];
+}
+
+/**
+ * Set an ARM register
+ * @param index Register index (0-15)
+ * @param value Value to set register to
+ */
+void ARM_DynCom::SetReg(int index, u32 value) {
+ state->Reg[index] = value;
+}
+
+/**
+ * Get the current CPSR register
+ * @return Returns the value of the CPSR register
+ */
+u32 ARM_DynCom::GetCPSR() const {
+ return state->Cpsr;
+}
+
+/**
+ * Set the current CPSR register
+ * @param cpsr Value to set CPSR to
+ */
+void ARM_DynCom::SetCPSR(u32 cpsr) {
+ state->Cpsr = cpsr;
+}
+
+/**
+ * Returns the number of clock ticks since the last reset
+ * @return Returns number of clock ticks
+ */
+u64 ARM_DynCom::GetTicks() const {
+ return ticks;
+}
+
+/**
+ * Executes the given number of instructions
+ * @param num_instructions Number of instructions to executes
+ */
+void ARM_DynCom::ExecuteInstructions(int num_instructions) {
+ ticks += num_instructions;
+ state->NumInstrsToExecute = num_instructions;
+ InterpreterMainLoop(state.get());
+}
+
+/**
+ * Saves the current CPU context
+ * @param ctx Thread context to save
+ * @todo Do we need to save Reg[15] and NextInstr?
+ */
+void ARM_DynCom::SaveContext(ThreadContext& ctx) {
+ memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
+ memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
+
+ ctx.sp = state->Reg[13];
+ ctx.lr = state->Reg[14];
+ ctx.pc = state->pc;
+ ctx.cpsr = state->Cpsr;
+
+ ctx.fpscr = state->VFP[1];
+ ctx.fpexc = state->VFP[2];
+
+ ctx.reg_15 = state->Reg[15];
+ ctx.mode = state->NextInstr;
+}
+
+/**
+ * Loads a CPU context
+ * @param ctx Thread context to load
+ * @param Do we need to load Reg[15] and NextInstr?
+ */
+void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
+ memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
+ memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
+
+ state->Reg[13] = ctx.sp;
+ state->Reg[14] = ctx.lr;
+ state->pc = ctx.pc;
+ state->Cpsr = ctx.cpsr;
+
+ state->VFP[1] = ctx.fpscr;
+ state->VFP[2] = ctx.fpexc;
+
+ state->Reg[15] = ctx.reg_15;
+ state->NextInstr = ctx.mode;
+}
+
+/// Prepare core for thread reschedule (if needed to correctly handle state)
+void ARM_DynCom::PrepareReschedule() {
+ state->NumInstrsToExecute = 0;
+}