static void disas_thumb_insn(CPUARMState *env, DisasContext *s)

{

    uint32_t val, insn, op, rm, rn, rd, shift, cond;

    int32_t offset;

    int i;

    TCGv_i32 tmp;

    TCGv_i32 tmp2;

    TCGv_i32 addr;



    if (s->condexec_mask) {

        cond = s->condexec_cond;

        if (cond != 0x0e) {     /* Skip conditional when condition is AL. */

          s->condlabel = gen_new_label();

          arm_gen_test_cc(cond ^ 1, s->condlabel);

          s->condjmp = 1;

        }

    }



    insn = arm_lduw_code(env, s->pc, s->sctlr_b);

    s->pc += 2;



    switch (insn >> 12) {

    case 0: case 1:



        rd = insn & 7;

        op = (insn >> 11) & 3;

        if (op == 3) {

            /* add/subtract */

            rn = (insn >> 3) & 7;

            tmp = load_reg(s, rn);

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

                /* immediate */

                tmp2 = tcg_temp_new_i32();

                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);

            } else {

                /* reg */

                rm = (insn >> 6) & 7;

                tmp2 = load_reg(s, rm);

            }

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

                if (s->condexec_mask)

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                else

                    gen_sub_CC(tmp, tmp, tmp2);

            } else {

                if (s->condexec_mask)

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                else

                    gen_add_CC(tmp, tmp, tmp2);

            }

            tcg_temp_free_i32(tmp2);

            store_reg(s, rd, tmp);

        } else {

            /* shift immediate */

            rm = (insn >> 3) & 7;

            shift = (insn >> 6) & 0x1f;

            tmp = load_reg(s, rm);

            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            store_reg(s, rd, tmp);

        }

        break;

    case 2: case 3:

        /* arithmetic large immediate */

        op = (insn >> 11) & 3;

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

        if (op == 0) { /* mov */

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, insn & 0xff);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            store_reg(s, rd, tmp);

        } else {

            tmp = load_reg(s, rd);

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, insn & 0xff);

            switch (op) {

            case 1: /* cmp */

                gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp);

                tcg_temp_free_i32(tmp2);

                break;

            case 2: /* add */

                if (s->condexec_mask)

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                else

                    gen_add_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

                break;

            case 3: /* sub */

                if (s->condexec_mask)

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                else

                    gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

                break;

            }

        }

        break;

    case 4:

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

            rd = (insn >> 8) & 7;

            /* load pc-relative.  Bit 1 of PC is ignored.  */

            val = s->pc + 2 + ((insn & 0xff) * 4);

            val &= ~(uint32_t)2;

            addr = tcg_temp_new_i32();

            tcg_gen_movi_i32(addr, val);

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),

                               rd | ISSIs16Bit);

            tcg_temp_free_i32(addr);

            store_reg(s, rd, tmp);

            break;

        }

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

            /* data processing extended or blx */

            rd = (insn & 7) | ((insn >> 4) & 8);

            rm = (insn >> 3) & 0xf;

            op = (insn >> 8) & 3;

            switch (op) {

            case 0: /* add */

                tmp = load_reg(s, rd);

                tmp2 = load_reg(s, rm);

                tcg_gen_add_i32(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

                break;

            case 1: /* cmp */

                tmp = load_reg(s, rd);

                tmp2 = load_reg(s, rm);

                gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                tcg_temp_free_i32(tmp);

                break;

            case 2: /* mov/cpy */

                tmp = load_reg(s, rm);

                store_reg(s, rd, tmp);

                break;

            case 3:/* branch [and link] exchange thumb register */

                tmp = load_reg(s, rm);

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

                    ARCH(5);

                    val = (uint32_t)s->pc | 1;

                    tmp2 = tcg_temp_new_i32();

                    tcg_gen_movi_i32(tmp2, val);

                    store_reg(s, 14, tmp2);

                    gen_bx(s, tmp);

                } else {

                    /* Only BX works as exception-return, not BLX */

                    gen_bx_excret(s, tmp);

                }

                break;

            }

            break;

        }



        /* data processing register */

        rd = insn & 7;

        rm = (insn >> 3) & 7;

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

        if (op == 2 || op == 3 || op == 4 || op == 7) {

            /* the shift/rotate ops want the operands backwards */

            val = rm;

            rm = rd;

            rd = val;

            val = 1;

        } else {

            val = 0;

        }



        if (op == 9) { /* neg */

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, 0);

        } else if (op != 0xf) { /* mvn doesn't read its first operand */

            tmp = load_reg(s, rd);

        } else {

            TCGV_UNUSED_I32(tmp);

        }



        tmp2 = load_reg(s, rm);

        switch (op) {

        case 0x0: /* and */

            tcg_gen_and_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0x1: /* eor */

            tcg_gen_xor_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0x2: /* lsl */

            if (s->condexec_mask) {

                gen_shl(tmp2, tmp2, tmp);

            } else {

                gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x3: /* lsr */

            if (s->condexec_mask) {

                gen_shr(tmp2, tmp2, tmp);

            } else {

                gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x4: /* asr */

            if (s->condexec_mask) {

                gen_sar(tmp2, tmp2, tmp);

            } else {

                gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x5: /* adc */

            if (s->condexec_mask) {

                gen_adc(tmp, tmp2);

            } else {

                gen_adc_CC(tmp, tmp, tmp2);

            }

            break;

        case 0x6: /* sbc */

            if (s->condexec_mask) {

                gen_sub_carry(tmp, tmp, tmp2);

            } else {

                gen_sbc_CC(tmp, tmp, tmp2);

            }

            break;

        case 0x7: /* ror */

            if (s->condexec_mask) {

                tcg_gen_andi_i32(tmp, tmp, 0x1f);

                tcg_gen_rotr_i32(tmp2, tmp2, tmp);

            } else {

                gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x8: /* tst */

            tcg_gen_and_i32(tmp, tmp, tmp2);

            gen_logic_CC(tmp);

            rd = 16;

            break;

        case 0x9: /* neg */

            if (s->condexec_mask)

                tcg_gen_neg_i32(tmp, tmp2);

            else

                gen_sub_CC(tmp, tmp, tmp2);

            break;

        case 0xa: /* cmp */

            gen_sub_CC(tmp, tmp, tmp2);

            rd = 16;

            break;

        case 0xb: /* cmn */

            gen_add_CC(tmp, tmp, tmp2);

            rd = 16;

            break;

        case 0xc: /* orr */

            tcg_gen_or_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xd: /* mul */

            tcg_gen_mul_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xe: /* bic */

            tcg_gen_andc_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xf: /* mvn */

            tcg_gen_not_i32(tmp2, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp2);

            val = 1;

            rm = rd;

            break;

        }

        if (rd != 16) {

            if (val) {

                store_reg(s, rm, tmp2);

                if (op != 0xf)

                    tcg_temp_free_i32(tmp);

            } else {

                store_reg(s, rd, tmp);

                tcg_temp_free_i32(tmp2);

            }

        } else {

            tcg_temp_free_i32(tmp);

            tcg_temp_free_i32(tmp2);

        }

        break;



    case 5:

        /* load/store register offset.  */

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        rm = (insn >> 6) & 7;

        op = (insn >> 9) & 7;

        addr = load_reg(s, rn);

        tmp = load_reg(s, rm);

        tcg_gen_add_i32(addr, addr, tmp);

        tcg_temp_free_i32(tmp);



        if (op < 3) { /* store */

            tmp = load_reg(s, rd);

        } else {

            tmp = tcg_temp_new_i32();

        }



        switch (op) {

        case 0: /* str */

            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 1: /* strh */

            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 2: /* strb */

            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 3: /* ldrsb */

            gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 4: /* ldr */

            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 5: /* ldrh */

            gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 6: /* ldrb */

            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 7: /* ldrsh */

            gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        }

        if (op >= 3) { /* load */

            store_reg(s, rd, tmp);

        } else {

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 6:

        /* load/store word immediate offset */

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(s, rn);

        val = (insn >> 4) & 0x7c;

        tcg_gen_addi_i32(addr, addr, val);



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

            /* load */

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

            store_reg(s, rd, tmp);

        } else {

            /* store */

            tmp = load_reg(s, rd);

            gen_aa32_st32(s, tmp, addr, get_mem_index(s));

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 7:

        /* load/store byte immediate offset */

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(s, rn);

        val = (insn >> 6) & 0x1f;

        tcg_gen_addi_i32(addr, addr, val);



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

            /* load */

            tmp = tcg_temp_new_i32();

            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            store_reg(s, rd, tmp);

        } else {

            /* store */

            tmp = load_reg(s, rd);

            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 8:

        /* load/store halfword immediate offset */

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(s, rn);

        val = (insn >> 5) & 0x3e;

        tcg_gen_addi_i32(addr, addr, val);



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

            /* load */

            tmp = tcg_temp_new_i32();

            gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            store_reg(s, rd, tmp);

        } else {

            /* store */

            tmp = load_reg(s, rd);

            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 9:

        /* load/store from stack */

        rd = (insn >> 8) & 7;

        addr = load_reg(s, 13);

        val = (insn & 0xff) * 4;

        tcg_gen_addi_i32(addr, addr, val);



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

            /* load */

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            store_reg(s, rd, tmp);

        } else {

            /* store */

            tmp = load_reg(s, rd);

            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 10:

        /* add to high reg */

        rd = (insn >> 8) & 7;

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

            /* SP */

            tmp = load_reg(s, 13);

        } else {

            /* PC. bit 1 is ignored.  */

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);

        }

        val = (insn & 0xff) * 4;

        tcg_gen_addi_i32(tmp, tmp, val);

        store_reg(s, rd, tmp);

        break;



    case 11:

        /* misc */

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

        switch (op) {

        case 0:

            /* adjust stack pointer */

            tmp = load_reg(s, 13);

            val = (insn & 0x7f) * 4;

            if (insn & (1 << 7))

                val = -(int32_t)val;

            tcg_gen_addi_i32(tmp, tmp, val);

            store_reg(s, 13, tmp);

            break;



        case 2: /* sign/zero extend.  */

            ARCH(6);

            rd = insn & 7;

            rm = (insn >> 3) & 7;

            tmp = load_reg(s, rm);

            switch ((insn >> 6) & 3) {

            case 0: gen_sxth(tmp); break;

            case 1: gen_sxtb(tmp); break;

            case 2: gen_uxth(tmp); break;

            case 3: gen_uxtb(tmp); break;

            }

            store_reg(s, rd, tmp);

            break;

        case 4: case 5: case 0xc: case 0xd:

            /* push/pop */

            addr = load_reg(s, 13);

            if (insn & (1 << 8))

                offset = 4;

            else

                offset = 0;

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

                if (insn & (1 << i))

                    offset += 4;

            }

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

                tcg_gen_addi_i32(addr, addr, -offset);

            }

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

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

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

                        /* pop */

                        tmp = tcg_temp_new_i32();

                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

                        store_reg(s, i, tmp);

                    } else {

                        /* push */

                        tmp = load_reg(s, i);

                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));

                        tcg_temp_free_i32(tmp);

                    }

                    /* advance to the next address.  */

                    tcg_gen_addi_i32(addr, addr, 4);

                }

            }

            TCGV_UNUSED_I32(tmp);

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

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

                    /* pop pc */

                    tmp = tcg_temp_new_i32();

                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

                    /* don't set the pc until the rest of the instruction

                       has completed */

                } else {

                    /* push lr */

                    tmp = load_reg(s, 14);

                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));

                    tcg_temp_free_i32(tmp);

                }

                tcg_gen_addi_i32(addr, addr, 4);

            }

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

                tcg_gen_addi_i32(addr, addr, -offset);

            }

            /* write back the new stack pointer */

            store_reg(s, 13, addr);

            /* set the new PC value */

            if ((insn & 0x0900) == 0x0900) {

                store_reg_from_load(s, 15, tmp);

            }

            break;



        case 1: case 3: case 9: case 11: /* czb */

            rm = insn & 7;

            tmp = load_reg(s, rm);

            s->condlabel = gen_new_label();

            s->condjmp = 1;

            if (insn & (1 << 11))

                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);

            else

                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);

            tcg_temp_free_i32(tmp);

            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;

            val = (uint32_t)s->pc + 2;

            val += offset;

            gen_jmp(s, val);

            break;



        case 15: /* IT, nop-hint.  */

            if ((insn & 0xf) == 0) {

                gen_nop_hint(s, (insn >> 4) & 0xf);

                break;

            }

            /* If Then.  */

            s->condexec_cond = (insn >> 4) & 0xe;

            s->condexec_mask = insn & 0x1f;

            /* No actual code generated for this insn, just setup state.  */

            break;



        case 0xe: /* bkpt */

        {

            int imm8 = extract32(insn, 0, 8);

            ARCH(5);

            gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),

                               default_exception_el(s));

            break;

        }



        case 0xa: /* rev, and hlt */

        {

            int op1 = extract32(insn, 6, 2);



            if (op1 == 2) {

                /* HLT */

                int imm6 = extract32(insn, 0, 6);



                gen_hlt(s, imm6);

                break;

            }



            /* Otherwise this is rev */

            ARCH(6);

            rn = (insn >> 3) & 0x7;

            rd = insn & 0x7;

            tmp = load_reg(s, rn);

            switch (op1) {

            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;

            case 1: gen_rev16(tmp); break;

            case 3: gen_revsh(tmp); break;

            default:

                g_assert_not_reached();

            }

            store_reg(s, rd, tmp);

            break;

        }



        case 6:

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

            case 2:

                /* setend */

                ARCH(6);

                if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {

                    gen_helper_setend(cpu_env);

                    s->is_jmp = DISAS_UPDATE;

                }

                break;

            case 3:

                /* cps */

                ARCH(6);

                if (IS_USER(s)) {

                    break;

                }

                if (arm_dc_feature(s, ARM_FEATURE_M)) {

                    tmp = tcg_const_i32((insn & (1 << 4)) != 0);

                    /* FAULTMASK */

                    if (insn & 1) {

                        addr = tcg_const_i32(19);

                        gen_helper_v7m_msr(cpu_env, addr, tmp);

                        tcg_temp_free_i32(addr);

                    }

                    /* PRIMASK */

                    if (insn & 2) {

                        addr = tcg_const_i32(16);

                        gen_helper_v7m_msr(cpu_env, addr, tmp);

                        tcg_temp_free_i32(addr);

                    }

                    tcg_temp_free_i32(tmp);

                    gen_lookup_tb(s);

                } else {

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

                        shift = CPSR_A | CPSR_I | CPSR_F;

                    } else {

                        shift = 0;

                    }

                    gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);

                }

                break;

            default:

                goto undef;

            }

            break;



        default:

            goto undef;

        }

        break;



    case 12:

    {

        /* load/store multiple */

        TCGv_i32 loaded_var;

        TCGV_UNUSED_I32(loaded_var);

        rn = (insn >> 8) & 0x7;

        addr = load_reg(s, rn);

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

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

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

                    /* load */

                    tmp = tcg_temp_new_i32();

                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

                    if (i == rn) {

                        loaded_var = tmp;

                    } else {

                        store_reg(s, i, tmp);

                    }

                } else {

                    /* store */

                    tmp = load_reg(s, i);

                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));

                    tcg_temp_free_i32(tmp);

                }

                /* advance to the next address */

                tcg_gen_addi_i32(addr, addr, 4);

            }

        }

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

            /* base reg not in list: base register writeback */

            store_reg(s, rn, addr);

        } else {

            /* base reg in list: if load, complete it now */

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

                store_reg(s, rn, loaded_var);

            }

            tcg_temp_free_i32(addr);

        }

        break;

    }

    case 13:

        /* conditional branch or swi */

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

        if (cond == 0xe)

            goto undef;



        if (cond == 0xf) {

            /* swi */

            gen_set_pc_im(s, s->pc);

            s->svc_imm = extract32(insn, 0, 8);

            s->is_jmp = DISAS_SWI;

            break;

        }

        /* generate a conditional jump to next instruction */

        s->condlabel = gen_new_label();

        arm_gen_test_cc(cond ^ 1, s->condlabel);

        s->condjmp = 1;



        /* jump to the offset */

        val = (uint32_t)s->pc + 2;

        offset = ((int32_t)insn << 24) >> 24;

        val += offset << 1;

        gen_jmp(s, val);

        break;



    case 14:

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

            if (disas_thumb2_insn(env, s, insn))

              goto undef32;

            break;

        }

        /* unconditional branch */

        val = (uint32_t)s->pc;

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

        val += (offset << 1) + 2;

        gen_jmp(s, val);

        break;



    case 15:

        if (disas_thumb2_insn(env, s, insn))

            goto undef32;

        break;

    }

    return;

