From 32a6379bc883a18124fbb5027a87738881f7a011 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 29 Jun 2015 03:04:40 -0400 Subject: vfp: Handle accesses to FPINST/FPINST2 system registers Also has a side-benefit of correcting access to the FPEXC register. --- src/core/arm/skyeye_common/arm_regformat.h | 2 + src/core/arm/skyeye_common/vfp/vfp.cpp | 16 ++---- src/core/arm/skyeye_common/vfp/vfp.h | 2 - src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 75 ++++++++++++++++++----------- 4 files changed, 53 insertions(+), 42 deletions(-) (limited to 'src/core/arm') 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); -- cgit v1.2.3