static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)

{

    uint32_t insn, imm, shift, offset;

    uint32_t rd, rn, rm, rs;

    TCGv tmp;

    TCGv tmp2;

    TCGv tmp3;

    TCGv addr;

    TCGv_i64 tmp64;

    int op;

    int shiftop;

    int conds;

    int logic_cc;



    if (!(arm_feature(env, ARM_FEATURE_THUMB2)

          || arm_feature (env, ARM_FEATURE_M))) {

        /* Thumb-1 cores may need to treat bl and blx as a pair of

           16-bit instructions to get correct prefetch abort behavior.  */

        insn = insn_hw1;

        if ((insn & (1 << 12)) == 0) {

            /* Second half of blx.  */

            offset = ((insn & 0x7ff) << 1);

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);



            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if (insn & (1 << 11)) {

            /* Second half of bl.  */

            offset = ((insn & 0x7ff) << 1) | 1;

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);



            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {

            /* Instruction spans a page boundary.  Implement it as two

               16-bit instructions in case the second half causes an

               prefetch abort.  */

            offset = ((int32_t)insn << 21) >> 9;

            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);

            return 0;

        }

        /* Fall through to 32-bit decode.  */

    }



    insn = lduw_code(s->pc);

    s->pc += 2;

    insn |= (uint32_t)insn_hw1 << 16;



    if ((insn & 0xf800e800) != 0xf000e800) {

        ARCH(6T2);

    }



    rn = (insn >> 16) & 0xf;

    rs = (insn >> 12) & 0xf;

    rd = (insn >> 8) & 0xf;

    rm = insn & 0xf;

    switch ((insn >> 25) & 0xf) {

    case 0: case 1: case 2: case 3:

        /* 16-bit instructions.  Should never happen.  */

        abort();

    case 4:

        if (insn & (1 << 22)) {

            /* Other load/store, table branch.  */

            if (insn & 0x01200000) {

                /* Load/store doubleword.  */

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, s->pc & ~3);

                } else {

                    addr = load_reg(s, rn);

                }

                offset = (insn & 0xff) * 4;

                if ((insn & (1 << 23)) == 0)

                    offset = -offset;

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, offset);

                    offset = 0;

                }

                if (insn & (1 << 20)) {

                    /* ldrd */

                    tmp = gen_ld32(addr, IS_USER(s));

                    store_reg(s, rs, tmp);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = gen_ld32(addr, IS_USER(s));

                    store_reg(s, rd, tmp);

                } else {

                    /* strd */

                    tmp = load_reg(s, rs);

                    gen_st32(tmp, addr, IS_USER(s));

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = load_reg(s, rd);

                    gen_st32(tmp, addr, IS_USER(s));

                }

                if (insn & (1 << 21)) {

                    /* Base writeback.  */

                    if (rn == 15)

                        goto illegal_op;

                    tcg_gen_addi_i32(addr, addr, offset - 4);

                    store_reg(s, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            } else if ((insn & (1 << 23)) == 0) {

                /* Load/store exclusive word.  */

                addr = tcg_temp_local_new();

                load_reg_var(s, addr, rn);

                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(s, rs, 15, addr, 2);

                } else {

                    gen_store_exclusive(s, rd, rs, 15, addr, 2);

                }

                tcg_temp_free(addr);

            } else if ((insn & (1 << 6)) == 0) {

                /* Table Branch.  */

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, s->pc);

                } else {

                    addr = load_reg(s, rn);

                }

                tmp = load_reg(s, rm);

                tcg_gen_add_i32(addr, addr, tmp);

                if (insn & (1 << 4)) {

                    /* tbh */

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    tmp = gen_ld16u(addr, IS_USER(s));

                } else { /* tbb */

                    dead_tmp(tmp);

                    tmp = gen_ld8u(addr, IS_USER(s));

                }

                dead_tmp(addr);

                tcg_gen_shli_i32(tmp, tmp, 1);

                tcg_gen_addi_i32(tmp, tmp, s->pc);

                store_reg(s, 15, tmp);

            } else {

                /* Load/store exclusive byte/halfword/doubleword.  */

                ARCH(7);

                op = (insn >> 4) & 0x3;

                if (op == 2) {

                    goto illegal_op;

                }

                addr = tcg_temp_local_new();

                load_reg_var(s, addr, rn);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(s, rs, rd, addr, op);

                } else {

                    gen_store_exclusive(s, rm, rs, rd, addr, op);

                }

                tcg_temp_free(addr);

            }

        } else {

            /* Load/store multiple, RFE, SRS.  */

            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {

                /* Not available in user mode.  */

                if (IS_USER(s))

                    goto illegal_op;

                if (insn & (1 << 20)) {

                    /* rfe */

                    addr = load_reg(s, rn);

                    if ((insn & (1 << 24)) == 0)

                        tcg_gen_addi_i32(addr, addr, -8);

                    /* Load PC into tmp and CPSR into tmp2.  */

                    tmp = gen_ld32(addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp2 = gen_ld32(addr, 0);

                    if (insn & (1 << 21)) {

                        /* Base writeback.  */

                        if (insn & (1 << 24)) {

                            tcg_gen_addi_i32(addr, addr, 4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, -4);

                        }

                        store_reg(s, rn, addr);

                    } else {

                        dead_tmp(addr);

                    }

                    gen_rfe(s, tmp, tmp2);

                } else {

                    /* srs */

                    op = (insn & 0x1f);

                    if (op == (env->uncached_cpsr & CPSR_M)) {

                        addr = load_reg(s, 13);

                    } else {

                        addr = new_tmp();

                        tmp = tcg_const_i32(op);

                        gen_helper_get_r13_banked(addr, cpu_env, tmp);

                        tcg_temp_free_i32(tmp);

                    }

                    if ((insn & (1 << 24)) == 0) {

                        tcg_gen_addi_i32(addr, addr, -8);

                    }

                    tmp = load_reg(s, 14);

                    gen_st32(tmp, addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = new_tmp();

                    gen_helper_cpsr_read(tmp);

                    gen_st32(tmp, addr, 0);

                    if (insn & (1 << 21)) {

                        if ((insn & (1 << 24)) == 0) {

                            tcg_gen_addi_i32(addr, addr, -4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, 4);

                        }

                        if (op == (env->uncached_cpsr & CPSR_M)) {

                            store_reg(s, 13, addr);

                        } else {

                            tmp = tcg_const_i32(op);

                            gen_helper_set_r13_banked(cpu_env, tmp, addr);

                            tcg_temp_free_i32(tmp);

                        }

                    } else {

                        dead_tmp(addr);

                    }

                }

            } else {

                int i;

                /* Load/store multiple.  */

                addr = load_reg(s, rn);

                offset = 0;

                for (i = 0; i < 16; i++) {

                    if (insn & (1 << i))

                        offset += 4;

                }

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, -offset);

                }



                for (i = 0; i < 16; i++) {

                    if ((insn & (1 << i)) == 0)

                        continue;

                    if (insn & (1 << 20)) {

                        /* Load.  */

                        tmp = gen_ld32(addr, IS_USER(s));

                        if (i == 15) {

                            gen_bx(s, tmp);

                        } else {

                            store_reg(s, i, tmp);

                        }

                    } else {

                        /* Store.  */

                        tmp = load_reg(s, i);

                        gen_st32(tmp, addr, IS_USER(s));

                    }

                    tcg_gen_addi_i32(addr, addr, 4);

                }

                if (insn & (1 << 21)) {

                    /* Base register writeback.  */

                    if (insn & (1 << 24)) {

                        tcg_gen_addi_i32(addr, addr, -offset);

                    }

                    /* Fault if writeback register is in register list.  */

                    if (insn & (1 << rn))

                        goto illegal_op;

                    store_reg(s, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            }

        }

        break;

    case 5:



        op = (insn >> 21) & 0xf;

        if (op == 6) {

            /* 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_andi_i32(tmp, tmp, 0xffff0000);

                tcg_gen_ext16u_i32(tmp2, tmp2);

            } else {

                /* pkhbt */

                if (shift)

                    tcg_gen_shli_i32(tmp2, tmp2, shift);

                tcg_gen_ext16u_i32(tmp, tmp);

                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

            }

            tcg_gen_or_i32(tmp, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(s, rd, tmp);

        } else {

            /* Data processing register constant shift.  */

            if (rn == 15) {

                tmp = new_tmp();

                tcg_gen_movi_i32(tmp, 0);

            } else {

                tmp = load_reg(s, rn);

            }

            tmp2 = load_reg(s, rm);



            shiftop = (insn >> 4) & 3;

            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

            conds = (insn & (1 << 20)) != 0;

            logic_cc = (conds && thumb2_logic_op(op));

            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);

            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))

                goto illegal_op;

            dead_tmp(tmp2);

            if (rd != 15) {

                store_reg(s, rd, tmp);

            } else {

                dead_tmp(tmp);

            }

        }

        break;

    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.  */

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((insn & 0x70) != 0)

                goto illegal_op;

            op = (insn >> 21) & 3;

            logic_cc = (insn & (1 << 20)) != 0;

            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);

            if (logic_cc)

                gen_logic_CC(tmp);

            store_reg_bx(env, s, rd, tmp);

            break;

        case 1: /* Sign/zero extend.  */

            tmp = load_reg(s, rm);

            shift = (insn >> 4) & 3;

            /* ??? In many cases it's not neccessary to do a

               rotate, a shift is sufficient.  */

            if (shift != 0)

                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: goto illegal_op;

            }

            if (rn != 15) {

                tmp2 = load_reg(s, rn);

                if ((op >> 1) == 1) {

                    gen_add16(tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 2: /* SIMD add/subtract.  */

            op = (insn >> 20) & 7;

            shift = (insn >> 4) & 7;

            if ((op & 3) == 3 || (shift & 3) == 3)

                goto illegal_op;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(s, rd, tmp);

            break;

        case 3: /* Other data processing.  */

            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);

            if (op < 4) {

                /* Saturating add/subtract.  */

                tmp = load_reg(s, rn);

                tmp2 = load_reg(s, rm);

                if (op & 1)

                    gen_helper_double_saturate(tmp, tmp);

                if (op & 2)

                    gen_helper_sub_saturate(tmp, tmp2, tmp);

                else

                    gen_helper_add_saturate(tmp, tmp, tmp2);

                dead_tmp(tmp2);

            } else {

                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 = new_tmp();

                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));

                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);

                    dead_tmp(tmp3);

                    dead_tmp(tmp2);

                    break;

                case 0x18: /* clz */

                    gen_helper_clz(tmp, tmp);

                    break;

                default:

                    goto illegal_op;

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */

            op = (insn >> 4) & 0xf;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            switch ((insn >> 20) & 7) {

            case 0: /* 32 x 32 -> 32 */

                tcg_gen_mul_i32(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    if (op)

                        tcg_gen_sub_i32(tmp, tmp2, tmp);

                    else

                        tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 1: /* 16 x 16 -> 32 */

                gen_mulxy(tmp, tmp2, op & 2, op & 1);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 2: /* Dual multiply add.  */

            case 4: /* Dual multiply subtract.  */

                if (op)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                /* This addition cannot overflow.  */

                if (insn & (1 << 22)) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 3: /* 32 * 16 -> 32msb */

                if (op)

                    tcg_gen_sari_i32(tmp2, tmp2, 16);

                else

                    gen_sxth(tmp2);

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                tcg_gen_shri_i64(tmp64, tmp64, 16);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                if (rs != 15) {

                    tmp = load_reg(s, rs);

                    if (insn & (1 << 20)) {

                        tmp64 = gen_addq_msw(tmp64, tmp);

                    } else {

                        tmp64 = gen_subq_msw(tmp64, tmp);

                    }

                }

                if (insn & (1 << 4)) {

                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);

                }

                tcg_gen_shri_i64(tmp64, tmp64, 32);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                break;

            case 7: /* Unsigned sum of absolute differences.  */

                gen_helper_usad8(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            }

            store_reg(s, rd, tmp);

            break;

        case 6: case 7: /* 64-bit multiply, Divide.  */

            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((op & 0x50) == 0x10) {

                /* sdiv, udiv */

                if (!arm_feature(env, ARM_FEATURE_DIV))

                    goto illegal_op;

                if (op & 0x20)

                    gen_helper_udiv(tmp, tmp, tmp2);

                else

                    gen_helper_sdiv(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                store_reg(s, rd, tmp);

            } else if ((op & 0xe) == 0xc) {

                /* Dual multiply accumulate long.  */

                if (op & 1)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                if (op & 0x10) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                /* BUGFIX */

                tmp64 = tcg_temp_new_i64();

                tcg_gen_ext_i32_i64(tmp64, tmp);

                dead_tmp(tmp);

                gen_addq(s, tmp64, rs, rd);

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            } else {

                if (op & 0x20) {

                    /* Unsigned 64-bit multiply  */

                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                } else {

                    if (op & 8) {

                        /* smlalxy */

                        gen_mulxy(tmp, tmp2, op & 2, op & 1);

                        dead_tmp(tmp2);

                        tmp64 = tcg_temp_new_i64();

                        tcg_gen_ext_i32_i64(tmp64, tmp);

                        dead_tmp(tmp);

                    } else {

                        /* Signed 64-bit multiply  */

                        tmp64 = gen_muls_i64_i32(tmp, tmp2);

                    }

                }

                if (op & 4) {

                    /* umaal */

                    gen_addq_lo(s, tmp64, rs);

                    gen_addq_lo(s, tmp64, rd);

                } else if (op & 0x40) {

                    /* 64-bit accumulate.  */

                    gen_addq(s, tmp64, rs, rd);

                }

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            }

            break;

        }

        break;

    case 6: case 7: case 14: case 15:

        /* Coprocessor.  */

        if (((insn >> 24) & 3) == 3) {

            /* Translate into the equivalent ARM encoding.  */

            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);

            if (disas_neon_data_insn(env, s, insn))

                goto illegal_op;

        } else {

            if (insn & (1 << 28))

                goto illegal_op;

            if (disas_coproc_insn (env, s, insn))

                goto illegal_op;

        }

        break;

    case 8: case 9: case 10: case 11:

        if (insn & (1 << 15)) {

            /* Branches, misc control.  */

            if (insn & 0x5000) {

                /* Unconditional branch.  */

                /* signextend(hw1[10:0]) -> offset[:12].  */

                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;

                /* hw1[10:0] -> offset[11:1].  */

                offset |= (insn & 0x7ff) << 1;

                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]

                   offset[24:22] already have the same value because of the

                   sign extension above.  */

                offset ^= ((~insn) & (1 << 13)) << 10;

                offset ^= ((~insn) & (1 << 11)) << 11;



                if (insn & (1 << 14)) {

                    /* Branch and link.  */

                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);

                }



                offset += s->pc;

                if (insn & (1 << 12)) {

                    /* b/bl */

                    gen_jmp(s, offset);

                } else {

                    /* blx */

                    offset &= ~(uint32_t)2;

                    gen_bx_im(s, offset);

                }

            } else if (((insn >> 23) & 7) == 7) {

                /* Misc control */

                if (insn & (1 << 13))

                    goto illegal_op;



                if (insn & (1 << 26)) {

                    /* Secure monitor call (v6Z) */

                    goto illegal_op; /* not implemented.  */

                } else {

                    op = (insn >> 20) & 7;

                    switch (op) {

                    case 0: /* msr cpsr.  */

                        if (IS_M(env)) {

                            tmp = load_reg(s, rn);

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_msr(cpu_env, addr, tmp);

                            tcg_temp_free_i32(addr);

                            dead_tmp(tmp);

                            gen_lookup_tb(s);

                            break;

                        }

                        /* fall through */

                    case 1: /* msr spsr.  */

                        if (IS_M(env))

                            goto illegal_op;

                        tmp = load_reg(s, rn);

                        if (gen_set_psr(s,

                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),

                              op == 1, tmp))

                            goto illegal_op;

                        break;

                    case 2: /* cps, nop-hint.  */

                        if (((insn >> 8) & 7) == 0) {

                            gen_nop_hint(s, insn & 0xff);

                        }

                        /* Implemented as NOP in user mode.  */

                        if (IS_USER(s))

                            break;

                        offset = 0;

                        imm = 0;

                        if (insn & (1 << 10)) {

                            if (insn & (1 << 7))

                                offset |= CPSR_A;

                            if (insn & (1 << 6))

                                offset |= CPSR_I;

                            if (insn & (1 << 5))

                                offset |= CPSR_F;

                            if (insn & (1 << 9))

                                imm = CPSR_A | CPSR_I | CPSR_F;

                        }

                        if (insn & (1 << 8)) {

                            offset |= 0x1f;

                            imm |= (insn & 0x1f);

                        }

                        if (offset) {

                            gen_set_psr_im(s, offset, 0, imm);

                        }

                        break;

                    case 3: /* Special control operations.  */

                        ARCH(7);

                        op = (insn >> 4) & 0xf;

                        switch (op) {

                        case 2: /* clrex */

                            gen_clrex(s);

                            break;

                        case 4: /* dsb */

                        case 5: /* dmb */

                        case 6: /* isb */

                            /* These execute as NOPs.  */

                            break;

                        default:

                            goto illegal_op;

                        }

                        break;

                    case 4: /* bxj */

                        /* Trivial implementation equivalent to bx.  */

                        tmp = load_reg(s, rn);

                        gen_bx(s, tmp);

                        break;

                    case 5: /* Exception return.  */

                        if (IS_USER(s)) {

                            goto illegal_op;

                        }

                        if (rn != 14 || rd != 15) {

                            goto illegal_op;

                        }

                        tmp = load_reg(s, rn);

                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);

                        gen_exception_return(s, tmp);

                        break;

                    case 6: /* mrs cpsr.  */

                        tmp = new_tmp();

                        if (IS_M(env)) {

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_mrs(tmp, cpu_env, addr);

                            tcg_temp_free_i32(addr);

                        } else {

                            gen_helper_cpsr_read(tmp);

                        }

                        store_reg(s, rd, tmp);

                        break;

                    case 7: /* mrs spsr.  */

                        /* Not accessible in user mode.  */

                        if (IS_USER(s) || IS_M(env))

                            goto illegal_op;

                        tmp = load_cpu_field(spsr);

                        store_reg(s, rd, tmp);

                        break;

                    }

                }

            } else {

                /* Conditional branch.  */

                op = (insn >> 22) & 0xf;

                /* Generate a conditional jump to next instruction.  */

                s->condlabel = gen_new_label();

                gen_test_cc(op ^ 1, s->condlabel);

                s->condjmp = 1;



                /* offset[11:1] = insn[10:0] */

                offset = (insn & 0x7ff) << 1;

                /* offset[17:12] = insn[21:16].  */

                offset |= (insn & 0x003f0000) >> 4;

                /* offset[31:20] = insn[26].  */

                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;

                /* offset[18] = insn[13].  */

                offset |= (insn & (1 << 13)) << 5;

                /* offset[19] = insn[11].  */

                offset |= (insn & (1 << 11)) << 8;



                /* jump to the offset */

                gen_jmp(s, s->pc + offset);

            }

        } else {

            /* Data processing immediate.  */

            if (insn & (1 << 25)) {

                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 = new_tmp();

                        tcg_gen_movi_i32(tmp, 0);

                    } else {

                        tmp = load_reg(s, rn);

                    }

                    switch (op) {

                    case 2: /* Signed bitfield extract.  */

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_sbfx(tmp, shift, imm);

                        break;

                    case 6: /* Unsigned bitfield extract.  */

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_ubfx(tmp, shift, (1u << imm) - 1);

                        break;

                    case 3: /* Bitfield insert/clear.  */

                        if (imm < shift)

                            goto illegal_op;

                        imm = imm + 1 - shift;

                        if (imm != 32) {

                            tmp2 = load_reg(s, rd);

                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);

                            dead_tmp(tmp2);

                        }

                        break;

                    case 7:

                        goto illegal_op;

                    default: /* Saturate.  */

                        if (shift) {

                            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)

                                gen_helper_usat16(tmp, tmp, tmp2);

                            else

                                gen_helper_usat(tmp, tmp, tmp2);

                        } else {

                            /* Signed.  */

                            if ((op & 1) && shift == 0)

                                gen_helper_ssat16(tmp, tmp, tmp2);

                            else

                                gen_helper_ssat(tmp, tmp, tmp2);

                        }

                        tcg_temp_free_i32(tmp2);

                        break;

                    }

                    store_reg(s, rd, tmp);

                } else {

                    imm = ((insn & 0x04000000) >> 15)

                          | ((insn & 0x7000) >> 4) | (insn & 0xff);

                    if (insn & (1 << 22)) {

                        /* 16-bit immediate.  */

                        imm |= (insn >> 4) & 0xf000;

                        if (insn & (1 << 23)) {

                            /* movt */

                            tmp = load_reg(s, rd);

                            tcg_gen_ext16u_i32(tmp, tmp);

                            tcg_gen_ori_i32(tmp, tmp, imm << 16);

                        } else {

                            /* movw */

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, imm);

                        }

                    } else {

                        /* Add/sub 12-bit immediate.  */

                        if (rn == 15) {

                            offset = s->pc & ~(uint32_t)3;

                            if (insn & (1 << 23))

                                offset -= imm;

                            else

                                offset += imm;

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, offset);

                        } else {

                            tmp = load_reg(s, rn);

                            if (insn & (1 << 23))

                                tcg_gen_subi_i32(tmp, tmp, imm);

                            else

                                tcg_gen_addi_i32(tmp, tmp, imm);

                        }

                    }

                    store_reg(s, rd, tmp);

                }

            } else {

                int shifter_out = 0;

                /* modified 12-bit immediate.  */

                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);

                imm = (insn & 0xff);

                switch (shift) {

                case 0: /* XY */

                    /* Nothing to do.  */

                    break;

                case 1: /* 00XY00XY */

                    imm |= imm << 16;

                    break;

                case 2: /* XY00XY00 */

                    imm |= imm << 16;

                    imm <<= 8;

                    break;

                case 3: /* XYXYXYXY */

                    imm |= imm << 16;

                    imm |= imm << 8;

                    break;

                default: /* Rotated constant.  */

                    shift = (shift << 1) | (imm >> 7);

                    imm |= 0x80;

                    imm = imm << (32 - shift);

                    shifter_out = 1;

                    break;

                }

                tmp2 = new_tmp();

                tcg_gen_movi_i32(tmp2, imm);

                rn = (insn >> 16) & 0xf;

                if (rn == 15) {

                    tmp = new_tmp();

                    tcg_gen_movi_i32(tmp, 0);

                } else {

                    tmp = load_reg(s, rn);

                }

                op = (insn >> 21) & 0xf;

                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,

                                       shifter_out, tmp, tmp2))

                    goto illegal_op;

                dead_tmp(tmp2);

                rd = (insn >> 8) & 0xf;

                if (rd != 15) {

                    store_reg(s, rd, tmp);

                } else {

                    dead_tmp(tmp);

                }

            }

        }

        break;

    case 12: /* Load/store single data item.  */

        {

        int postinc = 0;

        int writeback = 0;

        int user;

        if ((insn & 0x01100000) == 0x01000000) {

            if (disas_neon_ls_insn(env, s, insn))

                goto illegal_op;

            break;

        }

        user = IS_USER(s);

        if (rn == 15) {

            addr = new_tmp();

            /* PC relative.  */

            /* s->pc has already been incremented by 4.  */

            imm = s->pc & 0xfffffffc;

            if (insn & (1 << 23))

                imm += insn & 0xfff;

            else

                imm -= insn & 0xfff;

            tcg_gen_movi_i32(addr, imm);

        } else {

            addr = load_reg(s, rn);

            if (insn & (1 << 23)) {

                /* Positive offset.  */

                imm = insn & 0xfff;

                tcg_gen_addi_i32(addr, addr, imm);

            } else {

                op = (insn >> 8) & 7;

                imm = insn & 0xff;

                switch (op) {

                case 0: case 8: /* Shifted Register.  */

                    shift = (insn >> 4) & 0xf;

                    if (shift > 3)

                        goto illegal_op;

                    tmp = load_reg(s, rm);

                    if (shift)

                        tcg_gen_shli_i32(tmp, tmp, shift);

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    break;

                case 4: /* Negative offset.  */

                    tcg_gen_addi_i32(addr, addr, -imm);

                    break;

                case 6: /* User privilege.  */

                    tcg_gen_addi_i32(addr, addr, imm);

                    user = 1;

                    break;

                case 1: /* Post-decrement.  */

                    imm = -imm;

                    /* Fall through.  */

                case 3: /* Post-increment.  */

                    postinc = 1;

                    writeback = 1;

                    break;

                case 5: /* Pre-decrement.  */

                    imm = -imm;

                    /* Fall through.  */

                case 7: /* Pre-increment.  */

                    tcg_gen_addi_i32(addr, addr, imm);

                    writeback = 1;

                    break;

                default:

                    goto illegal_op;

                }

            }

        }

        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);

        if (insn & (1 << 20)) {

            /* Load.  */

            if (rs == 15 && op != 2) {

                if (op & 2)

                    goto illegal_op;

                /* Memory hint.  Implemented as NOP.  */

            } else {

                switch (op) {

                case 0: tmp = gen_ld8u(addr, user); break;

                case 4: tmp = gen_ld8s(addr, user); break;

                case 1: tmp = gen_ld16u(addr, user); break;

                case 5: tmp = gen_ld16s(addr, user); break;

                case 2: tmp = gen_ld32(addr, user); break;

                default: goto illegal_op;

                }

                if (rs == 15) {

                    gen_bx(s, tmp);

                } else {

                    store_reg(s, rs, tmp);

                }

            }

        } else {

            /* Store.  */

            if (rs == 15)

                goto illegal_op;

            tmp = load_reg(s, rs);

            switch (op) {

            case 0: gen_st8(tmp, addr, user); break;

            case 1: gen_st16(tmp, addr, user); break;

            case 2: gen_st32(tmp, addr, user); break;

            default: goto illegal_op;

            }

        }

        if (postinc)

            tcg_gen_addi_i32(addr, addr, imm);

        if (writeback) {

            store_reg(s, rn, addr);

        } else {

            dead_tmp(addr);

        }

        }

        break;

    default:

        goto illegal_op;

    }

    return 0;

