diff options
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
-rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 535 |
1 files changed, 272 insertions, 263 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index d54dbeac5..f0d349de7 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -3100,7 +3100,6 @@ mainswitch: break; case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ - //ichfly PKHBT PKHTB todo check this if ((instr & 0x70) == 0x10) { //pkhbt u8 idest = BITS(12, 15); u8 rfis = BITS(16, 19); @@ -3109,18 +3108,11 @@ mainswitch: state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); break; } else if ((instr & 0x70) == 0x50) { //pkhtb - const u8 rd_idx = BITS(12, 15); - const u8 rn_idx = BITS(16, 19); - const u8 rm_idx = BITS(0, 3); - const u8 imm5 = BITS(7, 11); - - ARMword val; - if (imm5 >= 32) - val = (state->Reg[rm_idx] >> 31); - else - val = (state->Reg[rm_idx] >> imm5); - - state->Reg[rd_idx] = (val & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000); + u8 rd_idx = BITS(12, 15); + u8 rn_idx = BITS(16, 19); + u8 rm_idx = BITS(0, 3); + u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31; + state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000); break; } else if (BIT (4)) { #ifdef MODE32 @@ -6117,30 +6109,130 @@ L_stm_s_takeabort: } printf("Unhandled v6 insn: uasx/usax\n"); break; - case 0x66: - if ((instr & 0x0FF00FF0) == 0x06600FF0) { //uqsub8 - u32 rd = (instr >> 12) & 0xF; - u32 rm = (instr >> 16) & 0xF; - u32 rn = (instr >> 0) & 0xF; - u32 subfrom = state->Reg[rm]; - u32 tosub = state->Reg[rn]; - - u8 b1 = (u8)((u8)(subfrom)-(u8)(tosub)); - if (b1 > (u8)(subfrom)) b1 = 0; - u8 b2 = (u8)((u8)(subfrom >> 8) - (u8)(tosub >> 8)); - if (b2 > (u8)(subfrom >> 8)) b2 = 0; - u8 b3 = (u8)((u8)(subfrom >> 16) - (u8)(tosub >> 16)); - if (b3 > (u8)(subfrom >> 16)) b3 = 0; - u8 b4 = (u8)((u8)(subfrom >> 24) - (u8)(tosub >> 24)); - if (b4 > (u8)(subfrom >> 24)) b4 = 0; - state->Reg[rd] = (u32)(b1 | b2 << 8 | b3 << 16 | b4 << 24); + case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8 + { + const u8 rd_idx = BITS(12, 15); + const u8 rm_idx = BITS(0, 3); + const u8 rn_idx = BITS(16, 19); + const u8 op2 = BITS(5, 7); + const u32 rm_val = state->Reg[rm_idx]; + const u32 rn_val = state->Reg[rn_idx]; + + u16 lo_val = 0; + u16 hi_val = 0; + + // UQADD16 + if (op2 == 0x00) { + lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); + hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); + } + // UQASX + else if (op2 == 0x01) { + lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); + hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); + } + // UQSAX + else if (op2 == 0x02) { + lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); + hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); + } + // UQSUB16 + else if (op2 == 0x03) { + lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); + hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); + } + // UQADD8 + else if (op2 == 0x04) { + lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | + ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; + hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | + ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; + } + // UQSUB8 + else { + lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | + ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; + hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | + ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; + } + + state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16); return 1; - } else { - printf ("Unhandled v6 insn: uqsub16\n"); } break; - case 0x67: - printf ("Unhandled v6 insn: uhadd/uhsub\n"); + case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8. + { + const u8 op2 = BITS(5, 7); + + const u8 rm_idx = BITS(0, 3); + const u8 rn_idx = BITS(16, 19); + const u8 rd_idx = BITS(12, 15); + + const u32 rm_val = state->Reg[rm_idx]; + const u32 rn_val = state->Reg[rn_idx]; + + if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) + { + u32 lo_val = 0; + u32 hi_val = 0; + + // UHADD16 + if (op2 == 0x00) { + lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); + hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); + } + // UHASX + else if (op2 == 0x01) { + lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); + hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); + } + // UHSAX + else if (op2 == 0x02) { + lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); + hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); + } + // UHSUB16 + else if (op2 == 0x03) { + lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); + hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); + } + + lo_val >>= 1; + hi_val >>= 1; + + state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16); + return 1; + } + else if (op2 == 0x04 || op2 == 0x07) { + u32 sum1; + u32 sum2; + u32 sum3; + u32 sum4; + + // UHADD8 + if (op2 == 0x04) { + sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); + sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); + sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); + sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); + } + // UHSUB8 + else { + sum1 = (rn_val & 0xFF) - (rm_val & 0xFF); + sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); + sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); + sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); + } + + sum1 >>= 1; + sum2 >>= 1; + sum3 >>= 1; + sum4 >>= 1; + + state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); + return 1; + } + } break; case 0x68: { @@ -6172,129 +6264,94 @@ L_stm_s_takeabort: return 1; } } - printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); - break; - case 0x6a: { - ARMword Rm; - int ror = -1; - - switch (BITS(4, 11)) { - case 0x07: - ror = 0; - break; - case 0x47: - ror = 8; - break; - case 0x87: - ror = 16; - break; - case 0xc7: - ror = 24; - break; - - case 0x01: - case 0xf3: - //ichfly - //SSAT16 - { - const u8 rd_idx = BITS(12, 15); - const u8 rn_idx = BITS(0, 3); - const u8 num_bits = BITS(16, 19) + 1; - const s16 min = -(0x8000 >> (16 - num_bits)); - const s16 max = (0x7FFF >> (16 - num_bits)); - s16 rn_lo = (state->Reg[rn_idx]); - s16 rn_hi = (state->Reg[rn_idx] >> 16); - - if (rn_lo > max) { - rn_lo = max; - SETQ; - } else if (rn_lo < min) { - rn_lo = min; - SETQ; - } - - if (rn_hi > max) { - rn_hi = max; - SETQ; - } else if (rn_hi < min) { - rn_hi = min; - SETQ; - } - - state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); - return 1; - } + printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); + break; - default: - break; - } + case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB + { + const u8 op2 = BITS(5, 7); - if (ror == -1) { - if (BITS(4, 6) == 0x7) { - printf("Unhandled v6 insn: ssat\n"); - return 0; + // SSAT16 + if (op2 == 0x01) { + const u8 rd_idx = BITS(12, 15); + const u8 rn_idx = BITS(0, 3); + const u8 num_bits = BITS(16, 19) + 1; + const s16 min = -(0x8000 >> (16 - num_bits)); + const s16 max = (0x7FFF >> (16 - num_bits)); + s16 rn_lo = (state->Reg[rn_idx]); + s16 rn_hi = (state->Reg[rn_idx] >> 16); + + if (rn_lo > max) { + rn_lo = max; + SETQ; + } else if (rn_lo < min) { + rn_lo = min; + SETQ; } - break; - } - Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); - if (Rm & 0x80) - Rm |= 0xffffff00; + if (rn_hi > max) { + rn_hi = max; + SETQ; + } else if (rn_hi < min) { + rn_hi = min; + SETQ; + } - if (BITS(16, 19) == 0xf) - /* SXTB */ - state->Reg[BITS(12, 15)] = Rm; - else - /* SXTAB */ - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; + state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); + return 1; + } + else if (op2 == 0x03) { + const u8 rotation = BITS(10, 11) * 8; + u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF); + if (rm & 0x80) + rm |= 0xffffff00; + + // SXTB, otherwise SXTAB + if (BITS(16, 19) == 0xf) + state->Reg[BITS(12, 15)] = rm; + else + state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - return 1; + return 1; + } + else { + printf("Unimplemented op: SSAT"); + } } - case 0x6b: + break; + + case 0x6b: // REV, REV16, SXTH, and SXTAH { - ARMword Rm; - int ror = -1; - - switch (BITS(4, 11)) { - case 0x07: - ror = 0; - break; - case 0x47: - ror = 8; - break; - case 0x87: - ror = 16; - break; - case 0xc7: - ror = 24; - break; - - case 0xf3: // REV - DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); - return 1; - case 0xfb: // REV16 - DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); - return 1; - default: - break; - } + const u8 op2 = BITS(5, 7); - if (ror == -1) - break; + // REV + if (op2 == 0x01) { + DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); + return 1; + } + // REV16 + else if (op2 == 0x05) { + DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); + return 1; + } + else if (op2 == 0x03) { + const u8 rotate = BITS(10, 11) * 8; - Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF); - if (Rm & 0x8000) - Rm |= 0xffff0000; + u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); + if (rm & 0x8000) + rm |= 0xffff0000; - if (BITS(16, 19) == 0xf) - /* SXTH */ - state->Reg[BITS(12, 15)] = Rm; - else - /* SXTAH */ - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; + // SXTH, otherwise SXTAH + if (BITS(16, 19) == 15) + state->Reg[BITS(12, 15)] = rm; + else + state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - return 1; + return 1; + } } + break; + case 0x6c: // UXTB16 and UXTAB16 { const u8 rm_idx = BITS(0, 3); @@ -6322,132 +6379,84 @@ L_stm_s_takeabort: return 1; } break; - case 0x6e: { - ARMword Rm; - int ror = -1; - - switch (BITS(4, 11)) { - case 0x07: - ror = 0; - break; - case 0x47: - ror = 8; - break; - case 0x87: - ror = 16; - break; - case 0xc7: - ror = 24; - break; - - case 0x01: - case 0xf3: - //ichfly - //USAT16 - { - const u8 rd_idx = BITS(12, 15); - const u8 rn_idx = BITS(0, 3); - const u8 num_bits = BITS(16, 19); - const s16 max = 0xFFFF >> (16 - num_bits); - s16 rn_lo = (state->Reg[rn_idx]); - s16 rn_hi = (state->Reg[rn_idx] >> 16); - - if (max < rn_lo) { - rn_lo = max; - SETQ; - } else if (rn_lo < 0) { - rn_lo = 0; - SETQ; - } - - if (max < rn_hi) { - rn_hi = max; - SETQ; - } else if (rn_hi < 0) { - rn_hi = 0; - SETQ; - } - - state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); - return 1; - } - - default: - break; - } + case 0x6e: // USAT, USAT16, UXTB, and UXTAB + { + const u8 op2 = BITS(5, 7); - if (ror == -1) { - if (BITS(4, 6) == 0x7) { - printf("Unhandled v6 insn: usat\n"); - return 0; + // USAT16 + if (op2 == 0x01) { + const u8 rd_idx = BITS(12, 15); + const u8 rn_idx = BITS(0, 3); + const u8 num_bits = BITS(16, 19); + const s16 max = 0xFFFF >> (16 - num_bits); + s16 rn_lo = (state->Reg[rn_idx]); + s16 rn_hi = (state->Reg[rn_idx] >> 16); + + if (max < rn_lo) { + rn_lo = max; + SETQ; + } else if (rn_lo < 0) { + rn_lo = 0; + SETQ; + } + + if (max < rn_hi) { + rn_hi = max; + SETQ; + } else if (rn_hi < 0) { + rn_hi = 0; + SETQ; } - break; + + state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); + return 1; } - - Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); - - if (BITS(16, 19) == 0xf) + else if (op2 == 0x03) { + const u8 rotate = BITS(10, 11) * 8; + const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF); + + if (BITS(16, 19) == 0xf) /* UXTB */ - state->Reg[BITS(12, 15)] = Rm; - else + state->Reg[BITS(12, 15)] = rm; + else /* UXTAB */ - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; + state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - return 1; - } - - case 0x6f: { - ARMword Rm; - int ror = -1; - - switch (BITS(4, 11)) { - case 0x07: - ror = 0; - break; - case 0x47: - ror = 8; - break; - case 0x87: - ror = 16; - break; - case 0xc7: - ror = 24; - break; - - case 0xfb: // REVSH - { - DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8); - if (DEST & 0x8000) - DEST |= 0xffff0000; - return 1; - } - default: - break; + return 1; } + else { + printf("Unimplemented op: USAT"); + } + } + break; - if (ror == -1) - break; - - Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF); + case 0x6f: // UXTH, UXTAH, and REVSH. + { + const u8 op2 = BITS(5, 7); - /* UXT */ - /* state->Reg[BITS (12, 15)] = Rm; */ - /* dyf add */ - if (BITS(16, 19) == 0xf) { - state->Reg[BITS(12, 15)] = Rm; - } - else { - /* UXTAH */ - /* state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; */ - // printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)] - // , Rm, BITS(10, 11)); - // printf("icounter is %lld\n", state->NumInstrs); - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; - // printf("rd is %x\n", state->Reg[BITS (12, 15)]); - // exit(-1); + // REVSH + if (op2 == 0x05) { + DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8); + if (DEST & 0x8000) + DEST |= 0xffff0000; + return 1; } + // UXTH and UXTAH + else if (op2 == 0x03) { + const u8 rotate = BITS(10, 11) * 8; + const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); + + // UXTH + if (BITS(16, 19) == 0xf) { + state->Reg[BITS(12, 15)] = rm; + } + // UXTAH + else { + state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; + } - return 1; + return 1; + } } case 0x70: // ichfly @@ -6572,10 +6581,10 @@ L_stm_s_takeabort: const u32 rm_val = state->Reg[rm_idx]; const u32 rn_val = state->Reg[rn_idx]; - const u8 diff1 = (u8)std::labs((rn_val & 0xFF) - (rm_val & 0xFF)); - const u8 diff2 = (u8)std::labs(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF)); - const u8 diff3 = (u8)std::labs(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF)); - const u8 diff4 = (u8)std::labs(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF)); + const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); + const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); + const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); + const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); u32 finalDif = (diff1 + diff2 + diff3 + diff4); |