diff options
Diffstat (limited to 'src/core/arm')
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 94 | ||||
-rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 89 | ||||
-rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 5 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 2 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armemu.h | 7 |
5 files changed, 165 insertions, 32 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index ae407585e..460001b1a 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -2390,15 +2390,41 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) return inst_base; } ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD16"); } ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD8"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADDSUBX"); } +ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) +{ + arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->op1 = BITS(inst, 20, 21); + inst_cream->op2 = BITS(inst, 5, 7); + + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd16)(inst, index); +} ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); } ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); } ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB16"); } ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB8"); } -ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUBADDX"); } +ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd16)(inst, index); +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) +{ + return INTERPRETER_TRANSLATE(qadd16)(inst, index); +} ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) { arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); @@ -5561,15 +5587,69 @@ unsigned InterpreterMainLoop(ARMul_State* state) GOTO_NEXT_INST; } QADD_INST: - QADD16_INST: QADD8_INST: + + QADD16_INST: QADDSUBX_INST: + QSUB16_INST: + QSUBADDX_INST: + { + INC_ICOUNTER; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; + const s16 rm_lo = (RM & 0xFFFF); + const s16 rm_hi = ((RM >> 16) & 0xFFFF); + const s16 rn_lo = (RN & 0xFFFF); + const s16 rn_hi = ((RN >> 16) & 0xFFFF); + const u8 op2 = inst_cream->op2; + + s32 lo_result = 0; + s32 hi_result = 0; + + // QADD16 + if (op2 == 0x00) { + lo_result = (rn_lo + rm_lo); + hi_result = (rn_hi + rm_hi); + } + // QASX + else if (op2 == 0x01) { + lo_result = (rn_lo - rm_hi); + hi_result = (rn_hi + rm_lo); + } + // QSAX + else if (op2 == 0x02) { + lo_result = (rn_lo + rm_hi); + hi_result = (rn_hi - rm_lo); + } + // QSUB16 + else if (op2 == 0x03) { + lo_result = (rn_lo - rm_lo); + hi_result = (rn_hi - rm_hi); + } + + if (lo_result > 0x7FFF) + lo_result = 0x7FFF; + else if (lo_result < -0x8000) + lo_result = -0x8000; + + if (hi_result > 0x7FFF) + hi_result = 0x7FFF; + else if (hi_result < -0x8000) + hi_result = -0x8000; + + RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); + } + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(generic_arm_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + QDADD_INST: QDSUB_INST: QSUB_INST: - QSUB16_INST: QSUB8_INST: - QSUBADDX_INST: REV_INST: { INC_ICOUNTER; diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index db9d12797..578d71380 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -5877,6 +5877,8 @@ L_stm_s_takeabort: state->Cpsr &= ~(1 << 18); state->Cpsr &= ~(1 << 19); } + + ARMul_CPSRAltered(state); return 1; } // SADD8/SSUB8 @@ -5948,6 +5950,7 @@ L_stm_s_takeabort: state->Cpsr &= ~(1 << 19); } + ARMul_CPSRAltered(state); state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24); return 1; } @@ -6024,15 +6027,33 @@ L_stm_s_takeabort: if ((instr & 0x0F0) == 0x070) { // USUB16 h1 = ((u16)from - (u16)to); h2 = ((u16)(from >> 16) - (u16)(to >> 16)); - if (!(h1 & 0xffff0000)) state->Cpsr |= (3 << 16); - if (!(h2 & 0xffff0000)) state->Cpsr |= (3 << 18); + + if (!(h1 & 0xffff0000)) + state->Cpsr |= (3 << 16); + else + state->Cpsr &= ~(3 << 16); + + if (!(h2 & 0xffff0000)) + state->Cpsr |= (3 << 18); + else + state->Cpsr &= ~(3 << 18); } else { // UADD16 h1 = ((u16)from + (u16)to); h2 = ((u16)(from >> 16) + (u16)(to >> 16)); - if (h1 & 0xffff0000) state->Cpsr |= (3 << 16); - if (h2 & 0xffff0000) state->Cpsr |= (3 << 18); + + if (h1 & 0xffff0000) + state->Cpsr |= (3 << 16); + else + state->Cpsr &= ~(3 << 16); + + if (h2 & 0xffff0000) + state->Cpsr |= (3 << 18); + else + state->Cpsr &= ~(3 << 18); } + + ARMul_CPSRAltered(state); state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16)); return 1; } @@ -6045,10 +6066,26 @@ L_stm_s_takeabort: b2 = ((u8)(from >> 8) - (u8)(to >> 8)); b3 = ((u8)(from >> 16) - (u8)(to >> 16)); b4 = ((u8)(from >> 24) - (u8)(to >> 24)); - if (!(b1 & 0xffffff00)) state->Cpsr |= (1 << 16); - if (!(b2 & 0xffffff00)) state->Cpsr |= (1 << 17); - if (!(b3 & 0xffffff00)) state->Cpsr |= (1 << 18); - if (!(b4 & 0xffffff00)) state->Cpsr |= (1 << 19); + + if (!(b1 & 0xffffff00)) + state->Cpsr |= (1 << 16); + else + state->Cpsr &= ~(1 << 16); + + if (!(b2 & 0xffffff00)) + state->Cpsr |= (1 << 17); + else + state->Cpsr &= ~(1 << 17); + + if (!(b3 & 0xffffff00)) + state->Cpsr |= (1 << 18); + else + state->Cpsr &= ~(1 << 18); + + if (!(b4 & 0xffffff00)) + state->Cpsr |= (1 << 19); + else + state->Cpsr &= ~(1 << 19); } else { // UADD8 b1 = ((u8)from + (u8)to); @@ -6071,13 +6108,13 @@ L_stm_s_takeabort: else state->Cpsr &= ~(1 << 18); - if (b4 & 0xffffff00) state->Cpsr |= (1 << 19); else state->Cpsr &= ~(1 << 19); } + ARMul_CPSRAltered(state); state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); return 1; } @@ -6116,7 +6153,7 @@ L_stm_s_takeabort: u32 rm = (instr >> 0) & 0xF; u32 from = state->Reg[rn]; u32 to = state->Reg[rm]; - u32 cpsr = state->Cpsr; + u32 cpsr = ARMul_GetCPSR(state); if ((instr & 0xFF0) == 0xFB0) { // SEL u32 result; if (cpsr & (1 << 16)) @@ -6172,16 +6209,23 @@ L_stm_s_takeabort: s16 rn_lo = (state->Reg[rn_idx]); s16 rn_hi = (state->Reg[rn_idx] >> 16); - if (rn_lo > max) + if (rn_lo > max) { rn_lo = max; - else if (rn_lo < min) + state->Cpsr |= (1 << 27); + } else if (rn_lo < min) { rn_lo = min; + state->Cpsr |= (1 << 27); + } - if (rn_hi > max) + if (rn_hi > max) { rn_hi = max; - else if (rn_hi < min) + state->Cpsr |= (1 << 27); + } else if (rn_hi < min) { rn_hi = min; + state->Cpsr |= (1 << 27); + } + ARMul_CPSRAltered(state); state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); return 1; } @@ -6313,16 +6357,23 @@ L_stm_s_takeabort: s16 rn_lo = (state->Reg[rn_idx]); s16 rn_hi = (state->Reg[rn_idx] >> 16); - if (max < rn_lo) + if (max < rn_lo) { rn_lo = max; - else if (rn_lo < 0) + state->Cpsr |= (1 << 27); + } else if (rn_lo < 0) { rn_lo = 0; + state->Cpsr |= (1 << 27); + } - if (max < rn_hi) + if (max < rn_hi) { rn_hi = max; - else if (rn_hi < 0) + state->Cpsr |= (1 << 27); + } else if (rn_hi < 0) { rn_hi = 0; - + state->Cpsr |= (1 << 27); + } + + ARMul_CPSRAltered(state); state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); return 1; } diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 30519f216..b31c0ea24 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp @@ -227,8 +227,9 @@ ARMul_CPSRAltered (ARMul_State * state) //state->Cpsr &= ~CBIT; ASSIGNV ((state->Cpsr & VBIT) != 0); //state->Cpsr &= ~VBIT; - ASSIGNS ((state->Cpsr & SBIT) != 0); - //state->Cpsr &= ~SBIT; + ASSIGNQ ((state->Cpsr & QBIT) != 0); + //state->Cpsr &= ~QBIT; + state->GEFlag = (state->Cpsr & 0x000F0000); #ifdef MODET ASSIGNT ((state->Cpsr & TBIT) != 0); //state->Cpsr &= ~TBIT; diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 28a4a0db4..34eb5aaf7 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h @@ -198,7 +198,7 @@ struct ARMul_State //ARMword translate_pc; /* add armv6 flags dyf:2010-08-09 */ - ARMword GEFlag, EFlag, AFlag, QFlags; + ARMword GEFlag, EFlag, AFlag, QFlag; //chy:2003-08-19, used in arm v5e|xscale ARMword SFlag; #ifdef MODET diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h index 7f7c0e682..e1b286f0f 100644 --- a/src/core/arm/skyeye_common/armemu.h +++ b/src/core/arm/skyeye_common/armemu.h @@ -34,7 +34,7 @@ #define ZBIT (1L << 30) #define CBIT (1L << 29) #define VBIT (1L << 28) -#define SBIT (1L << 27) +#define QBIT (1L << 27) #define IBIT (1L << 7) #define FBIT (1L << 6) #define IFBITS (3L << 6) @@ -156,13 +156,14 @@ #define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) #define R15MODE (state->Reg[15] & R15MODEBITS) -#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27)) +#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (QFLAG << 27)) #define EINT (IFFLAGS << 6) #define ER15INT (IFFLAGS << 26) #define EMODE (state->Mode) +#define EGEBITS (state->GEFlag & 0x000F0000) #ifdef MODET -#define CPSR (ECC | EINT | EMODE | (TFLAG << 5)) +#define CPSR (ECC | EGEBITS | (EFLAG << 9) | (AFLAG << 8) | EINT | (TFLAG << 5) | EMODE) #else #define CPSR (ECC | EINT | EMODE) #endif |