diff options
-rw-r--r-- | target/arm/a32.decode | 32 | ||||
-rw-r--r-- | target/arm/t32.decode | 37 | ||||
-rw-r--r-- | target/arm/translate.c | 541 |
3 files changed, 300 insertions, 310 deletions
diff --git a/target/arm/a32.decode b/target/arm/a32.decode index 4dfd8133f7..4990eb3839 100644 --- a/target/arm/a32.decode +++ b/target/arm/a32.decode @@ -28,6 +28,7 @@ &s_rri_rot s rn rd imm rot &s_rrrr s rd rn rm ra &rrrr rd rn rm ra +&rrr_rot rd rn rm rot &rrr rd rn rm &rr rd rm &ri rd imm @@ -43,6 +44,8 @@ &ldrex rn rt rt2 imm &bfx rd rn lsb widthm1 &bfi rd rn lsb msb +&sat rd rn satimm imm sh +&pkh rd rn rm imm tb # Data-processing (register) @@ -454,3 +457,32 @@ UHSAX .... 0110 0111 .... .... 1111 0101 .... @rndm UHSUB16 .... 0110 0111 .... .... 1111 0111 .... @rndm UHADD8 .... 0110 0111 .... .... 1111 1001 .... @rndm UHSUB8 .... 0110 0111 .... .... 1111 1111 .... @rndm + +# Packing, unpacking, saturation, and reversal + +PKH ---- 0110 1000 rn:4 rd:4 imm:5 tb:1 01 rm:4 &pkh + +@sat ---- .... ... satimm:5 rd:4 imm:5 sh:1 .. rn:4 &sat +@sat16 ---- .... .... satimm:4 rd:4 .... .... rn:4 \ + &sat imm=0 sh=0 + +SSAT .... 0110 101. .... .... .... ..01 .... @sat +USAT .... 0110 111. .... .... .... ..01 .... @sat + +SSAT16 .... 0110 1010 .... .... 1111 0011 .... @sat16 +USAT16 .... 0110 1110 .... .... 1111 0011 .... @sat16 + +@rrr_rot ---- .... .... rn:4 rd:4 rot:2 ...... rm:4 &rrr_rot + +SXTAB16 .... 0110 1000 .... .... ..00 0111 .... @rrr_rot +SXTAB .... 0110 1010 .... .... ..00 0111 .... @rrr_rot +SXTAH .... 0110 1011 .... .... ..00 0111 .... @rrr_rot +UXTAB16 .... 0110 1100 .... .... ..00 0111 .... @rrr_rot +UXTAB .... 0110 1110 .... .... ..00 0111 .... @rrr_rot +UXTAH .... 0110 1111 .... .... ..00 0111 .... @rrr_rot + +SEL .... 0110 1000 .... .... 1111 1011 .... @rndm +REV .... 0110 1011 1111 .... 1111 0011 .... @rdm +REV16 .... 0110 1011 1111 .... 1111 1011 .... @rdm +REVSH .... 0110 1111 1111 .... 1111 1011 .... @rdm +RBIT .... 0110 1111 1111 .... 1111 0011 .... @rdm diff --git a/target/arm/t32.decode b/target/arm/t32.decode index c899c56766..71f6d728f2 100644 --- a/target/arm/t32.decode +++ b/target/arm/t32.decode @@ -25,6 +25,7 @@ &s_rri_rot !extern s rn rd imm rot &s_rrrr !extern s rd rn rm ra &rrrr !extern rd rn rm ra +&rrr_rot !extern rd rn rm rot &rrr !extern rd rn rm &rr !extern rd rm &ri !extern rd imm @@ -40,6 +41,8 @@ &ldrex !extern rn rt rt2 imm &bfx !extern rd rn lsb widthm1 &bfi !extern rd rn lsb msb +&sat !extern rd rn satimm imm sh +&pkh !extern rd rn rm imm tb # Data-processing (register) @@ -69,7 +72,8 @@ BIC_rrri 1110101 0001 . .... 0 ... .... .... .... @s_rrr_shi TEQ_xrri 1110101 0100 1 .... 0 ... 1111 .... .... @S_xrr_shi EOR_rrri 1110101 0100 . .... 0 ... .... .... .... @s_rrr_shi } -# PKHBT, PKHTB at opc1 = 0110 +PKH 1110101 0110 0 rn:4 0 ... rd:4 .. tb:1 0 rm:4 \ + &pkh imm=%imm5_12_6 { CMN_xrri 1110101 1000 1 .... 0 ... 1111 .... .... @S_xrr_shi ADD_rrri 1110101 1000 . .... 0 ... .... .... .... @s_rrr_shi @@ -148,6 +152,20 @@ RSB_rri 1111 0.0 1110 . .... 0 ... .... ........ @s_rri_rot # Saturate, bitfield +@sat .... .... .. sh:1 . rn:4 . ... rd:4 .. . satimm:5 \ + &sat imm=%imm5_12_6 +@sat16 .... .... .. . . rn:4 . ... rd:4 .. . satimm:5 \ + &sat sh=0 imm=0 + +{ + SSAT16 1111 0011 001 0 .... 0 000 .... 00 0 ..... @sat16 + SSAT 1111 0011 00. 0 .... 0 ... .... .. 0 ..... @sat +} +{ + USAT16 1111 0011 101 0 .... 0 000 .... 00 0 ..... @sat16 + USAT 1111 0011 10. 0 .... 0 ... .... .. 0 ..... @sat +} + @bfx .... .... ... . rn:4 . ... rd:4 .. . widthm1:5 \ &bfx lsb=%imm5_12_6 @bfi .... .... ... . rn:4 . ... rd:4 .. . msb:5 \ @@ -224,7 +242,13 @@ CRC32CB 1111 1010 1101 .... 1111 .... 1000 .... @rndm CRC32CH 1111 1010 1101 .... 1111 .... 1001 .... @rndm CRC32CW 1111 1010 1101 .... 1111 .... 1010 .... @rndm +SEL 1111 1010 1010 .... 1111 .... 1000 .... @rndm + # Note rn != rm is CONSTRAINED UNPREDICTABLE; we choose to ignore rn. +REV 1111 1010 1001 ---- 1111 .... 1000 .... @rdm +REV16 1111 1010 1001 ---- 1111 .... 1001 .... @rdm +RBIT 1111 1010 1001 ---- 1111 .... 1010 .... @rdm +REVSH 1111 1010 1001 ---- 1111 .... 1011 .... @rdm CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm # Branches and miscellaneous control @@ -501,3 +525,14 @@ SHSAX 1111 1010 1110 .... 1111 .... 0010 .... @rndm USAX 1111 1010 1110 .... 1111 .... 0100 .... @rndm UQSAX 1111 1010 1110 .... 1111 .... 0101 .... @rndm UHSAX 1111 1010 1110 .... 1111 .... 0110 .... @rndm + +# Register extends + +@rrr_rot .... .... .... rn:4 .... rd:4 .. rot:2 rm:4 &rrr_rot + +SXTAH 1111 1010 0000 .... 1111 .... 10.. .... @rrr_rot +UXTAH 1111 1010 0001 .... 1111 .... 10.. .... @rrr_rot +SXTAB16 1111 1010 0010 .... 1111 .... 10.. .... @rrr_rot +UXTAB16 1111 1010 0011 .... 1111 .... 10.. .... @rrr_rot +SXTAB 1111 1010 0100 .... 1111 .... 10.. .... @rrr_rot +UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot diff --git a/target/arm/translate.c b/target/arm/translate.c index 181d3d77f0..a6de23c6d3 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -355,7 +355,7 @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b) } /* Byteswap each halfword. */ -static void gen_rev16(TCGv_i32 var) +static void gen_rev16(TCGv_i32 dest, TCGv_i32 var) { TCGv_i32 tmp = tcg_temp_new_i32(); TCGv_i32 mask = tcg_const_i32(0x00ff00ff); @@ -363,17 +363,17 @@ static void gen_rev16(TCGv_i32 var) tcg_gen_and_i32(tmp, tmp, mask); tcg_gen_and_i32(var, var, mask); tcg_gen_shli_i32(var, var, 8); - tcg_gen_or_i32(var, var, tmp); + tcg_gen_or_i32(dest, var, tmp); tcg_temp_free_i32(mask); tcg_temp_free_i32(tmp); } /* Byteswap low halfword and sign extend. */ -static void gen_revsh(TCGv_i32 var) +static void gen_revsh(TCGv_i32 dest, TCGv_i32 var) { tcg_gen_ext16u_i32(var, var); tcg_gen_bswap16_i32(var, var); - tcg_gen_ext16s_i32(var, var); + tcg_gen_ext16s_i32(dest, var); } /* 32x32->64 multiply. Marks inputs as dead. */ @@ -426,7 +426,7 @@ static void gen_swap_half(TCGv_i32 var) t0 = (t0 + t1) ^ tmp; */ -static void gen_add16(TCGv_i32 t0, TCGv_i32 t1) +static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) { TCGv_i32 tmp = tcg_temp_new_i32(); tcg_gen_xor_i32(tmp, t0, t1); @@ -434,9 +434,8 @@ static void gen_add16(TCGv_i32 t0, TCGv_i32 t1) tcg_gen_andi_i32(t0, t0, ~0x8000); tcg_gen_andi_i32(t1, t1, ~0x8000); tcg_gen_add_i32(t0, t0, t1); - tcg_gen_xor_i32(t0, t0, tmp); + tcg_gen_xor_i32(dest, t0, tmp); tcg_temp_free_i32(tmp); - tcg_temp_free_i32(t1); } /* Set N and Z flags from var. */ @@ -6356,7 +6355,7 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn) } break; case NEON_2RM_VREV16: - gen_rev16(tmp); + gen_rev16(tmp, tmp); break; case NEON_2RM_VCLS: switch (size) { @@ -9334,12 +9333,224 @@ DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8) #undef DO_PAR_ADDSUB_GE /* + * Packing, unpacking, saturation, and reversal + */ + +static bool trans_PKH(DisasContext *s, arg_PKH *a) +{ + TCGv_i32 tn, tm; + int shift = a->imm; + + if (s->thumb + ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP) + : !ENABLE_ARCH_6) { + return false; + } + + tn = load_reg(s, a->rn); + tm = load_reg(s, a->rm); + if (a->tb) { + /* PKHTB */ + if (shift == 0) { + shift = 31; + } + tcg_gen_sari_i32(tm, tm, shift); + tcg_gen_deposit_i32(tn, tn, tm, 0, 16); + } else { + /* PKHBT */ + tcg_gen_shli_i32(tm, tm, shift); + tcg_gen_deposit_i32(tn, tm, tn, 0, 16); + } + tcg_temp_free_i32(tm); + store_reg(s, a->rd, tn); + return true; +} + +static bool op_sat(DisasContext *s, arg_sat *a, + void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) +{ + TCGv_i32 tmp, satimm; + int shift = a->imm; + + if (!ENABLE_ARCH_6) { + return false; + } + + tmp = load_reg(s, a->rn); + if (a->sh) { + tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31); + } else { + tcg_gen_shli_i32(tmp, tmp, shift); + } + + satimm = tcg_const_i32(a->satimm); + gen(tmp, cpu_env, tmp, satimm); + tcg_temp_free_i32(satimm); + + store_reg(s, a->rd, tmp); + return true; +} + +static bool trans_SSAT(DisasContext *s, arg_sat *a) +{ + return op_sat(s, a, gen_helper_ssat); +} + +static bool trans_USAT(DisasContext *s, arg_sat *a) +{ + return op_sat(s, a, gen_helper_usat); +} + +static bool trans_SSAT16(DisasContext *s, arg_sat *a) +{ + if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + return false; + } + return op_sat(s, a, gen_helper_ssat16); +} + +static bool trans_USAT16(DisasContext *s, arg_sat *a) +{ + if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + return false; + } + return op_sat(s, a, gen_helper_usat16); +} + +static bool op_xta(DisasContext *s, arg_rrr_rot *a, + void (*gen_extract)(TCGv_i32, TCGv_i32), + void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32)) +{ + TCGv_i32 tmp; + + if (!ENABLE_ARCH_6) { + return false; + } + + tmp = load_reg(s, a->rm); + /* + * TODO: In many cases we could do a shift instead of a rotate. + * Combined with a simple extend, that becomes an extract. + */ + tcg_gen_rotri_i32(tmp, tmp, a->rot * 8); + gen_extract(tmp, tmp); + + if (a->rn != 15) { + TCGv_i32 tmp2 = load_reg(s, a->rn); + gen_add(tmp, tmp, tmp2); + tcg_temp_free_i32(tmp2); + } + store_reg(s, a->rd, tmp); + return true; +} + +static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a) +{ + return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32); +} + +static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a) +{ + return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32); +} + +static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a) +{ + if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + return false; + } + return op_xta(s, a, gen_helper_sxtb16, gen_add16); +} + +static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a) +{ + return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32); +} + +static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a) +{ + return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32); +} + +static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a) +{ + if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + return false; + } + return op_xta(s, a, gen_helper_uxtb16, gen_add16); +} + +static bool trans_SEL(DisasContext *s, arg_rrr *a) +{ + TCGv_i32 t1, t2, t3; + + if (s->thumb + ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP) + : !ENABLE_ARCH_6) { + return false; + } + + t1 = load_reg(s, a->rn); + t2 = load_reg(s, a->rm); + t3 = tcg_temp_new_i32(); + tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE)); + gen_helper_sel_flags(t1, t3, t1, t2); + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + store_reg(s, a->rd, t1); + return true; +} + +static bool op_rr(DisasContext *s, arg_rr *a, + void (*gen)(TCGv_i32, TCGv_i32)) +{ + TCGv_i32 tmp; + + tmp = load_reg(s, a->rm); + gen(tmp, tmp); + store_reg(s, a->rd, tmp); + return true; +} + +static bool trans_REV(DisasContext *s, arg_rr *a) +{ + if (!ENABLE_ARCH_6) { + return false; + } + return op_rr(s, a, tcg_gen_bswap32_i32); +} + +static bool trans_REV16(DisasContext *s, arg_rr *a) +{ + if (!ENABLE_ARCH_6) { + return false; + } + return op_rr(s, a, gen_rev16); +} + +static bool trans_REVSH(DisasContext *s, arg_rr *a) +{ + if (!ENABLE_ARCH_6) { + return false; + } + return op_rr(s, a, gen_revsh); +} + +static bool trans_RBIT(DisasContext *s, arg_rr *a) +{ + if (!ENABLE_ARCH_6T2) { + return false; + } + return op_rr(s, a, gen_helper_rbit); +} + +/* * Legacy decoder. */ static void disas_arm_insn(DisasContext *s, unsigned int insn) { - unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh; + unsigned int cond, val, op1, i, rm, rs, rn, rd; TCGv_i32 tmp; TCGv_i32 tmp2; TCGv_i32 tmp3; @@ -9648,112 +9859,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) /* Done by decodetree */ goto illegal_op; case 1: - if ((insn & 0x00700020) == 0) { - /* Halfword pack. */ - tmp = load_reg(s, rn); - tmp2 = load_reg(s, rm); - shift = (insn >> 7) & 0x1f; - if (insn & (1 << 6)) { - /* pkhtb */ - if (shift == 0) { - shift = 31; - } - tcg_gen_sari_i32(tmp2, tmp2, shift); - tcg_gen_deposit_i32(tmp, tmp, tmp2, 0, 16); - } else { - /* pkhbt */ - tcg_gen_shli_i32(tmp2, tmp2, shift); - tcg_gen_deposit_i32(tmp, tmp2, tmp, 0, 16); - } - tcg_temp_free_i32(tmp2); - store_reg(s, rd, tmp); - } else if ((insn & 0x00200020) == 0x00200000) { - /* [us]sat */ - tmp = load_reg(s, rm); - shift = (insn >> 7) & 0x1f; - if (insn & (1 << 6)) { - if (shift == 0) - shift = 31; - tcg_gen_sari_i32(tmp, tmp, shift); - } else { - tcg_gen_shli_i32(tmp, tmp, shift); - } - sh = (insn >> 16) & 0x1f; - tmp2 = tcg_const_i32(sh); - if (insn & (1 << 22)) - gen_helper_usat(tmp, cpu_env, tmp, tmp2); - else - gen_helper_ssat(tmp, cpu_env, tmp, tmp2); - tcg_temp_free_i32(tmp2); - store_reg(s, rd, tmp); - } else if ((insn & 0x00300fe0) == 0x00200f20) { - /* [us]sat16 */ - tmp = load_reg(s, rm); - sh = (insn >> 16) & 0x1f; - tmp2 = tcg_const_i32(sh); - if (insn & (1 << 22)) - gen_helper_usat16(tmp, cpu_env, tmp, tmp2); - else - gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); - tcg_temp_free_i32(tmp2); - store_reg(s, rd, tmp); - } else if ((insn & 0x00700fe0) == 0x00000fa0) { - /* Select bytes. */ - tmp = load_reg(s, rn); - tmp2 = load_reg(s, rm); - tmp3 = tcg_temp_new_i32(); - tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE)); - gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); - tcg_temp_free_i32(tmp3); - tcg_temp_free_i32(tmp2); - store_reg(s, rd, tmp); - } else if ((insn & 0x000003e0) == 0x00000060) { - tmp = load_reg(s, rm); - shift = (insn >> 10) & 3; - /* ??? In many cases it's not necessary to do a - rotate, a shift is sufficient. */ - tcg_gen_rotri_i32(tmp, tmp, shift * 8); - op1 = (insn >> 20) & 7; - switch (op1) { - case 0: gen_sxtb16(tmp); break; - case 2: gen_sxtb(tmp); break; - case 3: gen_sxth(tmp); break; - case 4: gen_uxtb16(tmp); break; - case 6: gen_uxtb(tmp); break; - case 7: gen_uxth(tmp); break; - default: goto illegal_op; - } - if (rn != 15) { - tmp2 = load_reg(s, rn); - if ((op1 & 3) == 0) { - gen_add16(tmp, tmp2); - } else { - tcg_gen_add_i32(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); - } - } - store_reg(s, rd, tmp); - } else if ((insn & 0x003f0f60) == 0x003f0f20) { - /* rev */ - tmp = load_reg(s, rm); - if (insn & (1 << 22)) { - if (insn & (1 << 7)) { - gen_revsh(tmp); - } else { - ARCH(6T2); - gen_helper_rbit(tmp, tmp); - } - } else { - if (insn & (1 << 7)) - gen_rev16(tmp); - else - tcg_gen_bswap32_i32(tmp, tmp); - } - store_reg(s, rd, tmp); - } else { - goto illegal_op; - } - break; + /* Halfword pack, [US]SAT, [US]SAT16, SEL, REV et al */ + /* Done by decodetree */ + goto illegal_op; case 2: /* Multiplies (Type 3). */ switch ((insn >> 20) & 0x7) { case 5: @@ -10098,7 +10206,7 @@ static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn) /* Translate a 32-bit thumb instruction. */ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) { - uint32_t imm, shift, offset; + uint32_t imm, offset; uint32_t rd, rn, rm, rs; TCGv_i32 tmp; TCGv_i32 tmp2; @@ -10353,151 +10461,18 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) } break; case 5: - - op = (insn >> 21) & 0xf; - if (op == 6) { - if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { - goto illegal_op; - } - /* Halfword pack. */ - tmp = load_reg(s, rn); - tmp2 = load_reg(s, rm); - shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3); - if (insn & (1 << 5)) { - /* pkhtb */ - if (shift == 0) { - shift = 31; - } - tcg_gen_sari_i32(tmp2, tmp2, shift); - tcg_gen_deposit_i32(tmp, tmp, tmp2, 0, 16); - } else { - /* pkhbt */ - tcg_gen_shli_i32(tmp2, tmp2, shift); - tcg_gen_deposit_i32(tmp, tmp2, tmp, 0, 16); - } - tcg_temp_free_i32(tmp2); - store_reg(s, rd, tmp); - } else { - /* Data processing register constant shift. */ - /* All done in decodetree. Reach here for illegal ops. */ - goto illegal_op; - } - break; + /* All in decodetree */ + goto illegal_op; case 13: /* Misc data processing. */ op = ((insn >> 22) & 6) | ((insn >> 7) & 1); if (op < 4 && (insn & 0xf000) != 0xf000) goto illegal_op; switch (op) { case 0: /* Register controlled shift, in decodetree */ - goto illegal_op; - case 1: /* Sign/zero extend. */ - op = (insn >> 20) & 7; - switch (op) { - case 0: /* SXTAH, SXTH */ - case 1: /* UXTAH, UXTH */ - case 4: /* SXTAB, SXTB */ - case 5: /* UXTAB, UXTB */ - break; - case 2: /* SXTAB16, SXTB16 */ - case 3: /* UXTAB16, UXTB16 */ - if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { - goto illegal_op; - } - break; - default: - goto illegal_op; - } - if (rn != 15) { - if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { - goto illegal_op; - } - } - tmp = load_reg(s, rm); - shift = (insn >> 4) & 3; - /* ??? In many cases it's not necessary to do a - rotate, a shift is sufficient. */ - tcg_gen_rotri_i32(tmp, tmp, shift * 8); - op = (insn >> 20) & 7; - switch (op) { - case 0: gen_sxth(tmp); break; - case 1: gen_uxth(tmp); break; - case 2: gen_sxtb16(tmp); break; - case 3: gen_uxtb16(tmp); break; - case 4: gen_sxtb(tmp); break; - case 5: gen_uxtb(tmp); break; - default: - g_assert_not_reached(); - } - if (rn != 15) { - tmp2 = load_reg(s, rn); - if ((op >> 1) == 1) { - gen_add16(tmp, tmp2); - } else { - tcg_gen_add_i32(tmp, tmp, tmp2); - tcg_temp_free_i32(tmp2); - } - } - store_reg(s, rd, tmp); - break; + case 1: /* Sign/zero extend, in decodetree */ case 2: /* SIMD add/subtract, in decodetree */ + case 3: /* Other data processing, in decodetree */ goto illegal_op; - case 3: /* Other data processing. */ - op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); - if (op < 4) { - /* Saturating add/subtract. */ - /* All done in decodetree. Reach here for illegal ops. */ - goto illegal_op; - } else { - switch (op) { - case 0x0a: /* rbit */ - case 0x08: /* rev */ - case 0x09: /* rev16 */ - case 0x0b: /* revsh */ - break; - case 0x10: /* sel */ - if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { - goto illegal_op; - } - break; - case 0x18: /* clz, in decodetree */ - case 0x20: /* crc32/crc32c, in decodetree */ - case 0x21: - case 0x22: - case 0x28: - case 0x29: - case 0x2a: - goto illegal_op; - default: - goto illegal_op; - } - tmp = load_reg(s, rn); - switch (op) { - case 0x0a: /* rbit */ - gen_helper_rbit(tmp, tmp); - break; - case 0x08: /* rev */ - tcg_gen_bswap32_i32(tmp, tmp); - break; - case 0x09: /* rev16 */ - gen_rev16(tmp); - break; - case 0x0b: /* revsh */ - gen_revsh(tmp); - break; - case 0x10: /* sel */ - tmp2 = load_reg(s, rm); - tmp3 = tcg_temp_new_i32(); - tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE)); - gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); - tcg_temp_free_i32(tmp3); - tcg_temp_free_i32(tmp2); - break; - default: - g_assert_not_reached(); - } - } - store_reg(s, rd, tmp); - break; case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */ switch ((insn >> 20) & 7) { case 0: /* 32 x 32 -> 32 */ @@ -10851,60 +10826,8 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) * - Data-processing (plain binary immediate) */ if (insn & (1 << 24)) { - if (insn & (1 << 20)) - goto illegal_op; - /* Bitfield/Saturate. */ - op = (insn >> 21) & 7; - imm = insn & 0x1f; - shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); - if (rn == 15) { - tmp = tcg_temp_new_i32(); - tcg_gen_movi_i32(tmp, 0); - } else { - tmp = load_reg(s, rn); - } - switch (op) { - case 2: /* Signed bitfield extract, in decodetree */ - case 6: /* Unsigned bitfield extract, in decodetree */ - case 3: /* Bitfield insert/clear, in decodetree */ - case 7: - goto illegal_op; - default: /* Saturate. */ - if (op & 1) { - tcg_gen_sari_i32(tmp, tmp, shift); - } else { - tcg_gen_shli_i32(tmp, tmp, shift); - } - tmp2 = tcg_const_i32(imm); - if (op & 4) { - /* Unsigned. */ - if ((op & 1) && shift == 0) { - if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(tmp2); - goto illegal_op; - } - gen_helper_usat16(tmp, cpu_env, tmp, tmp2); - } else { - gen_helper_usat(tmp, cpu_env, tmp, tmp2); - } - } else { - /* Signed. */ - if ((op & 1) && shift == 0) { - if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { - tcg_temp_free_i32(tmp); - tcg_temp_free_i32(tmp2); - goto illegal_op; - } - gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); - } else { - gen_helper_ssat(tmp, cpu_env, tmp, tmp2); - } - } - tcg_temp_free_i32(tmp2); - break; - } - store_reg(s, rd, tmp); + /* Bitfield/Saturate, in decodetree */ + goto illegal_op; } else { imm = ((insn & 0x04000000) >> 15) | ((insn & 0x7000) >> 4) | (insn & 0xff); @@ -11596,8 +11519,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn) tmp = load_reg(s, rn); switch (op1) { case 0: tcg_gen_bswap32_i32(tmp, tmp); break; - case 1: gen_rev16(tmp); break; - case 3: gen_revsh(tmp); break; + case 1: gen_rev16(tmp, tmp); break; + case 3: gen_revsh(tmp, tmp); break; default: g_assert_not_reached(); } |