From 0832cf7cd78d09ead786df95da72fc934d333433 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 29 Oct 2014 22:37:25 -0400 Subject: [PATCH] ARM: Merged additional ARMv6 instructions implemented by 3dmoo. --- src/core/arm/interpreter/armemu.cpp | 276 +++++++++++++++++++++++----- 1 file changed, 234 insertions(+), 42 deletions(-) diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index cdcf47ee1..73223874e 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -63,13 +63,6 @@ static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int); static void Handle_Load_Double (ARMul_State *, ARMword); static void Handle_Store_Double (ARMul_State *, ARMword); -void -XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far); -int -XScale_debug_moe (ARMul_State * state, int moe); -unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, - unsigned cpnum); - static int handle_v6_insn (ARMul_State * state, ARMword instr); @@ -376,7 +369,7 @@ ARMul_Emulate26 (ARMul_State * state) #endif { /* The PC pipeline value depends on whether ARM - or Thumb instructions are being + or Thumb instructions are being d. */ ARMword isize; ARMword instr; /* The current instruction. */ @@ -538,6 +531,7 @@ ARMul_Emulate26 (ARMul_State * state) state->AbortAddr = 1; instr = ARMul_LoadInstrN (state, pc, isize); + //chy 2006-04-12, for ICE debug have_bp=ARMul_ICE_debug(state,instr,pc); #if 0 @@ -562,6 +556,7 @@ ARMul_Emulate26 (ARMul_State * state) } printf("\n"); #endif + instr = ARMul_LoadInstrN (state, pc, isize); state->last_instr = state->CurrInstr; state->CurrInstr = instr; @@ -952,9 +947,8 @@ ARMul_Emulate26 (ARMul_State * state) case t_decoded: /* ARM instruction available. */ //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp); - - if (armOp == 0xDEADC0DE) - { + + if (armOp == 0xDEADC0DE) { DEBUG("Failed to decode thumb opcode %04X at %08X\n", instr, pc); } @@ -967,7 +961,6 @@ ARMul_Emulate26 (ARMul_State * state) } } #endif - /* Check the condition codes. */ if ((temp = TOPBITS (28)) == AL) { /* Vile deed in the need for speed. */ @@ -1124,6 +1117,7 @@ ARMul_Emulate26 (ARMul_State * state) //chy 2003-08-24 now #if 0 .... #endif process cp14, cp15.reg14, I disable it... + /* Actual execution of instructions begins here. */ /* If the condition codes don't match, stop here. */ if (temp) { @@ -2308,12 +2302,9 @@ mainswitch: if (state->Aborted) { TAKEABORT; } - if (enter) - { + if (enter) { state->Reg[DESTReg] = 0; - } - else - { + } else { state->Reg[DESTReg] = 1; } break; @@ -3063,7 +3054,27 @@ mainswitch: break; case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ - if (BIT (4)) { + //ichfly PKHBT PKHTB todo check this + if ((instr & 0x70) == 0x10) //pkhbt + { + u8 idest = BITS(12, 15); + u8 rfis = BITS(16, 19); + u8 rlast = BITS(0, 3); + u8 ishi = BITS(7,11); + state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); + break; + } + else if ((instr & 0x70) == 0x50)//pkhtb + { + u8 idest = BITS(12, 15); + u8 rfis = BITS(16, 19); + u8 rlast = BITS(0, 3); + u8 ishi = BITS(7, 11); + if (ishi == 0)ishi = 0x20; + state->Reg[idest] = (((int)(state->Reg[rlast]) >> (int)(ishi))& 0xFFFF) | ((state->Reg[rfis]) & 0xFFFF0000); + break; + } + else if (BIT (4)) { #ifdef MODE32 if (state->is_v6 && handle_v6_insn (state, instr)) @@ -3675,7 +3686,13 @@ mainswitch: /* Co-Processor Data Transfers. */ case 0xc4: - if (state->is_v5) { + if ((instr & 0x0FF00FF0) == 0xC400B10) //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0 + { + state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)]; + state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)]; + break; + } + else if (state->is_v5) { /* Reading from R15 is UNPREDICTABLE. */ if (BITS (12, 15) == 15 || BITS (16, 19) == 15) ARMul_UndefInstr (state, instr); @@ -3695,13 +3712,21 @@ mainswitch: break; case 0xc5: - if (state->is_v5) { + if ((instr & 0x00000FF0) == 0xB10) //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0 + { + state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1]; + state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1]; + break; + } + else if (state->is_v5) { /* Writes to R15 are UNPREDICATABLE. */ if (DESTReg == 15 || LHSReg == 15) ARMul_UndefInstr (state, instr); /* Is access to the coprocessor allowed ? */ else if (!CP_ACCESS_ALLOWED(state, CPNum)) - ARMul_UndefInstr (state, instr); + { + ARMul_UndefInstr(state, instr); + } else { /* MRRC, ARMv5TE and up */ ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); @@ -4059,9 +4084,11 @@ TEST_EMULATE: // continue; else if (state->Emulate != RUN) break; - } - while (state->NumInstrsToExecute--); + + } + while (state->NumInstrsToExecute); +exit: state->decoded = decoded; state->loaded = loaded; state->pc = pc; @@ -5686,12 +5713,98 @@ L_stm_s_takeabort: case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break; +#endif case 0x61: - printf ("Unhandled v6 insn: sadd/ssub\n"); + if ((instr & 0xFF0) == 0xf70)//ssub16 + { + u8 tar = BITS(12, 15); + u8 src1 = BITS(16, 19); + u8 src2 = BITS(0, 3); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = (state->Reg[src2] & 0xFFFF); + s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = (a1 - a2)&0xFFFF | (((b1 - b2)&0xFFFF)<< 0x10); + return 1; + } + else if ((instr & 0xFF0) == 0xf10)//sadd16 + { + u8 tar = BITS(12, 15); + u8 src1 = BITS(16, 19); + u8 src2 = BITS(0, 3); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = (state->Reg[src2] & 0xFFFF); + s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = (a1 + a2)&0xFFFF | (((b1 + b2)&0xFFFF)<< 0x10); + return 1; + } + else if ((instr & 0xFF0) == 0xf50)//ssax + { + u8 tar = BITS(12, 15); + u8 src1 = BITS(16, 19); + u8 src2 = BITS(0, 3); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = (state->Reg[src2] & 0xFFFF); + s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = (a1 - b2) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); + return 1; + } + else if ((instr & 0xFF0) == 0xf30)//sasx + { + u8 tar = BITS(12, 15); + u8 src1 = BITS(16, 19); + u8 src2 = BITS(0, 3); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = (state->Reg[src2] & 0xFFFF); + s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = (a2 - b1) & 0xFFFF | (((a2 + b1) & 0xFFFF) << 0x10); + return 1; + } + else printf ("Unhandled v6 insn: sadd/ssub\n"); break; case 0x62: - printf ("Unhandled v6 insn: qadd/qsub\n"); + if ((instr & 0xFF0) == 0xf70)//QSUB16 + { + u8 tar = BITS(12, 15); + u8 src1 = BITS(16, 19); + u8 src2 = BITS(0, 3); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = (state->Reg[src2] & 0xFFFF); + s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); + s32 res1 = (a1 - b1); + s32 res2 = (a2 - b2); + if (res1 > 0x7FFF) res1 = 0x7FFF; + if (res2 > 0x7FFF) res2 = 0x7FFF; + if (res1 < 0x7FFF) res1 = -0x8000; + if (res2 < 0x7FFF) res2 = -0x8000; + state->Reg[tar] = (res1 & 0xFFFF) | ((res2 & 0xFFFF) << 0x10); + return 1; + } + else if ((instr & 0xFF0) == 0xf10)//QADD16 + { + u8 tar = BITS(12, 15); + u8 src1 = BITS(16, 19); + u8 src2 = BITS(0, 3); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = (state->Reg[src2] & 0xFFFF); + s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); + s32 res1 = (a1 + b1); + s32 res2 = (a2 + b2); + if (res1 > 0x7FFF) res1 = 0x7FFF; + if (res2 > 0x7FFF) res2 = 0x7FFF; + if (res1 < 0x7FFF) res1 = -0x8000; + if (res2 < 0x7FFF) res2 = -0x8000; + state->Reg[tar] = ((res1) & 0xFFFF) | (((res2) & 0xFFFF) << 0x10); + return 1; + } + else printf ("Unhandled v6 insn: qadd/qsub\n"); break; +#if 0 case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break; @@ -5709,10 +5822,65 @@ L_stm_s_takeabort: break; #endif case 0x6c: - printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); + if ((instr & 0xf03f0) == 0xf0070) //uxtb16 + { + u8 src1 = BITS(0, 3); + u8 tar = BITS(12, 15); + u32 base = state->Reg[src1]; + u32 shamt = BITS(9,10)* 8; + u32 in = ((base << (32 - shamt)) | (base >> shamt)); + state->Reg[tar] = in & 0x00FF00FF; + return 1; + } + else + printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break; case 0x70: - printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); + if ((instr & 0xf0d0) == 0xf010)//smuad //ichfly + { + u8 tar = BITS(16, 19); + u8 src1 = BITS(0, 3); + u8 src2 = BITS(8, 11); + u8 swap = BIT(5); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); + s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = a1*a2 + b1*b2; + return 1; + + } + else if ((instr & 0xf0d0) == 0xf050)//smusd + { + u8 tar = BITS(16, 19); + u8 src1 = BITS(0, 3); + u8 src2 = BITS(8, 11); + u8 swap = BIT(5); + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); + s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = a1*a2 - b1*b2; + return 1; + } + else if ((instr & 0xd0) == 0x10)//smlad + { + u8 tar = BITS(16, 19); + u8 src1 = BITS(0, 3); + u8 src2 = BITS(8, 11); + u8 src3 = BITS(12, 15); + u8 swap = BIT(5); + + u32 a3 = state->Reg[src3]; + + s16 a1 = (state->Reg[src1] & 0xFFFF); + s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); + s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); + s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); + state->Reg[tar] = a1*a2 + b1*b2 + a3; + return 1; + } + else printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break; case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); @@ -5750,13 +5918,10 @@ L_stm_s_takeabort: if (state->Aborted) { TAKEABORT; } - - if (enter) - { + + if (enter) { state->Reg[DESTReg] = 0; - } - else - { + } else { state->Reg[DESTReg] = 1; } @@ -5795,12 +5960,9 @@ L_stm_s_takeabort: } - if (enter) - { + if (enter) { state->Reg[DESTReg] = 0; - } - else - { + } else { state->Reg[DESTReg] = 1; } @@ -5853,8 +6015,25 @@ L_stm_s_takeabort: case 0x01: case 0xf3: - printf ("Unhandled v6 insn: ssat\n"); - return 0; + //ichfly + //SSAT16 + { + u8 tar = BITS(12,15); + u8 src = BITS(0, 3); + u8 val = BITS(16, 19) + 1; + s16 a1 = (state->Reg[src]); + s16 a2 = (state->Reg[src] >> 0x10); + s16 min = (s16)(0x8000) >> (16 - val); + s16 max = 0x7FFF >> (16 - val); + if (min > a1) a1 = min; + if (max < a1) a1 = max; + if (min > a2) a2 = min; + if (max < a2) a2 = max; + u32 temp2 = ((u32)(a2)) << 0x10; + state->Reg[tar] = (a1&0xFFFF) | (temp2); + } + + return 1; default: break; } @@ -5944,8 +6123,21 @@ L_stm_s_takeabort: case 0x01: case 0xf3: - printf ("Unhandled v6 insn: usat\n"); - return 0; + //ichfly + //USAT16 + { + u8 tar = BITS(12, 15); + u8 src = BITS(0, 3); + u8 val = BITS(16, 19); + s16 a1 = (state->Reg[src]); + s16 a2 = (state->Reg[src] >> 0x10); + s16 max = 0xFFFF >> (16 - val); + if (max < a1) a1 = max; + if (max < a2) a2 = max; + u32 temp2 = ((u32)(a2)) << 0x10; + state->Reg[tar] = (a1 & 0xFFFF) | (temp2); + } + return 1; default: break; }