illegal_op:

    return 1;

}

static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)

{

    uint32_t insn, imm, shift, offset;

    uint32_t rd, rn, rm, rs;

    TCGv tmp;

    TCGv tmp2;

    TCGv tmp3;

    TCGv addr;

    TCGv_i64 tmp64;

    int op;

    int shiftop;

    int conds;

    int logic_cc;



    if (!(arm_feature(env, ARM_FEATURE_THUMB2)

          || arm_feature (env, ARM_FEATURE_M))) {

        



        insn = insn_hw1;

        if ((insn & (1 << 12)) == 0) {

            

            offset = ((insn & 0x7ff) << 1);

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);



            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if (insn & (1 << 11)) {

            

            offset = ((insn & 0x7ff) << 1) | 1;

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);



            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {

            





            offset = ((int32_t)insn << 21) >> 9;

            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);

            return 0;

        }

        

    }



    insn = lduw_code(s->pc);

    s->pc += 2;

    insn |= (uint32_t)insn_hw1 << 16;



    if ((insn & 0xf800e800) != 0xf000e800) {

        ARCH(6T2);

    }



    rn = (insn >> 16) & 0xf;

    rs = (insn >> 12) & 0xf;

    rd = (insn >> 8) & 0xf;

    rm = insn & 0xf;

    switch ((insn >> 25) & 0xf) {

    case 0: case 1: case 2: case 3:

        

        abort();

    case 4:

        if (insn & (1 << 22)) {

            

            if (insn & 0x01200000) {

                

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, s->pc & ~3);

                } else {

                    addr = load_reg(s, rn);

                }

                offset = (insn & 0xff) * 4;

                if ((insn & (1 << 23)) == 0)

                    offset = -offset;

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, offset);

                    offset = 0;

                }

                if (insn & (1 << 20)) {

                    

                    tmp = gen_ld32(addr, IS_USER(s));

                    store_reg(s, rs, tmp);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = gen_ld32(addr, IS_USER(s));

                    store_reg(s, rd, tmp);

                } else {

                    

                    tmp = load_reg(s, rs);

                    gen_st32(tmp, addr, IS_USER(s));

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = load_reg(s, rd);

                    gen_st32(tmp, addr, IS_USER(s));

                }

                if (insn & (1 << 21)) {

                    

                    if (rn == 15)

                        goto illegal_op;

                    tcg_gen_addi_i32(addr, addr, offset - 4);

                    store_reg(s, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            } else if ((insn & (1 << 23)) == 0) {

                

                addr = tcg_temp_local_new();

                load_reg_var(s, addr, rn);

                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(s, rs, 15, addr, 2);

                } else {

                    gen_store_exclusive(s, rd, rs, 15, addr, 2);

                }

                tcg_temp_free(addr);

            } else if ((insn & (1 << 6)) == 0) {

                

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, s->pc);

                } else {

                    addr = load_reg(s, rn);

                }

                tmp = load_reg(s, rm);

                tcg_gen_add_i32(addr, addr, tmp);

                if (insn & (1 << 4)) {

                    

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    tmp = gen_ld16u(addr, IS_USER(s));

                } else { 

                    dead_tmp(tmp);

                    tmp = gen_ld8u(addr, IS_USER(s));

                }

                dead_tmp(addr);

                tcg_gen_shli_i32(tmp, tmp, 1);

                tcg_gen_addi_i32(tmp, tmp, s->pc);

                store_reg(s, 15, tmp);

            } else {

                

                ARCH(7);

                op = (insn >> 4) & 0x3;

                if (op == 2) {

                    goto illegal_op;

                }

                addr = tcg_temp_local_new();

                load_reg_var(s, addr, rn);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(s, rs, rd, addr, op);

                } else {

                    gen_store_exclusive(s, rm, rs, rd, addr, op);

                }

                tcg_temp_free(addr);

            }

        } else {

            

            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {

                

                if (IS_USER(s))

                    goto illegal_op;

                if (insn & (1 << 20)) {

                    

                    addr = load_reg(s, rn);

                    if ((insn & (1 << 24)) == 0)

                        tcg_gen_addi_i32(addr, addr, -8);

                    

                    tmp = gen_ld32(addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp2 = gen_ld32(addr, 0);

                    if (insn & (1 << 21)) {

                        

                        if (insn & (1 << 24)) {

                            tcg_gen_addi_i32(addr, addr, 4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, -4);

                        }

                        store_reg(s, rn, addr);

                    } else {

                        dead_tmp(addr);

                    }

                    gen_rfe(s, tmp, tmp2);

                } else {

                    

                    op = (insn & 0x1f);

                    if (op == (env->uncached_cpsr & CPSR_M)) {

                        addr = load_reg(s, 13);

                    } else {

                        addr = new_tmp();

                        tmp = tcg_const_i32(op);

                        gen_helper_get_r13_banked(addr, cpu_env, tmp);

                        tcg_temp_free_i32(tmp);

                    }

                    if ((insn & (1 << 24)) == 0) {

                        tcg_gen_addi_i32(addr, addr, -8);

                    }

                    tmp = load_reg(s, 14);

                    gen_st32(tmp, addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = new_tmp();

                    gen_helper_cpsr_read(tmp);

                    gen_st32(tmp, addr, 0);

                    if (insn & (1 << 21)) {

                        if ((insn & (1 << 24)) == 0) {

                            tcg_gen_addi_i32(addr, addr, -4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, 4);

                        }

                        if (op == (env->uncached_cpsr & CPSR_M)) {

                            store_reg(s, 13, addr);

                        } else {

                            tmp = tcg_const_i32(op);

                            gen_helper_set_r13_banked(cpu_env, tmp, addr);

                            tcg_temp_free_i32(tmp);

                        }

                    } else {

                        dead_tmp(addr);

                    }

                }

            } else {

                int i;

                

                addr = load_reg(s, rn);

                offset = 0;

                for (i = 0; i < 16; i++) {

                    if (insn & (1 << i))

                        offset += 4;

                }

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, -offset);

                }



                for (i = 0; i < 16; i++) {

                    if ((insn & (1 << i)) == 0)

                        continue;

                    if (insn & (1 << 20)) {

                        

                        tmp = gen_ld32(addr, IS_USER(s));

                        if (i == 15) {

                            gen_bx(s, tmp);

                        } else {

                            store_reg(s, i, tmp);

                        }

                    } else {

                        

                        tmp = load_reg(s, i);

                        gen_st32(tmp, addr, IS_USER(s));

                    }

                    tcg_gen_addi_i32(addr, addr, 4);

                }

                if (insn & (1 << 21)) {

                    

                    if (insn & (1 << 24)) {

                        tcg_gen_addi_i32(addr, addr, -offset);

                    }

                    

                    if (insn & (1 << rn))

                        goto illegal_op;

                    store_reg(s, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            }

        }

        break;

    case 5:



        op = (insn >> 21) & 0xf;

        if (op == 6) {

            

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);

            if (insn & (1 << 5)) {

                

                if (shift == 0)

                    shift = 31;

                tcg_gen_sari_i32(tmp2, tmp2, shift);

                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);

                tcg_gen_ext16u_i32(tmp2, tmp2);

            } else {

                

                if (shift)

                    tcg_gen_shli_i32(tmp2, tmp2, shift);

                tcg_gen_ext16u_i32(tmp, tmp);

                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

            }

            tcg_gen_or_i32(tmp, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(s, rd, tmp);

        } else {

            

            if (rn == 15) {

                tmp = new_tmp();

                tcg_gen_movi_i32(tmp, 0);

            } else {

                tmp = load_reg(s, rn);

            }

            tmp2 = load_reg(s, rm);



            shiftop = (insn >> 4) & 3;

            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

            conds = (insn & (1 << 20)) != 0;

            logic_cc = (conds && thumb2_logic_op(op));

            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);

            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))

                goto illegal_op;

            dead_tmp(tmp2);

            if (rd != 15) {

                store_reg(s, rd, tmp);

            } else {

                dead_tmp(tmp);

            }

        }

        break;

    case 13: 

        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);

        if (op < 4 && (insn & 0xf000) != 0xf000)

            goto illegal_op;

        switch (op) {

        case 0: 

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((insn & 0x70) != 0)

                goto illegal_op;

            op = (insn >> 21) & 3;

            logic_cc = (insn & (1 << 20)) != 0;

            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);

            if (logic_cc)

                gen_logic_CC(tmp);

            store_reg_bx(env, s, rd, tmp);

            break;

        case 1: 

            tmp = load_reg(s, rm);

            shift = (insn >> 4) & 3;

            



            if (shift != 0)

                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: goto illegal_op;

            }

            if (rn != 15) {

                tmp2 = load_reg(s, rn);

                if ((op >> 1) == 1) {

                    gen_add16(tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 2: 

            op = (insn >> 20) & 7;

            shift = (insn >> 4) & 7;

            if ((op & 3) == 3 || (shift & 3) == 3)

                goto illegal_op;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(s, rd, tmp);

            break;

        case 3: 

            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);

            if (op < 4) {

                

                tmp = load_reg(s, rn);

                tmp2 = load_reg(s, rm);

                if (op & 1)

                    gen_helper_double_saturate(tmp, tmp);

                if (op & 2)

                    gen_helper_sub_saturate(tmp, tmp2, tmp);

                else

                    gen_helper_add_saturate(tmp, tmp, tmp2);

                dead_tmp(tmp2);

            } else {

                tmp = load_reg(s, rn);

                switch (op) {

                case 0x0a: 

                    gen_helper_rbit(tmp, tmp);

                    break;

                case 0x08: 

                    tcg_gen_bswap32_i32(tmp, tmp);

                    break;

                case 0x09: 

                    gen_rev16(tmp);

                    break;

                case 0x0b: 

                    gen_revsh(tmp);

                    break;

                case 0x10: 

                    tmp2 = load_reg(s, rm);

                    tmp3 = new_tmp();

                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));

                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);

                    dead_tmp(tmp3);

                    dead_tmp(tmp2);

                    break;

                case 0x18: 

                    gen_helper_clz(tmp, tmp);

                    break;

                default:

                    goto illegal_op;

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 4: case 5: 

            op = (insn >> 4) & 0xf;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            switch ((insn >> 20) & 7) {

            case 0: 

                tcg_gen_mul_i32(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    if (op)

                        tcg_gen_sub_i32(tmp, tmp2, tmp);

                    else

                        tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 1: 

                gen_mulxy(tmp, tmp2, op & 2, op & 1);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 2: 

            case 4: 

                if (op)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                

                if (insn & (1 << 22)) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 3: 

                if (op)

                    tcg_gen_sari_i32(tmp2, tmp2, 16);

                else

                    gen_sxth(tmp2);

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                tcg_gen_shri_i64(tmp64, tmp64, 16);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 5: case 6: 

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                if (rs != 15) {

                    tmp = load_reg(s, rs);

                    if (insn & (1 << 20)) {

                        tmp64 = gen_addq_msw(tmp64, tmp);

                    } else {

                        tmp64 = gen_subq_msw(tmp64, tmp);

                    }

                }

                if (insn & (1 << 4)) {

                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);

                }

                tcg_gen_shri_i64(tmp64, tmp64, 32);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                break;

            case 7: 

                gen_helper_usad8(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            }

            store_reg(s, rd, tmp);

            break;

        case 6: case 7: 

            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((op & 0x50) == 0x10) {

                

                if (!arm_feature(env, ARM_FEATURE_DIV))

                    goto illegal_op;

                if (op & 0x20)

                    gen_helper_udiv(tmp, tmp, tmp2);

                else

                    gen_helper_sdiv(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                store_reg(s, rd, tmp);

            } else if ((op & 0xe) == 0xc) {

                

                if (op & 1)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                if (op & 0x10) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                

                tmp64 = tcg_temp_new_i64();

                tcg_gen_ext_i32_i64(tmp64, tmp);

                dead_tmp(tmp);

                gen_addq(s, tmp64, rs, rd);

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            } else {

                if (op & 0x20) {

                    

                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                } else {

                    if (op & 8) {

                        

                        gen_mulxy(tmp, tmp2, op & 2, op & 1);

                        dead_tmp(tmp2);

                        tmp64 = tcg_temp_new_i64();

                        tcg_gen_ext_i32_i64(tmp64, tmp);

                        dead_tmp(tmp);

                    } else {

                        

                        tmp64 = gen_muls_i64_i32(tmp, tmp2);

                    }

                }

                if (op & 4) {

                    

                    gen_addq_lo(s, tmp64, rs);

                    gen_addq_lo(s, tmp64, rd);

                } else if (op & 0x40) {

                    

                    gen_addq(s, tmp64, rs, rd);

                }

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            }

            break;

        }

        break;

    case 6: case 7: case 14: case 15:

        

        if (((insn >> 24) & 3) == 3) {

            

            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);

            if (disas_neon_data_insn(env, s, insn))

                goto illegal_op;

        } else {

            if (insn & (1 << 28))

                goto illegal_op;

            if (disas_coproc_insn (env, s, insn))

                goto illegal_op;

        }

        break;

    case 8: case 9: case 10: case 11:

        if (insn & (1 << 15)) {

            

            if (insn & 0x5000) {

                

                

                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;

                

                offset |= (insn & 0x7ff) << 1;

                





                offset ^= ((~insn) & (1 << 13)) << 10;

                offset ^= ((~insn) & (1 << 11)) << 11;



                if (insn & (1 << 14)) {

                    

                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);

                }



                offset += s->pc;

                if (insn & (1 << 12)) {

                    

                    gen_jmp(s, offset);

                } else {

                    

                    offset &= ~(uint32_t)2;

                    gen_bx_im(s, offset);

                }

            } else if (((insn >> 23) & 7) == 7) {

                

                if (insn & (1 << 13))

                    goto illegal_op;



                if (insn & (1 << 26)) {

                    

                    goto illegal_op; 

                } else {

                    op = (insn >> 20) & 7;

                    switch (op) {

                    case 0: 

                        if (IS_M(env)) {

                            tmp = load_reg(s, rn);

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_msr(cpu_env, addr, tmp);

                            tcg_temp_free_i32(addr);

                            dead_tmp(tmp);

                            gen_lookup_tb(s);

                            break;

                        }

                        

                    case 1: 

                        if (IS_M(env))

                            goto illegal_op;

                        tmp = load_reg(s, rn);

                        if (gen_set_psr(s,

                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),

                              op == 1, tmp))

                            goto illegal_op;

                        break;

                    case 2: 

                        if (((insn >> 8) & 7) == 0) {

                            gen_nop_hint(s, insn & 0xff);

                        }

                        

                        if (IS_USER(s))

                            break;

                        offset = 0;

                        imm = 0;

                        if (insn & (1 << 10)) {

                            if (insn & (1 << 7))

                                offset |= CPSR_A;

                            if (insn & (1 << 6))

                                offset |= CPSR_I;

                            if (insn & (1 << 5))

                                offset |= CPSR_F;

                            if (insn & (1 << 9))

                                imm = CPSR_A | CPSR_I | CPSR_F;

                        }

                        if (insn & (1 << 8)) {

                            offset |= 0x1f;

                            imm |= (insn & 0x1f);

                        }

                        if (offset) {

                            gen_set_psr_im(s, offset, 0, imm);

                        }

                        break;

                    case 3: 

                        ARCH(7);

                        op = (insn >> 4) & 0xf;

                        switch (op) {

                        case 2: 

                            gen_clrex(s);

                            break;

                        case 4: 

                        case 5: 

                        case 6: 

                            

                            break;

                        default:

                            goto illegal_op;

                        }

                        break;

                    case 4: 

                        

                        tmp = load_reg(s, rn);

                        gen_bx(s, tmp);

                        break;

                    case 5: 

                        if (IS_USER(s)) {

                            goto illegal_op;

                        }

                        if (rn != 14 || rd != 15) {

                            goto illegal_op;

                        }

                        tmp = load_reg(s, rn);

                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);

                        gen_exception_return(s, tmp);

                        break;

                    case 6: 

                        tmp = new_tmp();

                        if (IS_M(env)) {

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_mrs(tmp, cpu_env, addr);

                            tcg_temp_free_i32(addr);

                        } else {

                            gen_helper_cpsr_read(tmp);

                        }

                        store_reg(s, rd, tmp);

                        break;

                    case 7: 

                        

                        if (IS_USER(s) || IS_M(env))

                            goto illegal_op;

                        tmp = load_cpu_field(spsr);

                        store_reg(s, rd, tmp);

                        break;

                    }

                }

            } else {

                

                op = (insn >> 22) & 0xf;

                

                s->condlabel = gen_new_label();

                gen_test_cc(op ^ 1, s->condlabel);

                s->condjmp = 1;



                

                offset = (insn & 0x7ff) << 1;

                

                offset |= (insn & 0x003f0000) >> 4;

                

                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;

                

                offset |= (insn & (1 << 13)) << 5;

                

                offset |= (insn & (1 << 11)) << 8;



                

                gen_jmp(s, s->pc + offset);

            }

        } else {

            

            if (insn & (1 << 25)) {

                if (insn & (1 << 24)) {

                    if (insn & (1 << 20))

                        goto illegal_op;

                    

                    op = (insn >> 21) & 7;

                    imm = insn & 0x1f;

                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

                    if (rn == 15) {

                        tmp = new_tmp();

                        tcg_gen_movi_i32(tmp, 0);

                    } else {

                        tmp = load_reg(s, rn);

                    }

                    switch (op) {

                    case 2: 

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_sbfx(tmp, shift, imm);

                        break;

                    case 6: 

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_ubfx(tmp, shift, (1u << imm) - 1);

                        break;

                    case 3: 

                        if (imm < shift)

                            goto illegal_op;

                        imm = imm + 1 - shift;

                        if (imm != 32) {

                            tmp2 = load_reg(s, rd);

                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);

                            dead_tmp(tmp2);

                        }

                        break;

                    case 7:

                        goto illegal_op;

                    default: 

                        if (shift) {

                            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) {

                            

                            if ((op & 1) && shift == 0)

                                gen_helper_usat16(tmp, tmp, tmp2);

                            else

                                gen_helper_usat(tmp, tmp, tmp2);

                        } else {

                            

                            if ((op & 1) && shift == 0)

                                gen_helper_ssat16(tmp, tmp, tmp2);

                            else

                                gen_helper_ssat(tmp, tmp, tmp2);

                        }

                        tcg_temp_free_i32(tmp2);

                        break;

                    }

                    store_reg(s, rd, tmp);

                } else {

                    imm = ((insn & 0x04000000) >> 15)

                          | ((insn & 0x7000) >> 4) | (insn & 0xff);

                    if (insn & (1 << 22)) {

                        

                        imm |= (insn >> 4) & 0xf000;

                        if (insn & (1 << 23)) {

                            

                            tmp = load_reg(s, rd);

                            tcg_gen_ext16u_i32(tmp, tmp);

                            tcg_gen_ori_i32(tmp, tmp, imm << 16);

                        } else {

                            

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, imm);

                        }

                    } else {

                        

                        if (rn == 15) {

                            offset = s->pc & ~(uint32_t)3;

                            if (insn & (1 << 23))

                                offset -= imm;

                            else

                                offset += imm;

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, offset);

                        } else {

                            tmp = load_reg(s, rn);

                            if (insn & (1 << 23))

                                tcg_gen_subi_i32(tmp, tmp, imm);

                            else

                                tcg_gen_addi_i32(tmp, tmp, imm);

                        }

                    }

                    store_reg(s, rd, tmp);

                }

            } else {

                int shifter_out = 0;

                

                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);

                imm = (insn & 0xff);

                switch (shift) {

                case 0: 

                    

                    break;

                case 1: 

                    imm |= imm << 16;

                    break;

                case 2: 

                    imm |= imm << 16;

                    imm <<= 8;

                    break;

                case 3: 

                    imm |= imm << 16;

                    imm |= imm << 8;

                    break;

                default: 

                    shift = (shift << 1) | (imm >> 7);

                    imm |= 0x80;

                    imm = imm << (32 - shift);

                    shifter_out = 1;

                    break;

                }

                tmp2 = new_tmp();

                tcg_gen_movi_i32(tmp2, imm);

                rn = (insn >> 16) & 0xf;

                if (rn == 15) {

                    tmp = new_tmp();

                    tcg_gen_movi_i32(tmp, 0);

                } else {

                    tmp = load_reg(s, rn);

                }

                op = (insn >> 21) & 0xf;

                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,

                                       shifter_out, tmp, tmp2))

                    goto illegal_op;

                dead_tmp(tmp2);

                rd = (insn >> 8) & 0xf;

                if (rd != 15) {

                    store_reg(s, rd, tmp);

                } else {

                    dead_tmp(tmp);

                }

            }

        }

        break;

    case 12: 

        {

        int postinc = 0;

        int writeback = 0;

        int user;

        if ((insn & 0x01100000) == 0x01000000) {

            if (disas_neon_ls_insn(env, s, insn))

                goto illegal_op;

            break;

        }

        user = IS_USER(s);

        if (rn == 15) {

            addr = new_tmp();

            

            

            imm = s->pc & 0xfffffffc;

            if (insn & (1 << 23))

                imm += insn & 0xfff;

            else

                imm -= insn & 0xfff;

            tcg_gen_movi_i32(addr, imm);

        } else {

            addr = load_reg(s, rn);

            if (insn & (1 << 23)) {

                

                imm = insn & 0xfff;

                tcg_gen_addi_i32(addr, addr, imm);

            } else {

                op = (insn >> 8) & 7;

                imm = insn & 0xff;

                switch (op) {

                case 0: case 8: 

                    shift = (insn >> 4) & 0xf;

                    if (shift > 3)

                        goto illegal_op;

                    tmp = load_reg(s, rm);

                    if (shift)

                        tcg_gen_shli_i32(tmp, tmp, shift);

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    break;

                case 4: 

                    tcg_gen_addi_i32(addr, addr, -imm);

                    break;

                case 6: 

                    tcg_gen_addi_i32(addr, addr, imm);

                    user = 1;

                    break;

                case 1: 

                    imm = -imm;

                    

                case 3: 

                    postinc = 1;

                    writeback = 1;

                    break;

                case 5: 

                    imm = -imm;

                    

                case 7: 

                    tcg_gen_addi_i32(addr, addr, imm);

                    writeback = 1;

                    break;

                default:

                    goto illegal_op;

                }

            }

        }

        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);

        if (insn & (1 << 20)) {

            

            if (rs == 15 && op != 2) {

                if (op & 2)

                    goto illegal_op;

                

            } else {

                switch (op) {

                case 0: tmp = gen_ld8u(addr, user); break;

                case 4: tmp = gen_ld8s(addr, user); break;

                case 1: tmp = gen_ld16u(addr, user); break;

                case 5: tmp = gen_ld16s(addr, user); break;

                case 2: tmp = gen_ld32(addr, user); break;

                default: goto illegal_op;

                }

                if (rs == 15) {

                    gen_bx(s, tmp);

                } else {

                    store_reg(s, rs, tmp);

                }

            }

        } else {

            

            if (rs == 15)

                goto illegal_op;

            tmp = load_reg(s, rs);

            switch (op) {

            case 0: gen_st8(tmp, addr, user); break;

            case 1: gen_st16(tmp, addr, user); break;

            case 2: gen_st32(tmp, addr, user); break;

            default: goto illegal_op;

            }

        }

        if (postinc)

            tcg_gen_addi_i32(addr, addr, imm);

        if (writeback) {

            store_reg(s, rn, addr);

        } else {

            dead_tmp(addr);

        }

        }

        break;

    default:

        goto illegal_op;

    }

    return 0;

