diff options
author | Lioncash <mathew1800@gmail.com> | 2015-04-18 02:44:54 +0200 |
---|---|---|
committer | Lioncash <mathew1800@gmail.com> | 2015-04-18 02:46:05 +0200 |
commit | d66a12c6f6e612ba4574652a8087cd878c965b92 (patch) | |
tree | 7a2c560bfe158c4c749cfcfb1a9bfea9d8e53082 /src/core/arm/skyeye_common/vfp/vfp.cpp | |
parent | Merge pull request #696 from yuriks/interface-deinline (diff) | |
download | yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.tar yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.tar.gz yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.tar.bz2 yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.tar.lz yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.tar.xz yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.tar.zst yuzu-d66a12c6f6e612ba4574652a8087cd878c965b92.zip |
Diffstat (limited to 'src/core/arm/skyeye_common/vfp/vfp.cpp')
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.cpp | 621 |
1 files changed, 6 insertions, 615 deletions
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index d793261fd..d0fa157a2 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp @@ -37,296 +37,18 @@ unsigned VFPInit(ARMul_State* state) return 0; } -unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value) -{ - /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int OPC_1 = BITS(instr, 21, 23); - int Rt = BITS(instr, 12, 15); - int CRn = BITS(instr, 16, 19); - int CRm = BITS(instr, 0, 3); - int OPC_2 = BITS(instr, 5, 7); - - /* TODO check access permission */ - - /* CRn/opc1 CRm/opc2 */ - - if (CoProc == 10 || CoProc == 11) - { - if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0) - { - /* VMOV r to s */ - /* Transfering Rt is not mandatory, as the value of interest is pointed by value */ - VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value); - return ARMul_DONE; - } - - if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0) - { - VMRS(state, CRn, Rt, value); - return ARMul_DONE; - } - } - LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", - instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); - - return ARMul_CANT; -} - -unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value) -{ - /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int OPC_1 = BITS(instr, 21, 23); - int Rt = BITS(instr, 12, 15); - int CRn = BITS(instr, 16, 19); - int CRm = BITS(instr, 0, 3); - int OPC_2 = BITS(instr, 5, 7); - - /* TODO check access permission */ - - /* CRn/opc1 CRm/opc2 */ - if (CoProc == 10 || CoProc == 11) - { - if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0) - { - /* VMOV s to r */ - /* Transfering Rt is not mandatory, as the value of interest is pointed by value */ - VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value); - return ARMul_DONE; - } - - if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0) - { - VMSR(state, CRn, Rt); - return ARMul_DONE; - } - - if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0) - { - VFP_DEBUG_UNIMPLEMENTED(VMOVBRC); - return ARMul_DONE; - } - - if (CoProc == 11 && CRm == 0) - { - VFP_DEBUG_UNIMPLEMENTED(VMOVBCR); - return ARMul_DONE; - } - } - LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", - instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); - - return ARMul_CANT; -} - -unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2) -{ - /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int OPC_1 = BITS(instr, 4, 7); - int Rt = BITS(instr, 12, 15); - int Rt2 = BITS(instr, 16, 19); - int CRm = BITS(instr, 0, 3); - - if (CoProc == 10 || CoProc == 11) - { - if (CoProc == 10 && (OPC_1 & 0xD) == 1) - { - VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2); - return ARMul_DONE; - } - - if (CoProc == 11 && (OPC_1 & 0xD) == 1) - { - /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */ - VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2); - return ARMul_DONE; - } - } - LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", - instr, CoProc, OPC_1, Rt, Rt2, CRm); - - return ARMul_CANT; -} - -unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2) -{ - /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int OPC_1 = BITS(instr, 4, 7); - int Rt = BITS(instr, 12, 15); - int Rt2 = BITS(instr, 16, 19); - int CRm = BITS(instr, 0, 3); - - /* TODO check access permission */ - - /* CRn/opc1 CRm/opc2 */ - - if (CoProc == 11 || CoProc == 10) - { - if (CoProc == 10 && (OPC_1 & 0xD) == 1) - { - VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2); - return ARMul_DONE; - } - - if (CoProc == 11 && (OPC_1 & 0xD) == 1) - { - /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */ - VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2); - return ARMul_DONE; - } - } - LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", - instr, CoProc, OPC_1, Rt, Rt2, CRm); - - return ARMul_CANT; -} - -unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value) -{ - /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int CRd = BITS(instr, 12, 15); - int Rn = BITS(instr, 16, 19); - int imm8 = BITS(instr, 0, 7); - int P = BIT(instr, 24); - int U = BIT(instr, 23); - int D = BIT(instr, 22); - int W = BIT(instr, 21); - - /* TODO check access permission */ - - /* VSTM */ - if ( (P|U|D|W) == 0 ) { - LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__); - exit(-1); - } - if (CoProc == 10 || CoProc == 11) { -#if 1 - if (P == 0 && U == 0 && W == 0) { - LOG_ERROR(Core_ARM11, "VSTM Related encodings\n"); - exit(-1); - } - if (P == U && W == 1) { - LOG_ERROR(Core_ARM11, "UNDEFINED\n"); - exit(-1); - } -#endif - - if (P == 1 && W == 0) - { - return VSTR(state, type, instr, value); - } - - if (P == 1 && U == 0 && W == 1 && Rn == 0xD) - { - return VPUSH(state, type, instr, value); - } - - return VSTM(state, type, instr, value); - } - LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", - instr, CoProc, CRd, Rn, imm8, P, U, D, W); - - return ARMul_CANT; -} - -unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value) +void VMSR(ARMul_State* state, ARMword reg, ARMword Rt) { - /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int CRd = BITS(instr, 12, 15); - int Rn = BITS(instr, 16, 19); - int imm8 = BITS(instr, 0, 7); - int P = BIT(instr, 24); - int U = BIT(instr, 23); - int D = BIT(instr, 22); - int W = BIT(instr, 21); - - /* TODO check access permission */ - - if ( (P|U|D|W) == 0 ) { - LOG_ERROR(Core_ARM11, "In %s, UNDEFINED\n", __FUNCTION__); - exit(-1); - } - if (CoProc == 10 || CoProc == 11) + if (reg == 1) { - if (P == 1 && W == 0) - { - return VLDR(state, type, instr, value); - } - - if (P == 0 && U == 1 && W == 1 && Rn == 0xD) - { - return VPOP(state, type, instr, value); - } - - return VLDM(state, type, instr, value); + state->VFP[VFP_FPSCR] = state->Reg[Rt]; } - LOG_WARNING(Core_ARM11, "Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", - instr, CoProc, CRd, Rn, imm8, P, U, D, W); - - return ARMul_CANT; -} - -unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr) -{ - /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ - int CoProc = BITS(instr, 8, 11); /* 10 or 11 */ - int OPC_1 = BITS(instr, 20, 23); - int CRd = BITS(instr, 12, 15); - int CRn = BITS(instr, 16, 19); - int CRm = BITS(instr, 0, 3); - int OPC_2 = BITS(instr, 5, 7); - - /* TODO check access permission */ - - /* CRn/opc1 CRm/opc2 */ - - if (CoProc == 10 || CoProc == 11) + else if (reg == 8) { - if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0) - { - unsigned int single = BIT(instr, 8) == 0; - unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4); - unsigned int imm; - instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm - - if (single) - imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19; - else - imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16; - - VMOVI(state, single, d, imm); - return ARMul_DONE; - } - - if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2) - { - unsigned int single = BIT(instr, 8) == 0; - unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4); - unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4); - VMOVR(state, single, d, m); - return ARMul_DONE; - } - - int exceptions = 0; - if (CoProc == 10) - exceptions = vfp_single_cpdo(state, instr, state->VFP[VFP_FPSCR]); - else - exceptions = vfp_double_cpdo(state, instr, state->VFP[VFP_FPSCR]); - - vfp_raise_exceptions(state, exceptions, instr, state->VFP[VFP_FPSCR]); - - return ARMul_DONE; + state->VFP[VFP_FPEXC] = state->Reg[Rt]; } - LOG_WARNING(Core_ARM11, "Can't identify %x\n", instr); - return ARMul_CANT; } -/* ----------- MRC ------------ */ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) { if (to_arm) @@ -338,43 +60,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* state->ExtReg[n] = *value; } } -void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value) -{ - if (reg == 1) - { - if (Rt != 15) - { - *value = state->VFP[VFP_FPSCR]; - } - else - { - *value = state->VFP[VFP_FPSCR] ; - } - } - else - { - switch (reg) - { - case 0: - *value = state->VFP[VFP_FPSID]; - break; - case 6: - /* MVFR1, VFPv3 only ? */ - LOG_TRACE(Core_ARM11, "\tr%d <= MVFR1 unimplemented\n", Rt); - break; - case 7: - /* MVFR0, VFPv3 only? */ - LOG_TRACE(Core_ARM11, "\tr%d <= MVFR0 unimplemented\n", Rt); - break; - case 8: - *value = state->VFP[VFP_FPEXC]; - break; - default: - LOG_TRACE(Core_ARM11, "\tSUBARCHITECTURE DEFINED\n"); - break; - } - } -} + void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) { if (to_arm) @@ -402,301 +88,6 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor } } -/* ----------- MCR ------------ */ -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]; - } -} - -/* Memory operation are not inlined, as old Interpreter and Fast interpreter - don't have the same memory operation interface. - Old interpreter framework does one access to coprocessor per data, and - handles already data write, as well as address computation, - which is not the case for Fast interpreter. Therefore, implementation - of vfp instructions in old interpreter and fast interpreter are separate. */ - -/* ----------- STC ------------ */ -int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value) -{ - static int i = 0; - static int single_reg, add, d, n, imm32, regs; - if (type == ARMul_FIRST) - { - single_reg = BIT(instr, 8) == 0; // Double precision - add = BIT(instr, 23); - imm32 = BITS(instr, 0,7)<<2; // may not be used - d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */ - n = BITS(instr, 16, 19); // destination register - - i = 0; - regs = 1; - - return ARMul_DONE; - } - else if (type == ARMul_DATA) - { - if (single_reg) - { - *value = state->ExtReg[d+i]; - i++; - if (i < regs) - return ARMul_INC; - else - return ARMul_DONE; - } - else - { - /* FIXME Careful of endianness, may need to rework this */ - *value = state->ExtReg[d*2+i]; - i++; - if (i < regs*2) - return ARMul_INC; - else - return ARMul_DONE; - } - } - - return -1; -} -int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value) -{ - static int i = 0; - static int single_regs, d, imm32, regs; - if (type == ARMul_FIRST) - { - single_regs = BIT(instr, 8) == 0; // Single precision - d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register - imm32 = BITS(instr, 0,7)<<2; // may not be used - regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd - - state->Reg[R13] = state->Reg[R13] - imm32; - - i = 0; - - return ARMul_DONE; - } - else if (type == ARMul_DATA) - { - if (single_regs) - { - *value = state->ExtReg[d + i]; - i++; - if (i < regs) - return ARMul_INC; - else - return ARMul_DONE; - } - else - { - /* FIXME Careful of endianness, may need to rework this */ - *value = state->ExtReg[d*2 + i]; - i++; - if (i < regs*2) - return ARMul_INC; - else - return ARMul_DONE; - } - } - - return -1; -} -int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value) -{ - static int i = 0; - static int single_regs, add, wback, d, n, imm32, regs; - if (type == ARMul_FIRST) - { - single_regs = BIT(instr, 8) == 0; // Single precision - add = BIT(instr, 23); - wback = BIT(instr, 21); // write-back - d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register - n = BITS(instr, 16, 19); // destination register - imm32 = BITS(instr, 0,7) * 4; // may not be used - regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd - - if (wback) { - state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32); - } - - i = 0; - - return ARMul_DONE; - } - else if (type == ARMul_DATA) - { - if (single_regs) - { - *value = state->ExtReg[d + i]; - i++; - if (i < regs) - return ARMul_INC; - else - return ARMul_DONE; - } - else - { - /* FIXME Careful of endianness, may need to rework this */ - *value = state->ExtReg[d*2 + i]; - i++; - if (i < regs*2) - return ARMul_INC; - else - return ARMul_DONE; - } - } - - return -1; -} - -/* ----------- LDC ------------ */ -int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value) -{ - static int i = 0; - static int single_regs, d, imm32, regs; - if (type == ARMul_FIRST) - { - single_regs = BIT(instr, 8) == 0; // Single precision - d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register - imm32 = BITS(instr, 0, 7)<<2; // may not be used - regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd - - state->Reg[R13] = state->Reg[R13] + imm32; - - i = 0; - - return ARMul_DONE; - } - else if (type == ARMul_TRANSFER) - { - return ARMul_DONE; - } - else if (type == ARMul_DATA) - { - if (single_regs) - { - state->ExtReg[d + i] = value; - i++; - if (i < regs) - return ARMul_INC; - else - return ARMul_DONE; - } - else - { - /* FIXME Careful of endianness, may need to rework this */ - state->ExtReg[d*2 + i] = value; - i++; - if (i < regs*2) - return ARMul_INC; - else - return ARMul_DONE; - } - } - - return -1; -} -int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value) -{ - static int i = 0; - static int single_reg, add, d, n, imm32, regs; - if (type == ARMul_FIRST) - { - single_reg = BIT(instr, 8) == 0; // Double precision - add = BIT(instr, 23); - imm32 = BITS(instr, 0, 7)<<2; // may not be used - d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register - n = BITS(instr, 16, 19); // destination register - - i = 0; - regs = 1; - - return ARMul_DONE; - } - else if (type == ARMul_TRANSFER) - { - return ARMul_DONE; - } - else if (type == ARMul_DATA) - { - if (single_reg) - { - state->ExtReg[d+i] = value; - i++; - if (i < regs) - return ARMul_INC; - else - return ARMul_DONE; - } - else - { - /* FIXME Careful of endianness, may need to rework this */ - state->ExtReg[d*2+i] = value; - i++; - if (i < regs*2) - return ARMul_INC; - else - return ARMul_DONE; - } - } - - return -1; -} -int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value) -{ - static int i = 0; - static int single_regs, add, wback, d, n, imm32, regs; - if (type == ARMul_FIRST) - { - single_regs = BIT(instr, 8) == 0; // Single precision - add = BIT(instr, 23); - wback = BIT(instr, 21); // write-back - d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register - n = BITS(instr, 16, 19); // destination register - imm32 = BITS(instr, 0, 7) * 4; // may not be used - regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd - - if (wback) { - state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32); - } - - i = 0; - - return ARMul_DONE; - } - else if (type == ARMul_DATA) - { - if (single_regs) - { - state->ExtReg[d + i] = value; - i++; - if (i < regs) - return ARMul_INC; - else - return ARMul_DONE; - } - else - { - /* FIXME Careful of endianness, may need to rework this */ - state->ExtReg[d*2 + i] = value; - i++; - if (i < regs*2) - return ARMul_INC; - else - return ARMul_DONE; - } - } - - return -1; -} - -/* ----------- CDP ------------ */ void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) { if (single) |