undef32:

    gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),

                       default_exception_el(s));

    return;

illegal_op:

undef:

    gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),

                       default_exception_el(s));

}

static void disas_thumb_insn(CPUARMState *env, DisasContext *s)

{

    uint32_t val, insn, op, rm, rn, rd, shift, cond;

    int32_t offset;

    int i;

    TCGv_i32 tmp;

    TCGv_i32 tmp2;

    TCGv_i32 addr;



    if (s->condexec_mask) {

        cond = s->condexec_cond;

        if (cond != 0x0e) {     

          s->condlabel = gen_new_label();

          arm_gen_test_cc(cond ^ 1, s->condlabel);

          s->condjmp = 1;

        }

    }



    insn = arm_lduw_code(env, s->pc, s->sctlr_b);

    s->pc += 2;



    switch (insn >> 12) {

    case 0: case 1:



        rd = insn & 7;

        op = (insn >> 11) & 3;

        if (op == 3) {

            

            rn = (insn >> 3) & 7;

            tmp = load_reg(s, rn);

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

                

                tmp2 = tcg_temp_new_i32();

                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);

            } else {

                

                rm = (insn >> 6) & 7;

                tmp2 = load_reg(s, rm);

            }

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

                if (s->condexec_mask)

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                else

                    gen_sub_CC(tmp, tmp, tmp2);

            } else {

                if (s->condexec_mask)

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                else

                    gen_add_CC(tmp, tmp, tmp2);

            }

            tcg_temp_free_i32(tmp2);

            store_reg(s, rd, tmp);

        } else {

            

            rm = (insn >> 3) & 7;

            shift = (insn >> 6) & 0x1f;

            tmp = load_reg(s, rm);

            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            store_reg(s, rd, tmp);

        }

        break;

    case 2: case 3:

        

        op = (insn >> 11) & 3;

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

        if (op == 0) { 

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, insn & 0xff);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            store_reg(s, rd, tmp);

        } else {

            tmp = load_reg(s, rd);

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, insn & 0xff);

            switch (op) {

            case 1: 

                gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp);

                tcg_temp_free_i32(tmp2);

                break;

            case 2: 

                if (s->condexec_mask)

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                else

                    gen_add_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

                break;

            case 3: 

                if (s->condexec_mask)

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                else

                    gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

                break;

            }

        }

        break;

    case 4:

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

            rd = (insn >> 8) & 7;

            

            val = s->pc + 2 + ((insn & 0xff) * 4);

            val &= ~(uint32_t)2;

            addr = tcg_temp_new_i32();

            tcg_gen_movi_i32(addr, val);

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),

                               rd | ISSIs16Bit);

            tcg_temp_free_i32(addr);

            store_reg(s, rd, tmp);

            break;

        }

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

            

            rd = (insn & 7) | ((insn >> 4) & 8);

            rm = (insn >> 3) & 0xf;

            op = (insn >> 8) & 3;

            switch (op) {

            case 0: 

                tmp = load_reg(s, rd);

                tmp2 = load_reg(s, rm);

                tcg_gen_add_i32(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

                break;

            case 1: 

                tmp = load_reg(s, rd);

                tmp2 = load_reg(s, rm);

                gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                tcg_temp_free_i32(tmp);

                break;

            case 2: 

                tmp = load_reg(s, rm);

                store_reg(s, rd, tmp);

                break;

            case 3:

                tmp = load_reg(s, rm);

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

                    ARCH(5);

                    val = (uint32_t)s->pc | 1;

                    tmp2 = tcg_temp_new_i32();

                    tcg_gen_movi_i32(tmp2, val);

                    store_reg(s, 14, tmp2);

                    gen_bx(s, tmp);

                } else {

                    

                    gen_bx_excret(s, tmp);

                }

                break;

            }

            break;

        }



        

        rd = insn & 7;

        rm = (insn >> 3) & 7;

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

        if (op == 2 || op == 3 || op == 4 || op == 7) {

            

            val = rm;

            rm = rd;

            rd = val;

            val = 1;

        } else {

            val = 0;

        }



        if (op == 9) { 

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, 0);

        } else if (op != 0xf) { 

            tmp = load_reg(s, rd);

        } else {

            TCGV_UNUSED_I32(tmp);

        }



        tmp2 = load_reg(s, rm);

        switch (op) {

        case 0x0: 

            tcg_gen_and_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0x1: 

            tcg_gen_xor_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0x2: 

            if (s->condexec_mask) {

                gen_shl(tmp2, tmp2, tmp);

            } else {

                gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x3: 

            if (s->condexec_mask) {

                gen_shr(tmp2, tmp2, tmp);

            } else {

                gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x4: 

            if (s->condexec_mask) {

                gen_sar(tmp2, tmp2, tmp);

            } else {

                gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x5: 

            if (s->condexec_mask) {

                gen_adc(tmp, tmp2);

            } else {

                gen_adc_CC(tmp, tmp, tmp2);

            }

            break;

        case 0x6: 

            if (s->condexec_mask) {

                gen_sub_carry(tmp, tmp, tmp2);

            } else {

                gen_sbc_CC(tmp, tmp, tmp2);

            }

            break;

        case 0x7: 

            if (s->condexec_mask) {

                tcg_gen_andi_i32(tmp, tmp, 0x1f);

                tcg_gen_rotr_i32(tmp2, tmp2, tmp);

            } else {

                gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x8: 

            tcg_gen_and_i32(tmp, tmp, tmp2);

            gen_logic_CC(tmp);

            rd = 16;

            break;

        case 0x9: 

            if (s->condexec_mask)

                tcg_gen_neg_i32(tmp, tmp2);

            else

                gen_sub_CC(tmp, tmp, tmp2);

            break;

        case 0xa: 

            gen_sub_CC(tmp, tmp, tmp2);

            rd = 16;

            break;

        case 0xb: 

            gen_add_CC(tmp, tmp, tmp2);

            rd = 16;

            break;

        case 0xc: 

            tcg_gen_or_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xd: 

            tcg_gen_mul_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xe: 

            tcg_gen_andc_i32(tmp, tmp, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xf: 

            tcg_gen_not_i32(tmp2, tmp2);

            if (!s->condexec_mask)

                gen_logic_CC(tmp2);

            val = 1;

            rm = rd;

            break;

        }

        if (rd != 16) {

            if (val) {

                store_reg(s, rm, tmp2);

                if (op != 0xf)

                    tcg_temp_free_i32(tmp);

            } else {

                store_reg(s, rd, tmp);

                tcg_temp_free_i32(tmp2);

            }

        } else {

            tcg_temp_free_i32(tmp);

            tcg_temp_free_i32(tmp2);

        }

        break;



    case 5:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        rm = (insn >> 6) & 7;

        op = (insn >> 9) & 7;

        addr = load_reg(s, rn);

        tmp = load_reg(s, rm);

        tcg_gen_add_i32(addr, addr, tmp);

        tcg_temp_free_i32(tmp);



        if (op < 3) { 

            tmp = load_reg(s, rd);

        } else {

            tmp = tcg_temp_new_i32();

        }



        switch (op) {

        case 0: 

            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 1: 

            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 2: 

            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 3: 

            gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 4: 

            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 5: 

            gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 6: 

            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        case 7: 

            gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            break;

        }

        if (op >= 3) { 

            store_reg(s, rd, tmp);

        } else {

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 6:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(s, rn);

        val = (insn >> 4) & 0x7c;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

            store_reg(s, rd, tmp);

        } else {

            

            tmp = load_reg(s, rd);

            gen_aa32_st32(s, tmp, addr, get_mem_index(s));

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 7:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(s, rn);

        val = (insn >> 6) & 0x1f;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            store_reg(s, rd, tmp);

        } else {

            

            tmp = load_reg(s, rd);

            gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 8:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(s, rn);

        val = (insn >> 5) & 0x3e;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            store_reg(s, rd, tmp);

        } else {

            

            tmp = load_reg(s, rd);

            gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 9:

        

        rd = (insn >> 8) & 7;

        addr = load_reg(s, 13);

        val = (insn & 0xff) * 4;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            store_reg(s, rd, tmp);

        } else {

            

            tmp = load_reg(s, rd);

            gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 10:

        

        rd = (insn >> 8) & 7;

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

            

            tmp = load_reg(s, 13);

        } else {

            

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);

        }

        val = (insn & 0xff) * 4;

        tcg_gen_addi_i32(tmp, tmp, val);

        store_reg(s, rd, tmp);

        break;



    case 11:

        

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

        switch (op) {

        case 0:

            

            tmp = load_reg(s, 13);

            val = (insn & 0x7f) * 4;

            if (insn & (1 << 7))

                val = -(int32_t)val;

            tcg_gen_addi_i32(tmp, tmp, val);

            store_reg(s, 13, tmp);

            break;



        case 2: 

            ARCH(6);

            rd = insn & 7;

            rm = (insn >> 3) & 7;

            tmp = load_reg(s, rm);

            switch ((insn >> 6) & 3) {

            case 0: gen_sxth(tmp); break;

            case 1: gen_sxtb(tmp); break;

            case 2: gen_uxth(tmp); break;

            case 3: gen_uxtb(tmp); break;

            }

            store_reg(s, rd, tmp);

            break;

        case 4: case 5: case 0xc: case 0xd:

            

            addr = load_reg(s, 13);

            if (insn & (1 << 8))

                offset = 4;

            else

                offset = 0;

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

                if (insn & (1 << i))

                    offset += 4;

            }

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

                tcg_gen_addi_i32(addr, addr, -offset);

            }

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

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

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

                        

                        tmp = tcg_temp_new_i32();

                        gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

                        store_reg(s, i, tmp);

                    } else {

                        

                        tmp = load_reg(s, i);

                        gen_aa32_st32(s, tmp, addr, get_mem_index(s));

                        tcg_temp_free_i32(tmp);

                    }

                    

                    tcg_gen_addi_i32(addr, addr, 4);

                }

            }

            TCGV_UNUSED_I32(tmp);

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

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

                    

                    tmp = tcg_temp_new_i32();

                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

                    



                } else {

                    

                    tmp = load_reg(s, 14);

                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));

                    tcg_temp_free_i32(tmp);

                }

                tcg_gen_addi_i32(addr, addr, 4);

            }

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

                tcg_gen_addi_i32(addr, addr, -offset);

            }

            

            store_reg(s, 13, addr);

            

            if ((insn & 0x0900) == 0x0900) {

                store_reg_from_load(s, 15, tmp);

            }

            break;



        case 1: case 3: case 9: case 11: 

            rm = insn & 7;

            tmp = load_reg(s, rm);

            s->condlabel = gen_new_label();

            s->condjmp = 1;

            if (insn & (1 << 11))

                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);

            else

                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);

            tcg_temp_free_i32(tmp);

            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;

            val = (uint32_t)s->pc + 2;

            val += offset;

            gen_jmp(s, val);

            break;



        case 15: 

            if ((insn & 0xf) == 0) {

                gen_nop_hint(s, (insn >> 4) & 0xf);

                break;

            }

            

            s->condexec_cond = (insn >> 4) & 0xe;

            s->condexec_mask = insn & 0x1f;

            

            break;



        case 0xe: 

        {

            int imm8 = extract32(insn, 0, 8);

            ARCH(5);

            gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),

                               default_exception_el(s));

            break;

        }



        case 0xa: 

        {

            int op1 = extract32(insn, 6, 2);



            if (op1 == 2) {

                

                int imm6 = extract32(insn, 0, 6);



                gen_hlt(s, imm6);

                break;

            }



            

            ARCH(6);

            rn = (insn >> 3) & 0x7;

            rd = insn & 0x7;

            tmp = load_reg(s, rn);

            switch (op1) {

            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;

            case 1: gen_rev16(tmp); break;

            case 3: gen_revsh(tmp); break;

            default:

                g_assert_not_reached();

            }

            store_reg(s, rd, tmp);

            break;

        }



        case 6:

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

            case 2:

                

                ARCH(6);

                if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {

                    gen_helper_setend(cpu_env);

                    s->is_jmp = DISAS_UPDATE;

                }

                break;

            case 3:

                

                ARCH(6);

                if (IS_USER(s)) {

                    break;

                }

                if (arm_dc_feature(s, ARM_FEATURE_M)) {

                    tmp = tcg_const_i32((insn & (1 << 4)) != 0);

                    

                    if (insn & 1) {

                        addr = tcg_const_i32(19);

                        gen_helper_v7m_msr(cpu_env, addr, tmp);

                        tcg_temp_free_i32(addr);

                    }

                    

                    if (insn & 2) {

                        addr = tcg_const_i32(16);

                        gen_helper_v7m_msr(cpu_env, addr, tmp);

                        tcg_temp_free_i32(addr);

                    }

                    tcg_temp_free_i32(tmp);

                    gen_lookup_tb(s);

                } else {

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

                        shift = CPSR_A | CPSR_I | CPSR_F;

                    } else {

                        shift = 0;

                    }

                    gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);

                }

                break;

            default:

                goto undef;

            }

            break;



        default:

            goto undef;

        }

        break;



    case 12:

    {

        

        TCGv_i32 loaded_var;

        TCGV_UNUSED_I32(loaded_var);

        rn = (insn >> 8) & 0x7;

        addr = load_reg(s, rn);

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

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

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

                    

                    tmp = tcg_temp_new_i32();

                    gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));

                    if (i == rn) {

                        loaded_var = tmp;

                    } else {

                        store_reg(s, i, tmp);

                    }

                } else {

                    

                    tmp = load_reg(s, i);

                    gen_aa32_st32(s, tmp, addr, get_mem_index(s));

                    tcg_temp_free_i32(tmp);

                }

                

                tcg_gen_addi_i32(addr, addr, 4);

            }

        }

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

            

            store_reg(s, rn, addr);

        } else {

            

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

                store_reg(s, rn, loaded_var);

            }

            tcg_temp_free_i32(addr);

        }

        break;

    }

    case 13:

        

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

        if (cond == 0xe)

            goto undef;



        if (cond == 0xf) {

            

            gen_set_pc_im(s, s->pc);

            s->svc_imm = extract32(insn, 0, 8);

            s->is_jmp = DISAS_SWI;

            break;

        }

        

        s->condlabel = gen_new_label();

        arm_gen_test_cc(cond ^ 1, s->condlabel);

        s->condjmp = 1;



        

        val = (uint32_t)s->pc + 2;

        offset = ((int32_t)insn << 24) >> 24;

        val += offset << 1;

        gen_jmp(s, val);

        break;



    case 14:

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

            if (disas_thumb2_insn(env, s, insn))

              goto undef32;

            break;

        }

        

        val = (uint32_t)s->pc;

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

        val += (offset << 1) + 2;

        gen_jmp(s, val);

        break;



    case 15:

        if (disas_thumb2_insn(env, s, insn))

            goto undef32;

        break;

    }

    return;