illegal_op:

    return 1;

}

static int FUNC_0(CPUState *VAR_0, DisasContext *VAR_1, uint16_t VAR_2)

{

    uint32_t insn, imm, shift, offset;

    uint32_t rd, rn, rm, rs;

    TCGv tmp;

    TCGv tmp2;

    TCGv tmp3;

    TCGv addr;

    TCGv_i64 tmp64;

    int VAR_3;

    int VAR_4;

    int VAR_5;

    int VAR_6;



    if (!(arm_feature(VAR_0, ARM_FEATURE_THUMB2)

          || arm_feature (VAR_0, ARM_FEATURE_M))) {

        



        insn = VAR_2;

        if ((insn & (1 << 12)) == 0) {

            

            offset = ((insn & 0x7ff) << 1);

            tmp = load_reg(VAR_1, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);



            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, VAR_1->pc | 1);

            store_reg(VAR_1, 14, tmp2);

            gen_bx(VAR_1, tmp);

            return 0;

        }

        if (insn & (1 << 11)) {

            

            offset = ((insn & 0x7ff) << 1) | 1;

            tmp = load_reg(VAR_1, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);



            tmp2 = new_tmp();

            tcg_gen_movi_i32(tmp2, VAR_1->pc | 1);

            store_reg(VAR_1, 14, tmp2);

            gen_bx(VAR_1, tmp);

            return 0;

        }

        if ((VAR_1->pc & ~TARGET_PAGE_MASK) == 0) {

            





            offset = ((int32_t)insn << 21) >> 9;

            tcg_gen_movi_i32(cpu_R[14], VAR_1->pc + 2 + offset);

            return 0;

        }

        

    }



    insn = lduw_code(VAR_1->pc);

    VAR_1->pc += 2;

    insn |= (uint32_t)VAR_2 << 16;



    if ((insn & 0xf800e800) != 0xf000e800) {

        ARCH(6T2);

    }



    rn = (insn >> 16) & 0xf;

    rs = (insn >> 12) & 0xf;

    rd = (insn >> 8) & 0xf;

    rm = insn & 0xf;

    switch ((insn >> 25) & 0xf) {

    case 0: case 1: case 2: case 3:

        

        abort();

    case 4:

        if (insn & (1 << 22)) {

            

            if (insn & 0x01200000) {

                

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, VAR_1->pc & ~3);

                } else {

                    addr = load_reg(VAR_1, rn);

                }

                offset = (insn & 0xff) * 4;

                if ((insn & (1 << 23)) == 0)

                    offset = -offset;

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, offset);

                    offset = 0;

                }

                if (insn & (1 << 20)) {

                    

                    tmp = gen_ld32(addr, IS_USER(VAR_1));

                    store_reg(VAR_1, rs, tmp);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = gen_ld32(addr, IS_USER(VAR_1));

                    store_reg(VAR_1, rd, tmp);

                } else {

                    

                    tmp = load_reg(VAR_1, rs);

                    gen_st32(tmp, addr, IS_USER(VAR_1));

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = load_reg(VAR_1, rd);

                    gen_st32(tmp, addr, IS_USER(VAR_1));

                }

                if (insn & (1 << 21)) {

                    

                    if (rn == 15)

                        goto illegal_op;

                    tcg_gen_addi_i32(addr, addr, offset - 4);

                    store_reg(VAR_1, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            } else if ((insn & (1 << 23)) == 0) {

                

                addr = tcg_temp_local_new();

                load_reg_var(VAR_1, addr, rn);

                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(VAR_1, rs, 15, addr, 2);

                } else {

                    gen_store_exclusive(VAR_1, rd, rs, 15, addr, 2);

                }

                tcg_temp_free(addr);

            } else if ((insn & (1 << 6)) == 0) {

                

                if (rn == 15) {

                    addr = new_tmp();

                    tcg_gen_movi_i32(addr, VAR_1->pc);

                } else {

                    addr = load_reg(VAR_1, rn);

                }

                tmp = load_reg(VAR_1, rm);

                tcg_gen_add_i32(addr, addr, tmp);

                if (insn & (1 << 4)) {

                    

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    tmp = gen_ld16u(addr, IS_USER(VAR_1));

                } else { 

                    dead_tmp(tmp);

                    tmp = gen_ld8u(addr, IS_USER(VAR_1));

                }

                dead_tmp(addr);

                tcg_gen_shli_i32(tmp, tmp, 1);

                tcg_gen_addi_i32(tmp, tmp, VAR_1->pc);

                store_reg(VAR_1, 15, tmp);

            } else {

                

                ARCH(7);

                VAR_3 = (insn >> 4) & 0x3;

                if (VAR_3 == 2) {

                    goto illegal_op;

                }

                addr = tcg_temp_local_new();

                load_reg_var(VAR_1, addr, rn);

                if (insn & (1 << 20)) {

                    gen_load_exclusive(VAR_1, rs, rd, addr, VAR_3);

                } else {

                    gen_store_exclusive(VAR_1, rm, rs, rd, addr, VAR_3);

                }

                tcg_temp_free(addr);

            }

        } else {

            

            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {

                

                if (IS_USER(VAR_1))

                    goto illegal_op;

                if (insn & (1 << 20)) {

                    

                    addr = load_reg(VAR_1, rn);

                    if ((insn & (1 << 24)) == 0)

                        tcg_gen_addi_i32(addr, addr, -8);

                    

                    tmp = gen_ld32(addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp2 = gen_ld32(addr, 0);

                    if (insn & (1 << 21)) {

                        

                        if (insn & (1 << 24)) {

                            tcg_gen_addi_i32(addr, addr, 4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, -4);

                        }

                        store_reg(VAR_1, rn, addr);

                    } else {

                        dead_tmp(addr);

                    }

                    gen_rfe(VAR_1, tmp, tmp2);

                } else {

                    

                    VAR_3 = (insn & 0x1f);

                    if (VAR_3 == (VAR_0->uncached_cpsr & CPSR_M)) {

                        addr = load_reg(VAR_1, 13);

                    } else {

                        addr = new_tmp();

                        tmp = tcg_const_i32(VAR_3);

                        gen_helper_get_r13_banked(addr, cpu_env, tmp);

                        tcg_temp_free_i32(tmp);

                    }

                    if ((insn & (1 << 24)) == 0) {

                        tcg_gen_addi_i32(addr, addr, -8);

                    }

                    tmp = load_reg(VAR_1, 14);

                    gen_st32(tmp, addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = new_tmp();

                    gen_helper_cpsr_read(tmp);

                    gen_st32(tmp, addr, 0);

                    if (insn & (1 << 21)) {

                        if ((insn & (1 << 24)) == 0) {

                            tcg_gen_addi_i32(addr, addr, -4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, 4);

                        }

                        if (VAR_3 == (VAR_0->uncached_cpsr & CPSR_M)) {

                            store_reg(VAR_1, 13, addr);

                        } else {

                            tmp = tcg_const_i32(VAR_3);

                            gen_helper_set_r13_banked(cpu_env, tmp, addr);

                            tcg_temp_free_i32(tmp);

                        }

                    } else {

                        dead_tmp(addr);

                    }

                }

            } else {

                int VAR_7;

                

                addr = load_reg(VAR_1, rn);

                offset = 0;

                for (VAR_7 = 0; VAR_7 < 16; VAR_7++) {

                    if (insn & (1 << VAR_7))

                        offset += 4;

                }

                if (insn & (1 << 24)) {

                    tcg_gen_addi_i32(addr, addr, -offset);

                }



                for (VAR_7 = 0; VAR_7 < 16; VAR_7++) {

                    if ((insn & (1 << VAR_7)) == 0)

                        continue;

                    if (insn & (1 << 20)) {

                        

                        tmp = gen_ld32(addr, IS_USER(VAR_1));

                        if (VAR_7 == 15) {

                            gen_bx(VAR_1, tmp);

                        } else {

                            store_reg(VAR_1, VAR_7, tmp);

                        }

                    } else {

                        

                        tmp = load_reg(VAR_1, VAR_7);

                        gen_st32(tmp, addr, IS_USER(VAR_1));

                    }

                    tcg_gen_addi_i32(addr, addr, 4);

                }

                if (insn & (1 << 21)) {

                    

                    if (insn & (1 << 24)) {

                        tcg_gen_addi_i32(addr, addr, -offset);

                    }

                    

                    if (insn & (1 << rn))

                        goto illegal_op;

                    store_reg(VAR_1, rn, addr);

                } else {

                    dead_tmp(addr);

                }

            }

        }

        break;

    case 5:



        VAR_3 = (insn >> 21) & 0xf;

        if (VAR_3 == 6) {

            

            tmp = load_reg(VAR_1, rn);

            tmp2 = load_reg(VAR_1, rm);

            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);

            if (insn & (1 << 5)) {

                

                if (shift == 0)

                    shift = 31;

                tcg_gen_sari_i32(tmp2, tmp2, shift);

                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);

                tcg_gen_ext16u_i32(tmp2, tmp2);

            } else {

                

                if (shift)

                    tcg_gen_shli_i32(tmp2, tmp2, shift);

                tcg_gen_ext16u_i32(tmp, tmp);

                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

            }

            tcg_gen_or_i32(tmp, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(VAR_1, rd, tmp);

        } else {

            

            if (rn == 15) {

                tmp = new_tmp();

                tcg_gen_movi_i32(tmp, 0);

            } else {

                tmp = load_reg(VAR_1, rn);

            }

            tmp2 = load_reg(VAR_1, rm);



            VAR_4 = (insn >> 4) & 3;

            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

            VAR_5 = (insn & (1 << 20)) != 0;

            VAR_6 = (VAR_5 && thumb2_logic_op(VAR_3));

            gen_arm_shift_im(tmp2, VAR_4, shift, VAR_6);

            if (gen_thumb2_data_op(VAR_1, VAR_3, VAR_5, 0, tmp, tmp2))

                goto illegal_op;

            dead_tmp(tmp2);

            if (rd != 15) {

                store_reg(VAR_1, rd, tmp);

            } else {

                dead_tmp(tmp);

            }

        }

        break;

    case 13: 

        VAR_3 = ((insn >> 22) & 6) | ((insn >> 7) & 1);

        if (VAR_3 < 4 && (insn & 0xf000) != 0xf000)

            goto illegal_op;

        switch (VAR_3) {

        case 0: 

            tmp = load_reg(VAR_1, rn);

            tmp2 = load_reg(VAR_1, rm);

            if ((insn & 0x70) != 0)

                goto illegal_op;

            VAR_3 = (insn >> 21) & 3;

            VAR_6 = (insn & (1 << 20)) != 0;

            gen_arm_shift_reg(tmp, VAR_3, tmp2, VAR_6);

            if (VAR_6)

                gen_logic_CC(tmp);

            store_reg_bx(VAR_0, VAR_1, rd, tmp);

            break;

        case 1: 

            tmp = load_reg(VAR_1, rm);

            shift = (insn >> 4) & 3;

            



            if (shift != 0)

                tcg_gen_rotri_i32(tmp, tmp, shift * 8);

            VAR_3 = (insn >> 20) & 7;

            switch (VAR_3) {

            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: goto illegal_op;

            }

            if (rn != 15) {

                tmp2 = load_reg(VAR_1, rn);

                if ((VAR_3 >> 1) == 1) {

                    gen_add16(tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

            }

            store_reg(VAR_1, rd, tmp);

            break;

        case 2: 

            VAR_3 = (insn >> 20) & 7;

            shift = (insn >> 4) & 7;

            if ((VAR_3 & 3) == 3 || (shift & 3) == 3)

                goto illegal_op;

            tmp = load_reg(VAR_1, rn);

            tmp2 = load_reg(VAR_1, rm);

            gen_thumb2_parallel_addsub(VAR_3, shift, tmp, tmp2);

            dead_tmp(tmp2);

            store_reg(VAR_1, rd, tmp);

            break;

        case 3: 

            VAR_3 = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);

            if (VAR_3 < 4) {

                

                tmp = load_reg(VAR_1, rn);

                tmp2 = load_reg(VAR_1, rm);

                if (VAR_3 & 1)

                    gen_helper_double_saturate(tmp, tmp);

                if (VAR_3 & 2)

                    gen_helper_sub_saturate(tmp, tmp2, tmp);

                else

                    gen_helper_add_saturate(tmp, tmp, tmp2);

                dead_tmp(tmp2);

            } else {

                tmp = load_reg(VAR_1, rn);

                switch (VAR_3) {

                case 0x0a: 

                    gen_helper_rbit(tmp, tmp);

                    break;

                case 0x08: 

                    tcg_gen_bswap32_i32(tmp, tmp);

                    break;

                case 0x09: 

                    gen_rev16(tmp);

                    break;

                case 0x0b: 

                    gen_revsh(tmp);

                    break;

                case 0x10: 

                    tmp2 = load_reg(VAR_1, rm);

                    tmp3 = new_tmp();

                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));

                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);

                    dead_tmp(tmp3);

                    dead_tmp(tmp2);

                    break;

                case 0x18: 

                    gen_helper_clz(tmp, tmp);

                    break;

                default:

                    goto illegal_op;

                }

            }

            store_reg(VAR_1, rd, tmp);

            break;

        case 4: case 5: 

            VAR_3 = (insn >> 4) & 0xf;

            tmp = load_reg(VAR_1, rn);

            tmp2 = load_reg(VAR_1, rm);

            switch ((insn >> 20) & 7) {

            case 0: 

                tcg_gen_mul_i32(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(VAR_1, rs);

                    if (VAR_3)

                        tcg_gen_sub_i32(tmp, tmp2, tmp);

                    else

                        tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 1: 

                gen_mulxy(tmp, tmp2, VAR_3 & 2, VAR_3 & 1);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(VAR_1, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            case 2: 

            case 4: 

                if (VAR_3)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                

                if (insn & (1 << 22)) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                if (rs != 15)

                  {

                    tmp2 = load_reg(VAR_1, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 3: 

                if (VAR_3)

                    tcg_gen_sari_i32(tmp2, tmp2, 16);

                else

                    gen_sxth(tmp2);

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                tcg_gen_shri_i64(tmp64, tmp64, 16);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                if (rs != 15)

                  {

                    tmp2 = load_reg(VAR_1, rs);

                    gen_helper_add_setq(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                  }

                break;

            case 5: case 6: 

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                if (rs != 15) {

                    tmp = load_reg(VAR_1, rs);

                    if (insn & (1 << 20)) {

                        tmp64 = gen_addq_msw(tmp64, tmp);

                    } else {

                        tmp64 = gen_subq_msw(tmp64, tmp);

                    }

                }

                if (insn & (1 << 4)) {

                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);

                }

                tcg_gen_shri_i64(tmp64, tmp64, 32);

                tmp = new_tmp();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                break;

            case 7: 

                gen_helper_usad8(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(VAR_1, rs);

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    dead_tmp(tmp2);

                }

                break;

            }

            store_reg(VAR_1, rd, tmp);

            break;

        case 6: case 7: 

            VAR_3 = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);

            tmp = load_reg(VAR_1, rn);

            tmp2 = load_reg(VAR_1, rm);

            if ((VAR_3 & 0x50) == 0x10) {

                

                if (!arm_feature(VAR_0, ARM_FEATURE_DIV))

                    goto illegal_op;

                if (VAR_3 & 0x20)

                    gen_helper_udiv(tmp, tmp, tmp2);

                else

                    gen_helper_sdiv(tmp, tmp, tmp2);

                dead_tmp(tmp2);

                store_reg(VAR_1, rd, tmp);

            } else if ((VAR_3 & 0xe) == 0xc) {

                

                if (VAR_3 & 1)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                if (VAR_3 & 0x10) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                dead_tmp(tmp2);

                

                tmp64 = tcg_temp_new_i64();

                tcg_gen_ext_i32_i64(tmp64, tmp);

                dead_tmp(tmp);

                gen_addq(VAR_1, tmp64, rs, rd);

                gen_storeq_reg(VAR_1, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            } else {

                if (VAR_3 & 0x20) {

                    

                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                } else {

                    if (VAR_3 & 8) {

                        

                        gen_mulxy(tmp, tmp2, VAR_3 & 2, VAR_3 & 1);

                        dead_tmp(tmp2);

                        tmp64 = tcg_temp_new_i64();

                        tcg_gen_ext_i32_i64(tmp64, tmp);

                        dead_tmp(tmp);

                    } else {

                        

                        tmp64 = gen_muls_i64_i32(tmp, tmp2);

                    }

                }

                if (VAR_3 & 4) {

                    

                    gen_addq_lo(VAR_1, tmp64, rs);

                    gen_addq_lo(VAR_1, tmp64, rd);

                } else if (VAR_3 & 0x40) {

                    

                    gen_addq(VAR_1, tmp64, rs, rd);

                }

                gen_storeq_reg(VAR_1, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            }

            break;

        }

        break;

    case 6: case 7: case 14: case 15:

        

        if (((insn >> 24) & 3) == 3) {

            

            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);

            if (disas_neon_data_insn(VAR_0, VAR_1, insn))

                goto illegal_op;

        } else {

            if (insn & (1 << 28))

                goto illegal_op;

            if (disas_coproc_insn (VAR_0, VAR_1, insn))

                goto illegal_op;

        }

        break;

    case 8: case 9: case 10: case 11:

        if (insn & (1 << 15)) {

            

            if (insn & 0x5000) {

                

                

                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;

                

                offset |= (insn & 0x7ff) << 1;

                





                offset ^= ((~insn) & (1 << 13)) << 10;

                offset ^= ((~insn) & (1 << 11)) << 11;



                if (insn & (1 << 14)) {

                    

                    tcg_gen_movi_i32(cpu_R[14], VAR_1->pc | 1);

                }



                offset += VAR_1->pc;

                if (insn & (1 << 12)) {

                    

                    gen_jmp(VAR_1, offset);

                } else {

                    

                    offset &= ~(uint32_t)2;

                    gen_bx_im(VAR_1, offset);

                }

            } else if (((insn >> 23) & 7) == 7) {

                

                if (insn & (1 << 13))

                    goto illegal_op;



                if (insn & (1 << 26)) {

                    

                    goto illegal_op; 

                } else {

                    VAR_3 = (insn >> 20) & 7;

                    switch (VAR_3) {

                    case 0: 

                        if (IS_M(VAR_0)) {

                            tmp = load_reg(VAR_1, rn);

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_msr(cpu_env, addr, tmp);

                            tcg_temp_free_i32(addr);

                            dead_tmp(tmp);

                            gen_lookup_tb(VAR_1);

                            break;

                        }

                        

                    case 1: 

                        if (IS_M(VAR_0))

                            goto illegal_op;

                        tmp = load_reg(VAR_1, rn);

                        if (gen_set_psr(VAR_1,

                              msr_mask(VAR_0, VAR_1, (insn >> 8) & 0xf, VAR_3 == 1),

                              VAR_3 == 1, tmp))

                            goto illegal_op;

                        break;

                    case 2: 

                        if (((insn >> 8) & 7) == 0) {

                            gen_nop_hint(VAR_1, insn & 0xff);

                        }

                        

                        if (IS_USER(VAR_1))

                            break;

                        offset = 0;

                        imm = 0;

                        if (insn & (1 << 10)) {

                            if (insn & (1 << 7))

                                offset |= CPSR_A;

                            if (insn & (1 << 6))

                                offset |= CPSR_I;

                            if (insn & (1 << 5))

                                offset |= CPSR_F;

                            if (insn & (1 << 9))

                                imm = CPSR_A | CPSR_I | CPSR_F;

                        }

                        if (insn & (1 << 8)) {

                            offset |= 0x1f;

                            imm |= (insn & 0x1f);

                        }

                        if (offset) {

                            gen_set_psr_im(VAR_1, offset, 0, imm);

                        }

                        break;

                    case 3: 

                        ARCH(7);

                        VAR_3 = (insn >> 4) & 0xf;

                        switch (VAR_3) {

                        case 2: 

                            gen_clrex(VAR_1);

                            break;

                        case 4: 

                        case 5: 

                        case 6: 

                            

                            break;

                        default:

                            goto illegal_op;

                        }

                        break;

                    case 4: 

                        

                        tmp = load_reg(VAR_1, rn);

                        gen_bx(VAR_1, tmp);

                        break;

                    case 5: 

                        if (IS_USER(VAR_1)) {

                            goto illegal_op;

                        }

                        if (rn != 14 || rd != 15) {

                            goto illegal_op;

                        }

                        tmp = load_reg(VAR_1, rn);

                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);

                        gen_exception_return(VAR_1, tmp);

                        break;

                    case 6: 

                        tmp = new_tmp();

                        if (IS_M(VAR_0)) {

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_mrs(tmp, cpu_env, addr);

                            tcg_temp_free_i32(addr);

                        } else {

                            gen_helper_cpsr_read(tmp);

                        }

                        store_reg(VAR_1, rd, tmp);

                        break;

                    case 7: 

                        

                        if (IS_USER(VAR_1) || IS_M(VAR_0))

                            goto illegal_op;

                        tmp = load_cpu_field(spsr);

                        store_reg(VAR_1, rd, tmp);

                        break;

                    }

                }

            } else {

                

                VAR_3 = (insn >> 22) & 0xf;

                

                VAR_1->condlabel = gen_new_label();

                gen_test_cc(VAR_3 ^ 1, VAR_1->condlabel);

                VAR_1->condjmp = 1;



                

                offset = (insn & 0x7ff) << 1;

                

                offset |= (insn & 0x003f0000) >> 4;

                

                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;

                

                offset |= (insn & (1 << 13)) << 5;

                

                offset |= (insn & (1 << 11)) << 8;



                

                gen_jmp(VAR_1, VAR_1->pc + offset);

            }

        } else {

            

            if (insn & (1 << 25)) {

                if (insn & (1 << 24)) {

                    if (insn & (1 << 20))

                        goto illegal_op;

                    

                    VAR_3 = (insn >> 21) & 7;

                    imm = insn & 0x1f;

                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

                    if (rn == 15) {

                        tmp = new_tmp();

                        tcg_gen_movi_i32(tmp, 0);

                    } else {

                        tmp = load_reg(VAR_1, rn);

                    }

                    switch (VAR_3) {

                    case 2: 

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_sbfx(tmp, shift, imm);

                        break;

                    case 6: 

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_ubfx(tmp, shift, (1u << imm) - 1);

                        break;

                    case 3: 

                        if (imm < shift)

                            goto illegal_op;

                        imm = imm + 1 - shift;

                        if (imm != 32) {

                            tmp2 = load_reg(VAR_1, rd);

                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);

                            dead_tmp(tmp2);

                        }

                        break;

                    case 7:

                        goto illegal_op;

                    default: 

                        if (shift) {

                            if (VAR_3 & 1)

                                tcg_gen_sari_i32(tmp, tmp, shift);

                            else

                                tcg_gen_shli_i32(tmp, tmp, shift);

                        }

                        tmp2 = tcg_const_i32(imm);

                        if (VAR_3 & 4) {

                            

                            if ((VAR_3 & 1) && shift == 0)

                                gen_helper_usat16(tmp, tmp, tmp2);

                            else

                                gen_helper_usat(tmp, tmp, tmp2);

                        } else {

                            

                            if ((VAR_3 & 1) && shift == 0)

                                gen_helper_ssat16(tmp, tmp, tmp2);

                            else

                                gen_helper_ssat(tmp, tmp, tmp2);

                        }

                        tcg_temp_free_i32(tmp2);

                        break;

                    }

                    store_reg(VAR_1, rd, tmp);

                } else {

                    imm = ((insn & 0x04000000) >> 15)

                          | ((insn & 0x7000) >> 4) | (insn & 0xff);

                    if (insn & (1 << 22)) {

                        

                        imm |= (insn >> 4) & 0xf000;

                        if (insn & (1 << 23)) {

                            

                            tmp = load_reg(VAR_1, rd);

                            tcg_gen_ext16u_i32(tmp, tmp);

                            tcg_gen_ori_i32(tmp, tmp, imm << 16);

                        } else {

                            

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, imm);

                        }

                    } else {

                        

                        if (rn == 15) {

                            offset = VAR_1->pc & ~(uint32_t)3;

                            if (insn & (1 << 23))

                                offset -= imm;

                            else

                                offset += imm;

                            tmp = new_tmp();

                            tcg_gen_movi_i32(tmp, offset);

                        } else {

                            tmp = load_reg(VAR_1, rn);

                            if (insn & (1 << 23))

                                tcg_gen_subi_i32(tmp, tmp, imm);

                            else

                                tcg_gen_addi_i32(tmp, tmp, imm);

                        }

                    }

                    store_reg(VAR_1, rd, tmp);

                }

            } else {

                int VAR_8 = 0;

                

                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);

                imm = (insn & 0xff);

                switch (shift) {

                case 0: 

                    

                    break;

                case 1: 

                    imm |= imm << 16;

                    break;

                case 2: 

                    imm |= imm << 16;

                    imm <<= 8;

                    break;

                case 3: 

                    imm |= imm << 16;

                    imm |= imm << 8;

                    break;

                default: 

                    shift = (shift << 1) | (imm >> 7);

                    imm |= 0x80;

                    imm = imm << (32 - shift);

                    VAR_8 = 1;

                    break;

                }

                tmp2 = new_tmp();

                tcg_gen_movi_i32(tmp2, imm);

                rn = (insn >> 16) & 0xf;

                if (rn == 15) {

                    tmp = new_tmp();

                    tcg_gen_movi_i32(tmp, 0);

                } else {

                    tmp = load_reg(VAR_1, rn);

                }

                VAR_3 = (insn >> 21) & 0xf;

                if (gen_thumb2_data_op(VAR_1, VAR_3, (insn & (1 << 20)) != 0,

                                       VAR_8, tmp, tmp2))

                    goto illegal_op;

                dead_tmp(tmp2);

                rd = (insn >> 8) & 0xf;

                if (rd != 15) {

                    store_reg(VAR_1, rd, tmp);

                } else {

                    dead_tmp(tmp);

                }

            }

        }

        break;

    case 12: 

        {

        int VAR_9 = 0;

        int VAR_10 = 0;

        int VAR_11;

        if ((insn & 0x01100000) == 0x01000000) {

            if (disas_neon_ls_insn(VAR_0, VAR_1, insn))

                goto illegal_op;

            break;

        }

        VAR_11 = IS_USER(VAR_1);

        if (rn == 15) {

            addr = new_tmp();

            

            

            imm = VAR_1->pc & 0xfffffffc;

            if (insn & (1 << 23))

                imm += insn & 0xfff;

            else

                imm -= insn & 0xfff;

            tcg_gen_movi_i32(addr, imm);

        } else {

            addr = load_reg(VAR_1, rn);

            if (insn & (1 << 23)) {

                

                imm = insn & 0xfff;

                tcg_gen_addi_i32(addr, addr, imm);

            } else {

                VAR_3 = (insn >> 8) & 7;

                imm = insn & 0xff;

                switch (VAR_3) {

                case 0: case 8: 

                    shift = (insn >> 4) & 0xf;

                    if (shift > 3)

                        goto illegal_op;

                    tmp = load_reg(VAR_1, rm);

                    if (shift)

                        tcg_gen_shli_i32(tmp, tmp, shift);

                    tcg_gen_add_i32(addr, addr, tmp);

                    dead_tmp(tmp);

                    break;

                case 4: 

                    tcg_gen_addi_i32(addr, addr, -imm);

                    break;

                case 6: 

                    tcg_gen_addi_i32(addr, addr, imm);

                    VAR_11 = 1;

                    break;

                case 1: 

                    imm = -imm;

                    

                case 3: 

                    VAR_9 = 1;

                    VAR_10 = 1;

                    break;

                case 5: 

                    imm = -imm;

                    

                case 7: 

                    tcg_gen_addi_i32(addr, addr, imm);

                    VAR_10 = 1;

                    break;

                default:

                    goto illegal_op;

                }

            }

        }

        VAR_3 = ((insn >> 21) & 3) | ((insn >> 22) & 4);

        if (insn & (1 << 20)) {

            

            if (rs == 15 && VAR_3 != 2) {

                if (VAR_3 & 2)

                    goto illegal_op;

                

            } else {

                switch (VAR_3) {

                case 0: tmp = gen_ld8u(addr, VAR_11); break;

                case 4: tmp = gen_ld8s(addr, VAR_11); break;

                case 1: tmp = gen_ld16u(addr, VAR_11); break;

                case 5: tmp = gen_ld16s(addr, VAR_11); break;

                case 2: tmp = gen_ld32(addr, VAR_11); break;

                default: goto illegal_op;

                }

                if (rs == 15) {

                    gen_bx(VAR_1, tmp);

                } else {

                    store_reg(VAR_1, rs, tmp);

                }

            }

        } else {

            

            if (rs == 15)

                goto illegal_op;

            tmp = load_reg(VAR_1, rs);

            switch (VAR_3) {

            case 0: gen_st8(tmp, addr, VAR_11); break;

            case 1: gen_st16(tmp, addr, VAR_11); break;

            case 2: gen_st32(tmp, addr, VAR_11); break;

            default: goto illegal_op;

            }

        }

        if (VAR_9)

            tcg_gen_addi_i32(addr, addr, imm);

        if (VAR_10) {

            store_reg(VAR_1, rn, addr);

        } else {

            dead_tmp(addr);

        }

        }

        break;

    default:

        goto illegal_op;

    }

    return 0;

