aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/arm
diff options
context:
space:
mode:
authorGravatar Lioncash <mathew1800@gmail.com>2015-06-29 03:04:40 -0400
committerGravatar Lioncash <mathew1800@gmail.com>2015-06-29 03:27:26 -0400
commit32a6379bc883a18124fbb5027a87738881f7a011 (patch)
tree12f2ace4e6bd90c826f646fb12a44ccd3d099574 /src/core/arm
parent19d5fbce8e9a5419b5cbae610bbf18de82d87f2c (diff)
vfp: Handle accesses to FPINST/FPINST2 system registers
Also has a side-benefit of correcting access to the FPEXC register.
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp16
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp75
4 files changed, 53 insertions, 42 deletions
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..f40cf595 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -33,6 +33,10 @@ unsigned VFPInit(ARMul_State* state)
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;
@@ -40,18 +44,6 @@ unsigned VFPInit(ARMul_State* state)
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)
{
if (to_arm)
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index acefae9b..eb376561 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -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);