undef32:

    gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),

                       default_exception_el(s));

    return;

illegal_op:

undef:

    gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),

                       default_exception_el(s));

}

                tmp = load_reg(s, rm);                 if (insn & (1 << 7)) {
static void FUNC_0(CPUARMState *VAR_0, DisasContext *VAR_1)

{

    uint32_t val, insn, op, rm, rn, rd, shift, cond;

    int32_t offset;

    int VAR_2;

    TCGv_i32 tmp;

    TCGv_i32 tmp2;

    TCGv_i32 addr;



    if (VAR_1->condexec_mask) {

        cond = VAR_1->condexec_cond;

        if (cond != 0x0e) {     

          VAR_1->condlabel = gen_new_label();

          arm_gen_test_cc(cond ^ 1, VAR_1->condlabel);

          VAR_1->condjmp = 1;

        }

    }



    insn = arm_lduw_code(VAR_0, VAR_1->pc, VAR_1->sctlr_b);

    VAR_1->pc += 2;



    switch (insn >> 12) {

    case 0: case 1:



        rd = insn & 7;

        op = (insn >> 11) & 3;

        if (op == 3) {

            

            rn = (insn >> 3) & 7;

            tmp = load_reg(VAR_1, rn);

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

                

                tmp2 = tcg_temp_new_i32();

                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);

            } else {

                

                rm = (insn >> 6) & 7;

                tmp2 = load_reg(VAR_1, rm);

            }

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

                if (VAR_1->condexec_mask)

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                else

                    gen_sub_CC(tmp, tmp, tmp2);

            } else {

                if (VAR_1->condexec_mask)

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                else

                    gen_add_CC(tmp, tmp, tmp2);

            }

            tcg_temp_free_i32(tmp2);

            store_reg(VAR_1, rd, tmp);

        } else {

            

            rm = (insn >> 3) & 7;

            shift = (insn >> 6) & 0x1f;

            tmp = load_reg(VAR_1, rm);

            gen_arm_shift_im(tmp, op, shift, VAR_1->condexec_mask == 0);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            store_reg(VAR_1, rd, tmp);

        }

        break;

    case 2: case 3:

        

        op = (insn >> 11) & 3;

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

        if (op == 0) { 

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, insn & 0xff);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            store_reg(VAR_1, rd, tmp);

        } else {

            tmp = load_reg(VAR_1, rd);

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, insn & 0xff);

            switch (op) {

            case 1: 

                gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp);

                tcg_temp_free_i32(tmp2);

                break;

            case 2: 

                if (VAR_1->condexec_mask)

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                else

                    gen_add_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(VAR_1, rd, tmp);

                break;

            case 3: 

                if (VAR_1->condexec_mask)

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                else

                    gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(VAR_1, rd, tmp);

                break;

            }

        }

        break;

    case 4:

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

            rd = (insn >> 8) & 7;

            

            val = VAR_1->pc + 2 + ((insn & 0xff) * 4);

            val &= ~(uint32_t)2;

            addr = tcg_temp_new_i32();

            tcg_gen_movi_i32(addr, val);

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1),

                               rd | ISSIs16Bit);

            tcg_temp_free_i32(addr);

            store_reg(VAR_1, rd, tmp);

            break;

        }

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

            

            rd = (insn & 7) | ((insn >> 4) & 8);

            rm = (insn >> 3) & 0xf;

            op = (insn >> 8) & 3;

            switch (op) {

            case 0: 

                tmp = load_reg(VAR_1, rd);

                tmp2 = load_reg(VAR_1, rm);

                tcg_gen_add_i32(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(VAR_1, rd, tmp);

                break;

            case 1: 

                tmp = load_reg(VAR_1, rd);

                tmp2 = load_reg(VAR_1, rm);

                gen_sub_CC(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                tcg_temp_free_i32(tmp);

                break;

            case 2: 

                tmp = load_reg(VAR_1, rm);

                store_reg(VAR_1, rd, tmp);

                break;

            case 3:

                tmp = load_reg(VAR_1, rm);

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

                    ARCH(5);

                    val = (uint32_t)VAR_1->pc | 1;

                    tmp2 = tcg_temp_new_i32();

                    tcg_gen_movi_i32(tmp2, val);

                    store_reg(VAR_1, 14, tmp2);

                    gen_bx(VAR_1, tmp);

                } else {

                    

                    gen_bx_excret(VAR_1, tmp);

                }

                break;

            }

            break;

        }



        

        rd = insn & 7;

        rm = (insn >> 3) & 7;

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

        if (op == 2 || op == 3 || op == 4 || op == 7) {

            

            val = rm;

            rm = rd;

            rd = val;

            val = 1;

        } else {

            val = 0;

        }



        if (op == 9) { 

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, 0);

        } else if (op != 0xf) { 

            tmp = load_reg(VAR_1, rd);

        } else {

            TCGV_UNUSED_I32(tmp);

        }



        tmp2 = load_reg(VAR_1, rm);

        switch (op) {

        case 0x0: 

            tcg_gen_and_i32(tmp, tmp, tmp2);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0x1: 

            tcg_gen_xor_i32(tmp, tmp, tmp2);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0x2: 

            if (VAR_1->condexec_mask) {

                gen_shl(tmp2, tmp2, tmp);

            } else {

                gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x3: 

            if (VAR_1->condexec_mask) {

                gen_shr(tmp2, tmp2, tmp);

            } else {

                gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x4: 

            if (VAR_1->condexec_mask) {

                gen_sar(tmp2, tmp2, tmp);

            } else {

                gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x5: 

            if (VAR_1->condexec_mask) {

                gen_adc(tmp, tmp2);

            } else {

                gen_adc_CC(tmp, tmp, tmp2);

            }

            break;

        case 0x6: 

            if (VAR_1->condexec_mask) {

                gen_sub_carry(tmp, tmp, tmp2);

            } else {

                gen_sbc_CC(tmp, tmp, tmp2);

            }

            break;

        case 0x7: 

            if (VAR_1->condexec_mask) {

                tcg_gen_andi_i32(tmp, tmp, 0x1f);

                tcg_gen_rotr_i32(tmp2, tmp2, tmp);

            } else {

                gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);

                gen_logic_CC(tmp2);

            }

            break;

        case 0x8: 

            tcg_gen_and_i32(tmp, tmp, tmp2);

            gen_logic_CC(tmp);

            rd = 16;

            break;

        case 0x9: 

            if (VAR_1->condexec_mask)

                tcg_gen_neg_i32(tmp, tmp2);

            else

                gen_sub_CC(tmp, tmp, tmp2);

            break;

        case 0xa: 

            gen_sub_CC(tmp, tmp, tmp2);

            rd = 16;

            break;

        case 0xb: 

            gen_add_CC(tmp, tmp, tmp2);

            rd = 16;

            break;

        case 0xc: 

            tcg_gen_or_i32(tmp, tmp, tmp2);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xd: 

            tcg_gen_mul_i32(tmp, tmp, tmp2);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xe: 

            tcg_gen_andc_i32(tmp, tmp, tmp2);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp);

            break;

        case 0xf: 

            tcg_gen_not_i32(tmp2, tmp2);

            if (!VAR_1->condexec_mask)

                gen_logic_CC(tmp2);

            val = 1;

            rm = rd;

            break;

        }

        if (rd != 16) {

            if (val) {

                store_reg(VAR_1, rm, tmp2);

                if (op != 0xf)

                    tcg_temp_free_i32(tmp);

            } else {

                store_reg(VAR_1, rd, tmp);

                tcg_temp_free_i32(tmp2);

            }

        } else {

            tcg_temp_free_i32(tmp);

            tcg_temp_free_i32(tmp2);

        }

        break;



    case 5:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        rm = (insn >> 6) & 7;

        op = (insn >> 9) & 7;

        addr = load_reg(VAR_1, rn);

        tmp = load_reg(VAR_1, rm);

        tcg_gen_add_i32(addr, addr, tmp);

        tcg_temp_free_i32(tmp);



        if (op < 3) { 

            tmp = load_reg(VAR_1, rd);

        } else {

            tmp = tcg_temp_new_i32();

        }



        switch (op) {

        case 0: 

            gen_aa32_st32_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 1: 

            gen_aa32_st16_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 2: 

            gen_aa32_st8_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 3: 

            gen_aa32_ld8s_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 4: 

            gen_aa32_ld32u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 5: 

            gen_aa32_ld16u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 6: 

            gen_aa32_ld8u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        case 7: 

            gen_aa32_ld16s_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            break;

        }

        if (op >= 3) { 

            store_reg(VAR_1, rd, tmp);

        } else {

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 6:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(VAR_1, rn);

        val = (insn >> 4) & 0x7c;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1));

            store_reg(VAR_1, rd, tmp);

        } else {

            

            tmp = load_reg(VAR_1, rd);

            gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1));

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 7:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(VAR_1, rn);

        val = (insn >> 6) & 0x1f;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld8u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            store_reg(VAR_1, rd, tmp);

        } else {

            

            tmp = load_reg(VAR_1, rd);

            gen_aa32_st8_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 8:

        

        rd = insn & 7;

        rn = (insn >> 3) & 7;

        addr = load_reg(VAR_1, rn);

        val = (insn >> 5) & 0x3e;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld16u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            store_reg(VAR_1, rd, tmp);

        } else {

            

            tmp = load_reg(VAR_1, rd);

            gen_aa32_st16_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 9:

        

        rd = (insn >> 8) & 7;

        addr = load_reg(VAR_1, 13);

        val = (insn & 0xff) * 4;

        tcg_gen_addi_i32(addr, addr, val);



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

            

            tmp = tcg_temp_new_i32();

            gen_aa32_ld32u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            store_reg(VAR_1, rd, tmp);

        } else {

            

            tmp = load_reg(VAR_1, rd);

            gen_aa32_st32_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit);

            tcg_temp_free_i32(tmp);

        }

        tcg_temp_free_i32(addr);

        break;



    case 10:

        

        rd = (insn >> 8) & 7;

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

            

            tmp = load_reg(VAR_1, 13);

        } else {

            

            tmp = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp, (VAR_1->pc + 2) & ~(uint32_t)2);

        }

        val = (insn & 0xff) * 4;

        tcg_gen_addi_i32(tmp, tmp, val);

        store_reg(VAR_1, rd, tmp);

        break;



    case 11:

        

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

        switch (op) {

        case 0:

            

            tmp = load_reg(VAR_1, 13);

            val = (insn & 0x7f) * 4;

            if (insn & (1 << 7))

                val = -(int32_t)val;

            tcg_gen_addi_i32(tmp, tmp, val);

            store_reg(VAR_1, 13, tmp);

            break;



        case 2: 

            ARCH(6);

            rd = insn & 7;

            rm = (insn >> 3) & 7;

            tmp = load_reg(VAR_1, rm);

            switch ((insn >> 6) & 3) {

            case 0: gen_sxth(tmp); break;

            case 1: gen_sxtb(tmp); break;

            case 2: gen_uxth(tmp); break;

            case 3: gen_uxtb(tmp); break;

            }

            store_reg(VAR_1, rd, tmp);

            break;

        case 4: case 5: case 0xc: case 0xd:

            

            addr = load_reg(VAR_1, 13);

            if (insn & (1 << 8))

                offset = 4;

            else

                offset = 0;

            for (VAR_2 = 0; VAR_2 < 8; VAR_2++) {

                if (insn & (1 << VAR_2))

                    offset += 4;

            }

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

                tcg_gen_addi_i32(addr, addr, -offset);

            }

            for (VAR_2 = 0; VAR_2 < 8; VAR_2++) {

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

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

                        

                        tmp = tcg_temp_new_i32();

                        gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1));

                        store_reg(VAR_1, VAR_2, tmp);

                    } else {

                        

                        tmp = load_reg(VAR_1, VAR_2);

                        gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1));

                        tcg_temp_free_i32(tmp);

                    }

                    

                    tcg_gen_addi_i32(addr, addr, 4);

                }

            }

            TCGV_UNUSED_I32(tmp);

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

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

                    

                    tmp = tcg_temp_new_i32();

                    gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1));

                    



                } else {

                    

                    tmp = load_reg(VAR_1, 14);

                    gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1));

                    tcg_temp_free_i32(tmp);

                }

                tcg_gen_addi_i32(addr, addr, 4);

            }

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

                tcg_gen_addi_i32(addr, addr, -offset);

            }

            

            store_reg(VAR_1, 13, addr);

            

            if ((insn & 0x0900) == 0x0900) {

                store_reg_from_load(VAR_1, 15, tmp);

            }

            break;



        case 1: case 3: case 9: case 11: 

            rm = insn & 7;

            tmp = load_reg(VAR_1, rm);

            VAR_1->condlabel = gen_new_label();

            VAR_1->condjmp = 1;

            if (insn & (1 << 11))

                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, VAR_1->condlabel);

            else

                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, VAR_1->condlabel);

            tcg_temp_free_i32(tmp);

            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;

            val = (uint32_t)VAR_1->pc + 2;

            val += offset;

            gen_jmp(VAR_1, val);

            break;



        case 15: 

            if ((insn & 0xf) == 0) {

                gen_nop_hint(VAR_1, (insn >> 4) & 0xf);

                break;

            }

            

            VAR_1->condexec_cond = (insn >> 4) & 0xe;

            VAR_1->condexec_mask = insn & 0x1f;

            

            break;



        case 0xe: 

        {

            int VAR_3 = extract32(insn, 0, 8);

            ARCH(5);

            gen_exception_insn(VAR_1, 2, EXCP_BKPT, syn_aa32_bkpt(VAR_3, true),

                               default_exception_el(VAR_1));

            break;

        }



        case 0xa: 

        {

            int VAR_4 = extract32(insn, 6, 2);



            if (VAR_4 == 2) {

                

                int VAR_5 = extract32(insn, 0, 6);



                gen_hlt(VAR_1, VAR_5);

                break;

            }



            

            ARCH(6);

            rn = (insn >> 3) & 0x7;

            rd = insn & 0x7;

            tmp = load_reg(VAR_1, rn);

            switch (VAR_4) {

            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;

            case 1: gen_rev16(tmp); break;

            case 3: gen_revsh(tmp); break;

            default:

                g_assert_not_reached();

            }

            store_reg(VAR_1, rd, tmp);

            break;

        }



        case 6:

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

            case 2:

                

                ARCH(6);

                if (((insn >> 3) & 1) != !!(VAR_1->be_data == MO_BE)) {

                    gen_helper_setend(cpu_env);

                    VAR_1->is_jmp = DISAS_UPDATE;

                }

                break;

            case 3:

                

                ARCH(6);

                if (IS_USER(VAR_1)) {

                    break;

                }

                if (arm_dc_feature(VAR_1, ARM_FEATURE_M)) {

                    tmp = tcg_const_i32((insn & (1 << 4)) != 0);

                    

                    if (insn & 1) {

                        addr = tcg_const_i32(19);

                        gen_helper_v7m_msr(cpu_env, addr, tmp);

                        tcg_temp_free_i32(addr);

                    }

                    

                    if (insn & 2) {

                        addr = tcg_const_i32(16);

                        gen_helper_v7m_msr(cpu_env, addr, tmp);

                        tcg_temp_free_i32(addr);

                    }

                    tcg_temp_free_i32(tmp);

                    gen_lookup_tb(VAR_1);

                } else {

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

                        shift = CPSR_A | CPSR_I | CPSR_F;

                    } else {

                        shift = 0;

                    }

                    gen_set_psr_im(VAR_1, ((insn & 7) << 6), 0, shift);

                }

                break;

            default:

                goto undef;

            }

            break;



        default:

            goto undef;

        }

        break;



    case 12:

    {

        

        TCGv_i32 loaded_var;

        TCGV_UNUSED_I32(loaded_var);

        rn = (insn >> 8) & 0x7;

        addr = load_reg(VAR_1, rn);

        for (VAR_2 = 0; VAR_2 < 8; VAR_2++) {

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

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

                    

                    tmp = tcg_temp_new_i32();

                    gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1));

                    if (VAR_2 == rn) {

                        loaded_var = tmp;

                    } else {

                        store_reg(VAR_1, VAR_2, tmp);

                    }

                } else {

                    

                    tmp = load_reg(VAR_1, VAR_2);

                    gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1));

                    tcg_temp_free_i32(tmp);

                }

                

                tcg_gen_addi_i32(addr, addr, 4);

            }

        }

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

            

            store_reg(VAR_1, rn, addr);

        } else {

            

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

                store_reg(VAR_1, rn, loaded_var);

            }

            tcg_temp_free_i32(addr);

        }

        break;

    }

    case 13:

        

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

        if (cond == 0xe)

            goto undef;



        if (cond == 0xf) {

            

            gen_set_pc_im(VAR_1, VAR_1->pc);

            VAR_1->svc_imm = extract32(insn, 0, 8);

            VAR_1->is_jmp = DISAS_SWI;

            break;

        }

        

        VAR_1->condlabel = gen_new_label();

        arm_gen_test_cc(cond ^ 1, VAR_1->condlabel);

        VAR_1->condjmp = 1;



        

        val = (uint32_t)VAR_1->pc + 2;

        offset = ((int32_t)insn << 24) >> 24;

        val += offset << 1;

        gen_jmp(VAR_1, val);

        break;



    case 14:

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

            if (disas_thumb2_insn(VAR_0, VAR_1, insn))

              goto undef32;

            break;

        }

        

        val = (uint32_t)VAR_1->pc;

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

        val += (offset << 1) + 2;

        gen_jmp(VAR_1, val);

        break;



    case 15:

        if (disas_thumb2_insn(VAR_0, VAR_1, insn))

            goto undef32;

        break;

    }

    return;