illegal_op:

    return 1;

}

static int FUNC_0(CPUState *VAR_0, DisasContext *VAR_1, uint16_t VAR_2)
{ uint32_t insn, imm, shift, offset; uint32_t rd, rn, rm, rs; TCGv tmp; TCGv tmp2; TCGv tmp3; TCGv addr; TCGv_i64 tmp64; int VAR_3; int VAR_4; int VAR_5; int VAR_6; if (!(arm_feature(VAR_0, ARM_FEATURE_THUMB2)
|| arm_feature (VAR_0, ARM_FEATURE_M))) { insn = VAR_2; if ((insn & (1 << 12)) == 0) { offset = ((insn & 0x7ff) << 1); tmp = load_reg(VAR_1, 14); tcg_gen_addi_i32(tmp, tmp, offset); tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); tmp2 = new_tmp(); tcg_gen_movi_i32(tmp2, VAR_1->pc | 1); store_reg(VAR_1, 14, tmp2); gen_bx(VAR_1, tmp); return 0; } if (insn & (1 << 11)) { offset = ((insn & 0x7ff) << 1) | 1; tmp = load_reg(VAR_1, 14); tcg_gen_addi_i32(tmp, tmp, offset); tmp2 = new_tmp(); tcg_gen_movi_i32(tmp2, VAR_1->pc | 1); store_reg(VAR_1, 14, tmp2); gen_bx(VAR_1, tmp); return 0; } if ((VAR_1->pc & ~TARGET_PAGE_MASK) == 0) { offset = ((int32_t)insn << 21) >> 9; tcg_gen_movi_i32(cpu_R[14], VAR_1->pc + 2 + offset); return 0; } } insn = lduw_code(VAR_1->pc); VAR_1->pc += 2; insn |= (uint32_t)VAR_2 << 16; if ((insn & 0xf800e800) != 0xf000e800) { ARCH(6T2); } rn = (insn >> 16) & 0xf; rs = (insn >> 12) & 0xf; rd = (insn >> 8) & 0xf; rm = insn & 0xf; switch ((insn >> 25) & 0xf) { case 0: case 1: case 2: case 3:
abort(); case 4:
if (insn & (1 << 22)) { if (insn & 0x01200000) { if (rn == 15) { addr = new_tmp(); tcg_gen_movi_i32(addr, VAR_1->pc & ~3); } else { addr = load_reg(VAR_1, rn); } offset = (insn & 0xff) * 4; if ((insn & (1 << 23)) == 0)
offset = -offset; if (insn & (1 << 24)) { tcg_gen_addi_i32(addr, addr, offset); offset = 0; } if (insn & (1 << 20)) { tmp = gen_ld32(addr, IS_USER(VAR_1)); store_reg(VAR_1, rs, tmp); tcg_gen_addi_i32(addr, addr, 4); tmp = gen_ld32(addr, IS_USER(VAR_1)); store_reg(VAR_1, rd, tmp); } else { tmp = load_reg(VAR_1, rs); gen_st32(tmp, addr, IS_USER(VAR_1)); tcg_gen_addi_i32(addr, addr, 4); tmp = load_reg(VAR_1, rd); gen_st32(tmp, addr, IS_USER(VAR_1)); } if (insn & (1 << 21)) { if (rn == 15)
goto illegal_op; tcg_gen_addi_i32(addr, addr, offset - 4); store_reg(VAR_1, rn, addr); } else { dead_tmp(addr); } } else if ((insn & (1 << 23)) == 0) { addr = tcg_temp_local_new(); load_reg_var(VAR_1, addr, rn); tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2); if (insn & (1 << 20)) { gen_load_exclusive(VAR_1, rs, 15, addr, 2); } else { gen_store_exclusive(VAR_1, rd, rs, 15, addr, 2); } tcg_temp_free(addr); } else if ((insn & (1 << 6)) == 0) { if (rn == 15) { addr = new_tmp(); tcg_gen_movi_i32(addr, VAR_1->pc); } else { addr = load_reg(VAR_1, rn); } tmp = load_reg(VAR_1, rm); tcg_gen_add_i32(addr, addr, tmp); if (insn & (1 << 4)) { tcg_gen_add_i32(addr, addr, tmp); dead_tmp(tmp); tmp = gen_ld16u(addr, IS_USER(VAR_1)); } else { dead_tmp(tmp); tmp = gen_ld8u(addr, IS_USER(VAR_1)); } dead_tmp(addr); tcg_gen_shli_i32(tmp, tmp, 1); tcg_gen_addi_i32(tmp, tmp, VAR_1->pc); store_reg(VAR_1, 15, tmp); } else { ARCH(7); VAR_3 = (insn >> 4) & 0x3; if (VAR_3 == 2) { goto illegal_op; } addr = tcg_temp_local_new(); load_reg_var(VAR_1, addr, rn); if (insn & (1 << 20)) { gen_load_exclusive(VAR_1, rs, rd, addr, VAR_3); } else { gen_store_exclusive(VAR_1, rm, rs, rd, addr, VAR_3); } tcg_temp_free(addr); } } else { if (((insn >> 23) & 1) == ((insn >> 24) & 1)) { if (IS_USER(VAR_1))
goto illegal_op; if (insn & (1 << 20)) { addr = load_reg(VAR_1, rn); if ((insn & (1 << 24)) == 0)
tcg_gen_addi_i32(addr, addr, -8); tmp = gen_ld32(addr, 0); tcg_gen_addi_i32(addr, addr, 4); tmp2 = gen_ld32(addr, 0); if (insn & (1 << 21)) { if (insn & (1 << 24)) { tcg_gen_addi_i32(addr, addr, 4); } else { tcg_gen_addi_i32(addr, addr, -4); } store_reg(VAR_1, rn, addr); } else { dead_tmp(addr); } gen_rfe(VAR_1, tmp, tmp2); } else { VAR_3 = (insn & 0x1f); if (VAR_3 == (VAR_0->uncached_cpsr & CPSR_M)) { addr = load_reg(VAR_1, 13); } else { addr = new_tmp(); tmp = tcg_const_i32(VAR_3); gen_helper_get_r13_banked(addr, cpu_env, tmp); tcg_temp_free_i32(tmp); } if ((insn & (1 << 24)) == 0) { tcg_gen_addi_i32(addr, addr, -8); } tmp = load_reg(VAR_1, 14); gen_st32(tmp, addr, 0); tcg_gen_addi_i32(addr, addr, 4); tmp = new_tmp(); gen_helper_cpsr_read(tmp); gen_st32(tmp, addr, 0); if (insn & (1 << 21)) { if ((insn & (1 << 24)) == 0) { tcg_gen_addi_i32(addr, addr, -4); } else { tcg_gen_addi_i32(addr, addr, 4); } if (VAR_3 == (VAR_0->uncached_cpsr & CPSR_M)) { store_reg(VAR_1, 13, addr); } else { tmp = tcg_const_i32(VAR_3); gen_helper_set_r13_banked(cpu_env, tmp, addr); tcg_temp_free_i32(tmp); } } else { dead_tmp(addr); } } } else { int VAR_7; addr = load_reg(VAR_1, rn); offset = 0; for (VAR_7 = 0; VAR_7 < 16; VAR_7++) { if (insn & (1 << VAR_7))
offset += 4; } if (insn & (1 << 24)) { tcg_gen_addi_i32(addr, addr, -offset); } for (VAR_7 = 0; VAR_7 < 16; VAR_7++) { if ((insn & (1 << VAR_7)) == 0)
continue; if (insn & (1 << 20)) { tmp = gen_ld32(addr, IS_USER(VAR_1)); if (VAR_7 == 15) { gen_bx(VAR_1, tmp); } else { store_reg(VAR_1, VAR_7, tmp); } } else { tmp = load_reg(VAR_1, VAR_7); gen_st32(tmp, addr, IS_USER(VAR_1)); } tcg_gen_addi_i32(addr, addr, 4); } if (insn & (1 << 21)) { if (insn & (1 << 24)) { tcg_gen_addi_i32(addr, addr, -offset); } if (insn & (1 << rn))
goto illegal_op; store_reg(VAR_1, rn, addr); } else { dead_tmp(addr); } } } break; case 5:
VAR_3 = (insn >> 21) & 0xf; if (VAR_3 == 6) { tmp = load_reg(VAR_1, rn); tmp2 = load_reg(VAR_1, rm); shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3); if (insn & (1 << 5)) { if (shift == 0)
shift = 31; tcg_gen_sari_i32(tmp2, tmp2, shift); tcg_gen_andi_i32(tmp, tmp, 0xffff0000); tcg_gen_ext16u_i32(tmp2, tmp2); } else { if (shift)
tcg_gen_shli_i32(tmp2, tmp2, shift); tcg_gen_ext16u_i32(tmp, tmp); tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); } tcg_gen_or_i32(tmp, tmp, tmp2); dead_tmp(tmp2); store_reg(VAR_1, rd, tmp); } else { if (rn == 15) { tmp = new_tmp(); tcg_gen_movi_i32(tmp, 0); } else { tmp = load_reg(VAR_1, rn); } tmp2 = load_reg(VAR_1, rm); VAR_4 = (insn >> 4) & 3; shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); VAR_5 = (insn & (1 << 20)) != 0; VAR_6 = (VAR_5 && thumb2_logic_op(VAR_3)); gen_arm_shift_im(tmp2, VAR_4, shift, VAR_6); if (gen_thumb2_data_op(VAR_1, VAR_3, VAR_5, 0, tmp, tmp2))
goto illegal_op; dead_tmp(tmp2); if (rd != 15) { store_reg(VAR_1, rd, tmp); } else { dead_tmp(tmp); } } break; case 13:
VAR_3 = ((insn >> 22) & 6) | ((insn >> 7) & 1); if (VAR_3 < 4 && (insn & 0xf000) != 0xf000)
goto illegal_op; switch (VAR_3) { case 0:
tmp = load_reg(VAR_1, rn); tmp2 = load_reg(VAR_1, rm); if ((insn & 0x70) != 0)
goto illegal_op; VAR_3 = (insn >> 21) & 3; VAR_6 = (insn & (1 << 20)) != 0; gen_arm_shift_reg(tmp, VAR_3, tmp2, VAR_6); if (VAR_6)
gen_logic_CC(tmp); store_reg_bx(VAR_0, VAR_1, rd, tmp); break; case 1:
tmp = load_reg(VAR_1, rm); shift = (insn >> 4) & 3; if (shift != 0)
tcg_gen_rotri_i32(tmp, tmp, shift * 8); VAR_3 = (insn >> 20) & 7; switch (VAR_3) { 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: goto illegal_op; } if (rn != 15) { tmp2 = load_reg(VAR_1, rn); if ((VAR_3 >> 1) == 1) { gen_add16(tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); dead_tmp(tmp2); } } store_reg(VAR_1, rd, tmp); break; case 2:
VAR_3 = (insn >> 20) & 7; shift = (insn >> 4) & 7; if ((VAR_3 & 3) == 3 || (shift & 3) == 3)
goto illegal_op; tmp = load_reg(VAR_1, rn); tmp2 = load_reg(VAR_1, rm); gen_thumb2_parallel_addsub(VAR_3, shift, tmp, tmp2); dead_tmp(tmp2); store_reg(VAR_1, rd, tmp); break; case 3:
VAR_3 = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); if (VAR_3 < 4) { tmp = load_reg(VAR_1, rn); tmp2 = load_reg(VAR_1, rm); if (VAR_3 & 1)
gen_helper_double_saturate(tmp, tmp); if (VAR_3 & 2)
gen_helper_sub_saturate(tmp, tmp2, tmp); else
gen_helper_add_saturate(tmp, tmp, tmp2); dead_tmp(tmp2); } else { tmp = load_reg(VAR_1, rn); switch (VAR_3) { case 0x0a:
gen_helper_rbit(tmp, tmp); break; case 0x08:
tcg_gen_bswap32_i32(tmp, tmp); break; case 0x09:
gen_rev16(tmp); break; case 0x0b:
gen_revsh(tmp); break; case 0x10:
tmp2 = load_reg(VAR_1, rm); tmp3 = new_tmp(); tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE)); gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); dead_tmp(tmp3); dead_tmp(tmp2); break; case 0x18:
gen_helper_clz(tmp, tmp); break; default:
goto illegal_op; } } store_reg(VAR_1, rd, tmp); break; case 4: case 5:
VAR_3 = (insn >> 4) & 0xf; tmp = load_reg(VAR_1, rn); tmp2 = load_reg(VAR_1, rm); switch ((insn >> 20) & 7) { case 0:
tcg_gen_mul_i32(tmp, tmp, tmp2); dead_tmp(tmp2); if (rs != 15) { tmp2 = load_reg(VAR_1, rs); if (VAR_3)
tcg_gen_sub_i32(tmp, tmp2, tmp); else
tcg_gen_add_i32(tmp, tmp, tmp2); dead_tmp(tmp2); } break; case 1:
gen_mulxy(tmp, tmp2, VAR_3 & 2, VAR_3 & 1); dead_tmp(tmp2); if (rs != 15) { tmp2 = load_reg(VAR_1, rs); gen_helper_add_setq(tmp, tmp, tmp2); dead_tmp(tmp2); } break; case 2:
case 4:
if (VAR_3)
gen_swap_half(tmp2); gen_smul_dual(tmp, tmp2); if (insn & (1 << 22)) { tcg_gen_sub_i32(tmp, tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); } dead_tmp(tmp2); if (rs != 15)
{ tmp2 = load_reg(VAR_1, rs); gen_helper_add_setq(tmp, tmp, tmp2); dead_tmp(tmp2); } break; case 3:
if (VAR_3)
tcg_gen_sari_i32(tmp2, tmp2, 16); else
gen_sxth(tmp2); tmp64 = gen_muls_i64_i32(tmp, tmp2); tcg_gen_shri_i64(tmp64, tmp64, 16); tmp = new_tmp(); tcg_gen_trunc_i64_i32(tmp, tmp64); tcg_temp_free_i64(tmp64); if (rs != 15)
{ tmp2 = load_reg(VAR_1, rs); gen_helper_add_setq(tmp, tmp, tmp2); dead_tmp(tmp2); } break; case 5: case 6:
tmp64 = gen_muls_i64_i32(tmp, tmp2); if (rs != 15) { tmp = load_reg(VAR_1, rs); if (insn & (1 << 20)) { tmp64 = gen_addq_msw(tmp64, tmp); } else { tmp64 = gen_subq_msw(tmp64, tmp); } } if (insn & (1 << 4)) { tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u); } tcg_gen_shri_i64(tmp64, tmp64, 32); tmp = new_tmp(); tcg_gen_trunc_i64_i32(tmp, tmp64); tcg_temp_free_i64(tmp64); break; case 7:
gen_helper_usad8(tmp, tmp, tmp2); dead_tmp(tmp2); if (rs != 15) { tmp2 = load_reg(VAR_1, rs); tcg_gen_add_i32(tmp, tmp, tmp2); dead_tmp(tmp2); } break; } store_reg(VAR_1, rd, tmp); break; case 6: case 7:
VAR_3 = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70); tmp = load_reg(VAR_1, rn); tmp2 = load_reg(VAR_1, rm); if ((VAR_3 & 0x50) == 0x10) { if (!arm_feature(VAR_0, ARM_FEATURE_DIV))
goto illegal_op; if (VAR_3 & 0x20)
gen_helper_udiv(tmp, tmp, tmp2); else
gen_helper_sdiv(tmp, tmp, tmp2); dead_tmp(tmp2); store_reg(VAR_1, rd, tmp); } else if ((VAR_3 & 0xe) == 0xc) { if (VAR_3 & 1)
gen_swap_half(tmp2); gen_smul_dual(tmp, tmp2); if (VAR_3 & 0x10) { tcg_gen_sub_i32(tmp, tmp, tmp2); } else { tcg_gen_add_i32(tmp, tmp, tmp2); } dead_tmp(tmp2); tmp64 = tcg_temp_new_i64(); tcg_gen_ext_i32_i64(tmp64, tmp); dead_tmp(tmp); gen_addq(VAR_1, tmp64, rs, rd); gen_storeq_reg(VAR_1, rs, rd, tmp64); tcg_temp_free_i64(tmp64); } else { if (VAR_3 & 0x20) { tmp64 = gen_mulu_i64_i32(tmp, tmp2); } else { if (VAR_3 & 8) { gen_mulxy(tmp, tmp2, VAR_3 & 2, VAR_3 & 1); dead_tmp(tmp2); tmp64 = tcg_temp_new_i64(); tcg_gen_ext_i32_i64(tmp64, tmp); dead_tmp(tmp); } else { tmp64 = gen_muls_i64_i32(tmp, tmp2); } } if (VAR_3 & 4) { gen_addq_lo(VAR_1, tmp64, rs); gen_addq_lo(VAR_1, tmp64, rd); } else if (VAR_3 & 0x40) { gen_addq(VAR_1, tmp64, rs, rd); } gen_storeq_reg(VAR_1, rs, rd, tmp64); tcg_temp_free_i64(tmp64); } break; } break; case 6: case 7: case 14: case 15:
if (((insn >> 24) & 3) == 3) { insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4); if (disas_neon_data_insn(VAR_0, VAR_1, insn))
goto illegal_op; } else { if (insn & (1 << 28))
goto illegal_op; if (disas_coproc_insn (VAR_0, VAR_1, insn))
goto illegal_op; } break; case 8: case 9: case 10: case 11:
if (insn & (1 << 15)) { if (insn & 0x5000) { offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff; offset |= (insn & 0x7ff) << 1; offset ^= ((~insn) & (1 << 13)) << 10; offset ^= ((~insn) & (1 << 11)) << 11; if (insn & (1 << 14)) { tcg_gen_movi_i32(cpu_R[14], VAR_1->pc | 1); } offset += VAR_1->pc; if (insn & (1 << 12)) { gen_jmp(VAR_1, offset); } else { offset &= ~(uint32_t)2; gen_bx_im(VAR_1, offset); } } else if (((insn >> 23) & 7) == 7) { if (insn & (1 << 13))
goto illegal_op; if (insn & (1 << 26)) { goto illegal_op; } else { VAR_3 = (insn >> 20) & 7; switch (VAR_3) { case 0:
if (IS_M(VAR_0)) { tmp = load_reg(VAR_1, rn); addr = tcg_const_i32(insn & 0xff); gen_helper_v7m_msr(cpu_env, addr, tmp); tcg_temp_free_i32(addr); dead_tmp(tmp); gen_lookup_tb(VAR_1); break; } case 1:
if (IS_M(VAR_0))
goto illegal_op; tmp = load_reg(VAR_1, rn); if (gen_set_psr(VAR_1,
msr_mask(VAR_0, VAR_1, (insn >> 8) & 0xf, VAR_3 == 1),
VAR_3 == 1, tmp))
goto illegal_op; break; case 2:
if (((insn >> 8) & 7) == 0) { gen_nop_hint(VAR_1, insn & 0xff); } if (IS_USER(VAR_1))
break; offset = 0; imm = 0; if (insn & (1 << 10)) { if (insn & (1 << 7))
offset |= CPSR_A; if (insn & (1 << 6))
offset |= CPSR_I; if (insn & (1 << 5))
offset |= CPSR_F; if (insn & (1 << 9))
imm = CPSR_A | CPSR_I | CPSR_F; } if (insn & (1 << 8)) { offset |= 0x1f; imm |= (insn & 0x1f); } if (offset) { gen_set_psr_im(VAR_1, offset, 0, imm); } break; case 3:
ARCH(7); VAR_3 = (insn >> 4) & 0xf; switch (VAR_3) { case 2:
gen_clrex(VAR_1); break; case 4:
case 5:
case 6:
break; default:
goto illegal_op; } break; case 4:
tmp = load_reg(VAR_1, rn); gen_bx(VAR_1, tmp); break; case 5:
if (IS_USER(VAR_1)) { goto illegal_op; } if (rn != 14 || rd != 15) { goto illegal_op; } tmp = load_reg(VAR_1, rn); tcg_gen_subi_i32(tmp, tmp, insn & 0xff); gen_exception_return(VAR_1, tmp); break; case 6:
tmp = new_tmp(); if (IS_M(VAR_0)) { addr = tcg_const_i32(insn & 0xff); gen_helper_v7m_mrs(tmp, cpu_env, addr); tcg_temp_free_i32(addr); } else { gen_helper_cpsr_read(tmp); } store_reg(VAR_1, rd, tmp); break; case 7:
if (IS_USER(VAR_1) || IS_M(VAR_0))
goto illegal_op; tmp = load_cpu_field(spsr); store_reg(VAR_1, rd, tmp); break; } } } else { VAR_3 = (insn >> 22) & 0xf; VAR_1->condlabel = gen_new_label(); gen_test_cc(VAR_3 ^ 1, VAR_1->condlabel); VAR_1->condjmp = 1; offset = (insn & 0x7ff) << 1; offset |= (insn & 0x003f0000) >> 4; offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11; offset |= (insn & (1 << 13)) << 5; offset |= (insn & (1 << 11)) << 8; gen_jmp(VAR_1, VAR_1->pc + offset); } } else { if (insn & (1 << 25)) { if (insn & (1 << 24)) { if (insn & (1 << 20))
goto illegal_op; VAR_3 = (insn >> 21) & 7; imm = insn & 0x1f; shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); if (rn == 15) { tmp = new_tmp(); tcg_gen_movi_i32(tmp, 0); } else { tmp = load_reg(VAR_1, rn); } switch (VAR_3) { case 2:
imm++; if (shift + imm > 32)
goto illegal_op; if (imm < 32)
gen_sbfx(tmp, shift, imm); break; case 6:
imm++; if (shift + imm > 32)
goto illegal_op; if (imm < 32)
gen_ubfx(tmp, shift, (1u << imm) - 1); break; case 3:
if (imm < shift)
goto illegal_op; imm = imm + 1 - shift; if (imm != 32) { tmp2 = load_reg(VAR_1, rd); gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1); dead_tmp(tmp2); } break; case 7:
goto illegal_op; default:
if (shift) { if (VAR_3 & 1)
tcg_gen_sari_i32(tmp, tmp, shift); else
tcg_gen_shli_i32(tmp, tmp, shift); } tmp2 = tcg_const_i32(imm); if (VAR_3 & 4) { if ((VAR_3 & 1) && shift == 0)
gen_helper_usat16(tmp, tmp, tmp2); else
gen_helper_usat(tmp, tmp, tmp2); } else { if ((VAR_3 & 1) && shift == 0)
gen_helper_ssat16(tmp, tmp, tmp2); else
gen_helper_ssat(tmp, tmp, tmp2); } tcg_temp_free_i32(tmp2); break; } store_reg(VAR_1, rd, tmp); } else { imm = ((insn & 0x04000000) >> 15)
| ((insn & 0x7000) >> 4) | (insn & 0xff); if (insn & (1 << 22)) { imm |= (insn >> 4) & 0xf000; if (insn & (1 << 23)) { tmp = load_reg(VAR_1, rd); tcg_gen_ext16u_i32(tmp, tmp); tcg_gen_ori_i32(tmp, tmp, imm << 16); } else { tmp = new_tmp(); tcg_gen_movi_i32(tmp, imm); } } else { if (rn == 15) { offset = VAR_1->pc & ~(uint32_t)3; if (insn & (1 << 23))
offset -= imm; else
offset += imm; tmp = new_tmp(); tcg_gen_movi_i32(tmp, offset); } else { tmp = load_reg(VAR_1, rn); if (insn & (1 << 23))
tcg_gen_subi_i32(tmp, tmp, imm); else
tcg_gen_addi_i32(tmp, tmp, imm); } } store_reg(VAR_1, rd, tmp); } } else { int VAR_8 = 0; shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12); imm = (insn & 0xff); switch (shift) { case 0:
break; case 1:
imm |= imm << 16; break; case 2:
imm |= imm << 16; imm <<= 8; break; case 3:
imm |= imm << 16; imm |= imm << 8; break; default:
shift = (shift << 1) | (imm >> 7); imm |= 0x80; imm = imm << (32 - shift); VAR_8 = 1; break; } tmp2 = new_tmp(); tcg_gen_movi_i32(tmp2, imm); rn = (insn >> 16) & 0xf; if (rn == 15) { tmp = new_tmp(); tcg_gen_movi_i32(tmp, 0); } else { tmp = load_reg(VAR_1, rn); } VAR_3 = (insn >> 21) & 0xf; if (gen_thumb2_data_op(VAR_1, VAR_3, (insn & (1 << 20)) != 0,
VAR_8, tmp, tmp2))
goto illegal_op; dead_tmp(tmp2); rd = (insn >> 8) & 0xf; if (rd != 15) { store_reg(VAR_1, rd, tmp); } else { dead_tmp(tmp); } } } break; case 12:
{ int VAR_9 = 0; int VAR_10 = 0; int VAR_11; if ((insn & 0x01100000) == 0x01000000) { if (disas_neon_ls_insn(VAR_0, VAR_1, insn))
goto illegal_op; break; } VAR_11 = IS_USER(VAR_1); if (rn == 15) { addr = new_tmp(); imm = VAR_1->pc & 0xfffffffc; if (insn & (1 << 23))
imm += insn & 0xfff; else
imm -= insn & 0xfff; tcg_gen_movi_i32(addr, imm); } else { addr = load_reg(VAR_1, rn); if (insn & (1 << 23)) { imm = insn & 0xfff; tcg_gen_addi_i32(addr, addr, imm); } else { VAR_3 = (insn >> 8) & 7; imm = insn & 0xff; switch (VAR_3) { case 0: case 8:
shift = (insn >> 4) & 0xf; if (shift > 3)
goto illegal_op; tmp = load_reg(VAR_1, rm); if (shift)
tcg_gen_shli_i32(tmp, tmp, shift); tcg_gen_add_i32(addr, addr, tmp); dead_tmp(tmp); break; case 4:
tcg_gen_addi_i32(addr, addr, -imm); break; case 6:
tcg_gen_addi_i32(addr, addr, imm); VAR_11 = 1; break; case 1:
imm = -imm; case 3:
VAR_9 = 1; VAR_10 = 1; break; case 5:
imm = -imm; case 7:
tcg_gen_addi_i32(addr, addr, imm); VAR_10 = 1; break; default:
goto illegal_op; } } } VAR_3 = ((insn >> 21) & 3) | ((insn >> 22) & 4); if (insn & (1 << 20)) { if (rs == 15 && VAR_3 != 2) { if (VAR_3 & 2)
goto illegal_op; } else { switch (VAR_3) { case 0: tmp = gen_ld8u(addr, VAR_11); break; case 4: tmp = gen_ld8s(addr, VAR_11); break; case 1: tmp = gen_ld16u(addr, VAR_11); break; case 5: tmp = gen_ld16s(addr, VAR_11); break; case 2: tmp = gen_ld32(addr, VAR_11); break; default: goto illegal_op; } if (rs == 15) { gen_bx(VAR_1, tmp); } else { store_reg(VAR_1, rs, tmp); } } } else { if (rs == 15)
goto illegal_op; tmp = load_reg(VAR_1, rs); switch (VAR_3) { case 0: gen_st8(tmp, addr, VAR_11); break; case 1: gen_st16(tmp, addr, VAR_11); break; case 2: gen_st32(tmp, addr, VAR_11); break; default: goto illegal_op; } } if (VAR_9)
tcg_gen_addi_i32(addr, addr, imm); if (VAR_10) { store_reg(VAR_1, rn, addr); } else { dead_tmp(addr); } } break; default:
goto illegal_op; } return 0; illegal_op:
return 1; }