aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/arm
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/disassembler/load_symbol_map.cpp1
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h5
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp13
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp14
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp26
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp75
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp4
9 files changed, 79 insertions, 65 deletions
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp
index 13d26d17..eb20bf6f 100644
--- a/src/core/arm/disassembler/load_symbol_map.cpp
+++ b/src/core/arm/disassembler/load_symbol_map.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <sstream>
#include <string>
#include <vector>
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 2488c879..cc935572 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -10,6 +10,11 @@
#include "core/arm/arm_interface.h"
#include "core/arm/skyeye_common/armdefs.h"
+#include "core/arm/skyeye_common/arm_regformat.h"
+
+namespace Core {
+struct ThreadContext;
+}
class ARM_DynCom final : virtual public ARM_Interface {
public:
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index b00eb49a..785f3956 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -4144,11 +4144,13 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
bx_inst* const inst_cream = (bx_inst*)inst_base->component;
+ u32 address = RM;
+
if (inst_cream->Rm == 15)
- LOG_WARNING(Core_ARM11, "BX at pc %x: use of Rm = R15 is discouraged", cpu->Reg[15]);
+ address += 2 * GET_INST_SIZE(cpu);
- cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1;
- cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe;
+ cpu->TFlag = address & 1;
+ cpu->Reg[15] = address & 0xfffffffe;
INC_PC(sizeof(bx_inst));
goto DISPATCH;
}
@@ -5695,7 +5697,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF);
const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16);
- RD = (result & (0xFFFFFFFFFFFFFFFFLL >> 15)) >> 16;
+ RD = BITS(result, 16, 47);
if ((result >> 16) != (s32)RD)
cpu->Cpsr |= (1 << 27);
@@ -6246,7 +6248,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
SWI_INST:
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
- SVC::CallSVC(Memory::Read32(cpu->Reg[15]));
+ swi_inst* const inst_cream = (swi_inst*)inst_base->component;
+ SVC::CallSVC(inst_cream->num & 0xFFFF);
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index 3e79c44c..f10a5b70 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -130,14 +130,13 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
}
} else {
ARMword Rd = ((tinstr & 0x0007) >> 0);
- ARMword Rs = ((tinstr & 0x0038) >> 3);
+ ARMword Rs = ((tinstr & 0x0078) >> 3);
if (tinstr & (1 << 7))
Rd += 8;
- if (tinstr & (1 << 6))
- Rs += 8;
switch ((tinstr & 0x03C0) >> 6) {
+ case 0x0: // ADD Rd,Rd,Rs
case 0x1: // ADD Rd,Rd,Hs
case 0x2: // ADD Hd,Hd,Rs
case 0x3: // ADD Hd,Hd,Hs
@@ -146,19 +145,19 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
|(Rd << 12) // Rd
|(Rs << 0); // Rm
break;
+ case 0x4: // CMP Rd,Rs
case 0x5: // CMP Rd,Hs
case 0x6: // CMP Hd,Rs
case 0x7: // CMP Hd,Hs
*ainstr = 0xE1500000 // base
| (Rd << 16) // Rn
- |(Rd << 12) // Rd
|(Rs << 0); // Rm
break;
+ case 0x8: // MOV Rd,Rs
case 0x9: // MOV Rd,Hs
case 0xA: // MOV Hd,Rs
case 0xB: // MOV Hd,Hs
*ainstr = 0xE1A00000 // base
- | (Rd << 16) // Rn
|(Rd << 12) // Rd
|(Rs << 0); // Rm
break;
@@ -167,11 +166,6 @@ tdstate thumb_translate(u32 addr, u32 instr, u32* ainstr, u32* inst_size) {
*ainstr = 0xE12FFF10 // base
| ((tinstr & 0x0078) >> 3); // Rd
break;
- case 0x0: // UNDEFINED
- case 0x4: // UNDEFINED
- case 0x8: // UNDEFINED
- valid = t_undefined;
- break;
case 0xE: // BLX
case 0xF: // BLX
*ainstr = 0xE1200030 // base
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index a92effbb..d1c72180 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -59,6 +59,8 @@ enum {
VFP_FPSID,
VFP_FPSCR,
VFP_FPEXC,
+ VFP_FPINST,
+ VFP_FPINST2,
VFP_MVFR0,
VFP_MVFR1,
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index 571d6c2f..1ffc1f9a 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -20,36 +20,27 @@
/* Note: this file handles interface with arm core and vfp registers */
+#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/vfp/asm_vfp.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
-unsigned VFPInit(ARMul_State* state)
+void VFPInit(ARMul_State* state)
{
state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
state->VFP[VFP_FPEXC] = 0;
state->VFP[VFP_FPSCR] = 0;
+ // ARM11 MPCore instruction register reset values.
+ state->VFP[VFP_FPINST] = 0xEE000A00;
+ state->VFP[VFP_FPINST2] = 0;
+
// ARM11 MPCore feature register values.
state->VFP[VFP_MVFR0] = 0x11111111;
state->VFP[VFP_MVFR1] = 0;
-
- return 0;
-}
-
-void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
-{
- if (reg == 1)
- {
- state->VFP[VFP_FPSCR] = state->Reg[Rt];
- }
- else if (reg == 8)
- {
- state->VFP[VFP_FPEXC] = state->Reg[Rt];
- }
}
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
@@ -153,9 +144,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x\n", exceptions);
if (exceptions == VFP_EXCEPTION_ERROR) {
- LOG_TRACE(Core_ARM11, "unhandled bounce %x\n", inst);
- exit(-1);
- return;
+ LOG_CRITICAL(Core_ARM11, "unhandled bounce %x\n", inst);
+ Crash();
}
/*
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index acefae9b..80ca93cc 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -26,7 +26,7 @@
#define CHECK_VFP_ENABLED
#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]);
-unsigned VFPInit(ARMul_State* state);
+void VFPInit(ARMul_State* state);
s32 vfp_get_float(ARMul_State* state, u32 reg);
void vfp_put_float(ARMul_State* state, s32 val, u32 reg);
@@ -36,10 +36,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
-void VMSR(ARMul_State* state, ARMword reg, ARMword Rt);
void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value);
void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2);
void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm);
-
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 67fe63aa..8efcbab1 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -995,7 +995,7 @@ VMOVBRS_INST:
#ifdef VFP_INTERPRETER_STRUCT
struct vmsr_inst {
unsigned int reg;
- unsigned int Rd;
+ unsigned int Rt;
};
#endif
#ifdef VFP_INTERPRETER_TRANS
@@ -1009,7 +1009,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
inst_base->br = NON_BRANCH;
inst_cream->reg = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rt = BITS(inst, 12, 15);
return inst_base;
}
@@ -1017,15 +1017,30 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMSR_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
/* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
and in privileged mode */
/* Exceptions must be checked, according to v7 ref manual */
CHECK_VFP_ENABLED;
- vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component;
+ vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component;
+
+ unsigned int reg = inst_cream->reg;
+ unsigned int rt = inst_cream->Rt;
- VMSR(cpu, inst_cream->reg, inst_cream->Rd);
+ if (reg == 1)
+ {
+ cpu->VFP[VFP_FPSCR] = cpu->Reg[rt];
+ }
+ else if (InAPrivilegedMode(cpu))
+ {
+ if (reg == 8)
+ cpu->VFP[VFP_FPEXC] = cpu->Reg[rt];
+ else if (reg == 9)
+ cpu->VFP[VFP_FPINST] = cpu->Reg[rt];
+ else if (reg == 10)
+ cpu->VFP[VFP_FPINST2] = cpu->Reg[rt];
+ }
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
INC_PC(sizeof(vmsr_inst));
@@ -1111,19 +1126,22 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index)
#ifdef VFP_INTERPRETER_IMPL
VMRS_INST:
{
- if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
/* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
and in privileged mode */
/* Exceptions must be checked, according to v7 ref manual */
CHECK_VFP_ENABLED;
- vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component;
+ vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component;
- if (inst_cream->reg == 1) /* FPSCR */
+ unsigned int reg = inst_cream->reg;
+ unsigned int rt = inst_cream->Rt;
+
+ if (reg == 1) // FPSCR
{
- if (inst_cream->Rt != 15)
+ if (rt != 15)
{
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSCR];
+ cpu->Reg[rt] = cpu->VFP[VFP_FPSCR];
}
else
{
@@ -1133,25 +1151,26 @@ VMRS_INST:
cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1;
}
}
- else
+ else if (reg == 0)
{
- switch (inst_cream->reg)
- {
- case 0:
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPSID];
- break;
- case 6:
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR1];
- break;
- case 7:
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_MVFR0];
- break;
- case 8:
- cpu->Reg[inst_cream->Rt] = cpu->VFP[VFP_FPEXC];
- break;
- default:
- break;
- }
+ cpu->Reg[rt] = cpu->VFP[VFP_FPSID];
+ }
+ else if (reg == 6)
+ {
+ cpu->Reg[rt] = cpu->VFP[VFP_MVFR1];
+ }
+ else if (reg == 7)
+ {
+ cpu->Reg[rt] = cpu->VFP[VFP_MVFR0];
+ }
+ else if (InAPrivilegedMode(cpu))
+ {
+ if (reg == 8)
+ cpu->Reg[rt] = cpu->VFP[VFP_FPEXC];
+ else if (reg == 9)
+ cpu->Reg[rt] = cpu->VFP[VFP_FPINST];
+ else if (reg == 10)
+ cpu->Reg[rt] = cpu->VFP[VFP_FPINST2];
}
}
cpu->Reg[15] += GET_INST_SIZE(cpu);
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 5a655a6f..e5d33925 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -53,6 +53,8 @@
#include <cinttypes>
+#include "common/common_funcs.h"
+#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/arm/skyeye_common/vfp/vfp_helper.h"
@@ -1246,7 +1248,7 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
if (!fop->fn) {
LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), inst, state->Reg[15]);
- exit(-1);
+ Crash();
goto invalid;
}