undef32:

    gen_exception_insn(VAR_1, 4, EXCP_UDEF, syn_uncategorized(),

                       default_exception_el(VAR_1));

    return;

illegal_op:

undef:

    gen_exception_insn(VAR_1, 2, EXCP_UDEF, syn_uncategorized(),

                       default_exception_el(VAR_1));

}

static void FUNC_0(CPUARMState *VAR_0, DisasContext *VAR_1)
{ uint32_t val, insn, op, rm, rn, rd, shift, cond; int32_t offset; int VAR_2; TCGv_i32 tmp; TCGv_i32 tmp2; TCGv_i32 addr; if (VAR_1->condexec_mask) { cond = VAR_1->condexec_cond; if (cond != 0x0e) { VAR_1->condlabel = gen_new_label(); arm_gen_test_cc(cond ^ 1, VAR_1->condlabel); VAR_1->condjmp = 1; } } insn = arm_lduw_code(VAR_0, VAR_1->pc, VAR_1->sctlr_b); VAR_1->pc += 2; switch (insn >> 12) { case 0: case 1:
rd = insn & 7; op = (insn >> 11) & 3; if (op == 3) { rn = (insn >> 3) & 7; tmp = load_reg(VAR_1, rn); if (insn & (1 << 10)) { tmp2 = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp2, (insn >> 6) & 7); } else { rm = (insn >> 6) & 7; tmp2 = load_reg(VAR_1, rm); } if (insn & (1 << 9)) { if (VAR_1->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2); else
gen_sub_CC(tmp, tmp, tmp2); } else { if (VAR_1->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2); else
gen_add_CC(tmp, tmp, tmp2); } tcg_temp_free_i32(tmp2); store_reg(VAR_1, rd, tmp); } else { rm = (insn >> 3) & 7; shift = (insn >> 6) & 0x1f; tmp = load_reg(VAR_1, rm); gen_arm_shift_im(tmp, op, shift, VAR_1->condexec_mask == 0); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); store_reg(VAR_1, rd, tmp); } break; case 2: case 3:
op = (insn >> 11) & 3; rd = (insn >> 8) & 0x7; if (op == 0) { tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, insn & 0xff); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); store_reg(VAR_1, rd, tmp); } else { tmp = load_reg(VAR_1, rd); tmp2 = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp2, insn & 0xff); switch (op) { case 1:
gen_sub_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); break; case 2:
if (VAR_1->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2); else
gen_add_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(VAR_1, rd, tmp); break; case 3:
if (VAR_1->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2); else
gen_sub_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(VAR_1, rd, tmp); break; } } break; case 4:
if (insn & (1 << 11)) { rd = (insn >> 8) & 7; val = VAR_1->pc + 2 + ((insn & 0xff) * 4); val &= ~(uint32_t)2; addr = tcg_temp_new_i32(); tcg_gen_movi_i32(addr, val); tmp = tcg_temp_new_i32(); gen_aa32_ld32u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1),
rd | ISSIs16Bit); tcg_temp_free_i32(addr); store_reg(VAR_1, rd, tmp); break; } if (insn & (1 << 10)) { rd = (insn & 7) | ((insn >> 4) & 8); rm = (insn >> 3) & 0xf; op = (insn >> 8) & 3; switch (op) { case 0:
tmp = load_reg(VAR_1, rd); tmp2 = load_reg(VAR_1, rm); tcg_gen_add_i32(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); store_reg(VAR_1, rd, tmp); break; case 1:
tmp = load_reg(VAR_1, rd); tmp2 = load_reg(VAR_1, rm); gen_sub_CC(tmp, tmp, tmp2); tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp); break; case 2:
tmp = load_reg(VAR_1, rm); store_reg(VAR_1, rd, tmp); break; case 3:
tmp = load_reg(VAR_1, rm); if (insn & (1 << 7)) { ARCH(5); val = (uint32_t)VAR_1->pc | 1; tmp2 = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp2, val); store_reg(VAR_1, 14, tmp2); gen_bx(VAR_1, tmp); } else { gen_bx_excret(VAR_1, tmp); } break; } break; } rd = insn & 7; rm = (insn >> 3) & 7; op = (insn >> 6) & 0xf; if (op == 2 || op == 3 || op == 4 || op == 7) { val = rm; rm = rd; rd = val; val = 1; } else { val = 0; } if (op == 9) { tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, 0); } else if (op != 0xf) { tmp = load_reg(VAR_1, rd); } else { TCGV_UNUSED_I32(tmp); } tmp2 = load_reg(VAR_1, rm); switch (op) { case 0x0:
tcg_gen_and_i32(tmp, tmp, tmp2); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); break; case 0x1:
tcg_gen_xor_i32(tmp, tmp, tmp2); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); break; case 0x2:
if (VAR_1->condexec_mask) { gen_shl(tmp2, tmp2, tmp); } else { gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x3:
if (VAR_1->condexec_mask) { gen_shr(tmp2, tmp2, tmp); } else { gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x4:
if (VAR_1->condexec_mask) { gen_sar(tmp2, tmp2, tmp); } else { gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x5:
if (VAR_1->condexec_mask) { gen_adc(tmp, tmp2); } else { gen_adc_CC(tmp, tmp, tmp2); } break; case 0x6:
if (VAR_1->condexec_mask) { gen_sub_carry(tmp, tmp, tmp2); } else { gen_sbc_CC(tmp, tmp, tmp2); } break; case 0x7:
if (VAR_1->condexec_mask) { tcg_gen_andi_i32(tmp, tmp, 0x1f); tcg_gen_rotr_i32(tmp2, tmp2, tmp); } else { gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp); gen_logic_CC(tmp2); } break; case 0x8:
tcg_gen_and_i32(tmp, tmp, tmp2); gen_logic_CC(tmp); rd = 16; break; case 0x9:
if (VAR_1->condexec_mask)
tcg_gen_neg_i32(tmp, tmp2); else
gen_sub_CC(tmp, tmp, tmp2); break; case 0xa:
gen_sub_CC(tmp, tmp, tmp2); rd = 16; break; case 0xb:
gen_add_CC(tmp, tmp, tmp2); rd = 16; break; case 0xc:
tcg_gen_or_i32(tmp, tmp, tmp2); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); break; case 0xd:
tcg_gen_mul_i32(tmp, tmp, tmp2); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); break; case 0xe:
tcg_gen_andc_i32(tmp, tmp, tmp2); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp); break; case 0xf:
tcg_gen_not_i32(tmp2, tmp2); if (!VAR_1->condexec_mask)
gen_logic_CC(tmp2); val = 1; rm = rd; break; } if (rd != 16) { if (val) { store_reg(VAR_1, rm, tmp2); if (op != 0xf)
tcg_temp_free_i32(tmp); } else { store_reg(VAR_1, rd, tmp); tcg_temp_free_i32(tmp2); } } else { tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp2); } break; case 5:
rd = insn & 7; rn = (insn >> 3) & 7; rm = (insn >> 6) & 7; op = (insn >> 9) & 7; addr = load_reg(VAR_1, rn); tmp = load_reg(VAR_1, rm); tcg_gen_add_i32(addr, addr, tmp); tcg_temp_free_i32(tmp); if (op < 3) { tmp = load_reg(VAR_1, rd); } else { tmp = tcg_temp_new_i32(); } switch (op) { case 0:
gen_aa32_st32_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 1:
gen_aa32_st16_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 2:
gen_aa32_st8_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 3:
gen_aa32_ld8s_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 4:
gen_aa32_ld32u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 5:
gen_aa32_ld16u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 6:
gen_aa32_ld8u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; case 7:
gen_aa32_ld16s_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); break; } if (op >= 3) { store_reg(VAR_1, rd, tmp); } else { tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; case 6:
rd = insn & 7; rn = (insn >> 3) & 7; addr = load_reg(VAR_1, rn); val = (insn >> 4) & 0x7c; tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1)); store_reg(VAR_1, rd, tmp); } else { tmp = load_reg(VAR_1, rd); gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1)); tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; case 7:
rd = insn & 7; rn = (insn >> 3) & 7; addr = load_reg(VAR_1, rn); val = (insn >> 6) & 0x1f; tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld8u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); store_reg(VAR_1, rd, tmp); } else { tmp = load_reg(VAR_1, rd); gen_aa32_st8_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; case 8:
rd = insn & 7; rn = (insn >> 3) & 7; addr = load_reg(VAR_1, rn); val = (insn >> 5) & 0x3e; tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld16u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); store_reg(VAR_1, rd, tmp); } else { tmp = load_reg(VAR_1, rd); gen_aa32_st16_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; case 9:
rd = (insn >> 8) & 7; addr = load_reg(VAR_1, 13); val = (insn & 0xff) * 4; tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld32u_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); store_reg(VAR_1, rd, tmp); } else { tmp = load_reg(VAR_1, rd); gen_aa32_st32_iss(VAR_1, tmp, addr, get_mem_index(VAR_1), rd | ISSIs16Bit); tcg_temp_free_i32(tmp); } tcg_temp_free_i32(addr); break; case 10:
rd = (insn >> 8) & 7; if (insn & (1 << 11)) { tmp = load_reg(VAR_1, 13); } else { tmp = tcg_temp_new_i32(); tcg_gen_movi_i32(tmp, (VAR_1->pc + 2) & ~(uint32_t)2); } val = (insn & 0xff) * 4; tcg_gen_addi_i32(tmp, tmp, val); store_reg(VAR_1, rd, tmp); break; case 11:
op = (insn >> 8) & 0xf; switch (op) { case 0:
tmp = load_reg(VAR_1, 13); val = (insn & 0x7f) * 4; if (insn & (1 << 7))
val = -(int32_t)val; tcg_gen_addi_i32(tmp, tmp, val); store_reg(VAR_1, 13, tmp); break; case 2:
ARCH(6); rd = insn & 7; rm = (insn >> 3) & 7; tmp = load_reg(VAR_1, rm); switch ((insn >> 6) & 3) { case 0: gen_sxth(tmp); break; case 1: gen_sxtb(tmp); break; case 2: gen_uxth(tmp); break; case 3: gen_uxtb(tmp); break; } store_reg(VAR_1, rd, tmp); break; case 4: case 5: case 0xc: case 0xd:
addr = load_reg(VAR_1, 13); if (insn & (1 << 8))
offset = 4; else
offset = 0; for (VAR_2 = 0; VAR_2 < 8; VAR_2++) { if (insn & (1 << VAR_2))
offset += 4; } if ((insn & (1 << 11)) == 0) { tcg_gen_addi_i32(addr, addr, -offset); } for (VAR_2 = 0; VAR_2 < 8; VAR_2++) { if (insn & (1 << VAR_2)) { if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1)); store_reg(VAR_1, VAR_2, tmp); } else { tmp = load_reg(VAR_1, VAR_2); gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1)); tcg_temp_free_i32(tmp); } tcg_gen_addi_i32(addr, addr, 4); } } TCGV_UNUSED_I32(tmp); if (insn & (1 << 8)) { if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1)); } else { tmp = load_reg(VAR_1, 14); gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1)); tcg_temp_free_i32(tmp); } tcg_gen_addi_i32(addr, addr, 4); } if ((insn & (1 << 11)) == 0) { tcg_gen_addi_i32(addr, addr, -offset); } store_reg(VAR_1, 13, addr); if ((insn & 0x0900) == 0x0900) { store_reg_from_load(VAR_1, 15, tmp); } break; case 1: case 3: case 9: case 11:
rm = insn & 7; tmp = load_reg(VAR_1, rm); VAR_1->condlabel = gen_new_label(); VAR_1->condjmp = 1; if (insn & (1 << 11))
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, VAR_1->condlabel); else
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, VAR_1->condlabel); tcg_temp_free_i32(tmp); offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3; val = (uint32_t)VAR_1->pc + 2; val += offset; gen_jmp(VAR_1, val); break; case 15:
if ((insn & 0xf) == 0) { gen_nop_hint(VAR_1, (insn >> 4) & 0xf); break; } VAR_1->condexec_cond = (insn >> 4) & 0xe; VAR_1->condexec_mask = insn & 0x1f; break; case 0xe:
{ int VAR_3 = extract32(insn, 0, 8); ARCH(5); gen_exception_insn(VAR_1, 2, EXCP_BKPT, syn_aa32_bkpt(VAR_3, true),
default_exception_el(VAR_1)); break; } case 0xa:
{ int VAR_4 = extract32(insn, 6, 2); if (VAR_4 == 2) { int VAR_5 = extract32(insn, 0, 6); gen_hlt(VAR_1, VAR_5); break; } ARCH(6); rn = (insn >> 3) & 0x7; rd = insn & 0x7; tmp = load_reg(VAR_1, rn); switch (VAR_4) { case 0: tcg_gen_bswap32_i32(tmp, tmp); break; case 1: gen_rev16(tmp); break; case 3: gen_revsh(tmp); break; default:
g_assert_not_reached(); } store_reg(VAR_1, rd, tmp); break; } case 6:
switch ((insn >> 5) & 7) { case 2:
ARCH(6); if (((insn >> 3) & 1) != !!(VAR_1->be_data == MO_BE)) { gen_helper_setend(cpu_env); VAR_1->is_jmp = DISAS_UPDATE; } break; case 3:
ARCH(6); if (IS_USER(VAR_1)) { break; } if (arm_dc_feature(VAR_1, ARM_FEATURE_M)) { tmp = tcg_const_i32((insn & (1 << 4)) != 0); if (insn & 1) { addr = tcg_const_i32(19); gen_helper_v7m_msr(cpu_env, addr, tmp); tcg_temp_free_i32(addr); } if (insn & 2) { addr = tcg_const_i32(16); gen_helper_v7m_msr(cpu_env, addr, tmp); tcg_temp_free_i32(addr); } tcg_temp_free_i32(tmp); gen_lookup_tb(VAR_1); } else { if (insn & (1 << 4)) { shift = CPSR_A | CPSR_I | CPSR_F; } else { shift = 0; } gen_set_psr_im(VAR_1, ((insn & 7) << 6), 0, shift); } break; default:
goto undef; } break; default:
goto undef; } break; case 12:
{ TCGv_i32 loaded_var; TCGV_UNUSED_I32(loaded_var); rn = (insn >> 8) & 0x7; addr = load_reg(VAR_1, rn); for (VAR_2 = 0; VAR_2 < 8; VAR_2++) { if (insn & (1 << VAR_2)) { if (insn & (1 << 11)) { tmp = tcg_temp_new_i32(); gen_aa32_ld32u(VAR_1, tmp, addr, get_mem_index(VAR_1)); if (VAR_2 == rn) { loaded_var = tmp; } else { store_reg(VAR_1, VAR_2, tmp); } } else { tmp = load_reg(VAR_1, VAR_2); gen_aa32_st32(VAR_1, tmp, addr, get_mem_index(VAR_1)); tcg_temp_free_i32(tmp); } tcg_gen_addi_i32(addr, addr, 4); } } if ((insn & (1 << rn)) == 0) { store_reg(VAR_1, rn, addr); } else { if (insn & (1 << 11)) { store_reg(VAR_1, rn, loaded_var); } tcg_temp_free_i32(addr); } break; } case 13:
cond = (insn >> 8) & 0xf; if (cond == 0xe)
goto undef; if (cond == 0xf) { gen_set_pc_im(VAR_1, VAR_1->pc); VAR_1->svc_imm = extract32(insn, 0, 8); VAR_1->is_jmp = DISAS_SWI; break; } VAR_1->condlabel = gen_new_label(); arm_gen_test_cc(cond ^ 1, VAR_1->condlabel); VAR_1->condjmp = 1; val = (uint32_t)VAR_1->pc + 2; offset = ((int32_t)insn << 24) >> 24; val += offset << 1; gen_jmp(VAR_1, val); break; case 14:
if (insn & (1 << 11)) { if (disas_thumb2_insn(VAR_0, VAR_1, insn))
goto undef32; break; } val = (uint32_t)VAR_1->pc; offset = ((int32_t)insn << 21) >> 21; val += (offset << 1) + 2; gen_jmp(VAR_1, val); break; case 15:
if (disas_thumb2_insn(VAR_0, VAR_1, insn))
goto undef32; break; } return; undef32:
gen_exception_insn(VAR_1, 4, EXCP_UDEF, syn_uncategorized(),
default_exception_el(VAR_1)); return; illegal_op:
undef:
gen_exception_insn(VAR_1, 2, EXCP_UDEF, syn_uncategorized(),
default_exception_el(VAR_1)); }