static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns)

{

    uint16_t insns[5];

    int ld_adr, ld_dst, ld_mop;

    int op_dst, op_src, op_opc;

    int mv_src, mt_dst, st_src, st_mop;

    TCGv op_arg;



    uint32_t pc = ctx->pc;

    uint32_t pc_end = ctx->tb->cs_base;

    int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);

    int max_insns = (pc_end - pc) / 2;

    int i;



    if (pc != pc_end + backup || max_insns < 2) {

        /* This is a malformed gUSA region.  Don't do anything special,

           since the interpreter is likely to get confused.  */

        ctx->envflags &= ~GUSA_MASK;

        return 0;

    }



    if (ctx->tbflags & GUSA_EXCLUSIVE) {

        /* Regardless of single-stepping or the end of the page,

           we must complete execution of the gUSA region while

           holding the exclusive lock.  */

        *pmax_insns = max_insns;

        return 0;

    }



    /* The state machine below will consume only a few insns.

       If there are more than that in a region, fail now.  */

    if (max_insns > ARRAY_SIZE(insns)) {

        goto fail;

    }



    /* Read all of the insns for the region.  */

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

        insns[i] = cpu_lduw_code(env, pc + i * 2);

    }



    ld_adr = ld_dst = ld_mop = -1;

    mv_src = -1;

    op_dst = op_src = op_opc = -1;

    mt_dst = -1;

    st_src = st_mop = -1;

    TCGV_UNUSED(op_arg);

    i = 0;



#define NEXT_INSN \

    do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)



    /*

     * Expect a load to begin the region.

     */

    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x6000: /* mov.b @Rm,Rn */

        ld_mop = MO_SB;

        break;

    case 0x6001: /* mov.w @Rm,Rn */

        ld_mop = MO_TESW;

        break;

    case 0x6002: /* mov.l @Rm,Rn */

        ld_mop = MO_TESL;

        break;

    default:

        goto fail;

    }

    ld_adr = B7_4;

    ld_dst = B11_8;

    if (ld_adr == ld_dst) {

        goto fail;

    }

    /* Unless we see a mov, any two-operand operation must use ld_dst.  */

    op_dst = ld_dst;



    /*

     * Expect an optional register move.

     */

    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x6003: /* mov Rm,Rn */

        /* Here we want to recognize ld_dst being saved for later consumtion,

           or for another input register being copied so that ld_dst need not

           be clobbered during the operation.  */

        op_dst = B11_8;

        mv_src = B7_4;

        if (op_dst == ld_dst) {

            /* Overwriting the load output.  */

            goto fail;

        }

        if (mv_src != ld_dst) {

            /* Copying a new input; constrain op_src to match the load.  */

            op_src = ld_dst;

        }

        break;



    default:

        /* Put back and re-examine as operation.  */

        --i;

    }



    /*

     * Expect the operation.

     */

    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x300c: /* add Rm,Rn */

        op_opc = INDEX_op_add_i32;

        goto do_reg_op;

    case 0x2009: /* and Rm,Rn */

        op_opc = INDEX_op_and_i32;

        goto do_reg_op;

    case 0x200a: /* xor Rm,Rn */

        op_opc = INDEX_op_xor_i32;

        goto do_reg_op;

    case 0x200b: /* or Rm,Rn */

        op_opc = INDEX_op_or_i32;

    do_reg_op:

        /* The operation register should be as expected, and the

           other input cannot depend on the load.  */

        if (op_dst != B11_8) {

            goto fail;

        }

        if (op_src < 0) {

            /* Unconstrainted input.  */

            op_src = B7_4;

        } else if (op_src == B7_4) {

            /* Constrained input matched load.  All operations are

               commutative; "swap" them by "moving" the load output

               to the (implicit) first argument and the move source

               to the (explicit) second argument.  */

            op_src = mv_src;

        } else {

            goto fail;

        }

        op_arg = REG(op_src);

        break;



    case 0x6007: /* not Rm,Rn */

        if (ld_dst != B7_4 || mv_src >= 0) {

            goto fail;

        }

        op_dst = B11_8;

        op_opc = INDEX_op_xor_i32;

        op_arg = tcg_const_i32(-1);

        break;



    case 0x7000 ... 0x700f: /* add #imm,Rn */

        if (op_dst != B11_8 || mv_src >= 0) {

            goto fail;

        }

        op_opc = INDEX_op_add_i32;

        op_arg = tcg_const_i32(B7_0s);

        break;



    case 0x3000: /* cmp/eq Rm,Rn */

        /* Looking for the middle of a compare-and-swap sequence,

           beginning with the compare.  Operands can be either order,

           but with only one overlapping the load.  */

        if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {

            goto fail;

        }

        op_opc = INDEX_op_setcond_i32;  /* placeholder */

        op_src = (ld_dst == B11_8 ? B7_4 : B11_8);

        op_arg = REG(op_src);



        NEXT_INSN;

        switch (ctx->opcode & 0xff00) {

        case 0x8b00: /* bf label */

        case 0x8f00: /* bf/s label */

            if (pc + (i + 1 + B7_0s) * 2 != pc_end) {

                goto fail;

            }

            if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */

                break;

            }

            /* We're looking to unconditionally modify Rn with the

               result of the comparison, within the delay slot of

               the branch.  This is used by older gcc.  */

            NEXT_INSN;

            if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */

                mt_dst = B11_8;

            } else {

                goto fail;

            }

            break;



        default:

            goto fail;

        }

        break;



    case 0x2008: /* tst Rm,Rn */

        /* Looking for a compare-and-swap against zero.  */

        if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {

            goto fail;

        }

        op_opc = INDEX_op_setcond_i32;

        op_arg = tcg_const_i32(0);



        NEXT_INSN;

        if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */

            || pc + (i + 1 + B7_0s) * 2 != pc_end) {

            goto fail;

        }

        break;



    default:

        /* Put back and re-examine as store.  */

        --i;

    }



    /*

     * Expect the store.

     */

    /* The store must be the last insn.  */

    if (i != max_insns - 1) {

        goto fail;

    }

    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x2000: /* mov.b Rm,@Rn */

        st_mop = MO_UB;

        break;

    case 0x2001: /* mov.w Rm,@Rn */

        st_mop = MO_UW;

        break;

    case 0x2002: /* mov.l Rm,@Rn */

        st_mop = MO_UL;

        break;

    default:

        goto fail;

    }

    /* The store must match the load.  */

    if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {

        goto fail;

    }

    st_src = B7_4;



#undef NEXT_INSN



    /*

     * Emit the operation.

     */

    tcg_gen_insn_start(pc, ctx->envflags);

    switch (op_opc) {

    case -1:

        /* No operation found.  Look for exchange pattern.  */

        if (st_src == ld_dst || mv_src >= 0) {

            goto fail;

        }

        tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),

                                ctx->memidx, ld_mop);

        break;



    case INDEX_op_add_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst && st_mop == MO_UL) {

            tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

            if (op_dst != ld_dst) {

                /* Note that mop sizes < 4 cannot use add_fetch

                   because it won't carry into the higher bits.  */

                tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);

            }

        }

        break;



    case INDEX_op_and_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst) {

            tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

            tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);

        }

        break;



    case INDEX_op_or_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst) {

            tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),

                                        op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),

                                        op_arg, ctx->memidx, ld_mop);

            tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);

        }

        break;



    case INDEX_op_xor_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst) {

            tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

            tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);

        }

        break;



    case INDEX_op_setcond_i32:

        if (st_src == ld_dst) {

            goto fail;

        }

        tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,

                                   REG(st_src), ctx->memidx, ld_mop);

        tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);

        if (mt_dst >= 0) {

            tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);

        }

        break;



    default:

        g_assert_not_reached();

    }



    /* If op_src is not a valid register, then op_arg was a constant.  */

    if (op_src < 0) {

        tcg_temp_free_i32(op_arg);

    }



    /* The entire region has been translated.  */

    ctx->envflags &= ~GUSA_MASK;

    ctx->pc = pc_end;

    return max_insns;



 fail:

    qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",

                  pc, pc_end);



    /* Restart with the EXCLUSIVE bit set, within a TB run via

       cpu_exec_step_atomic holding the exclusive lock.  */

    tcg_gen_insn_start(pc, ctx->envflags);

    ctx->envflags |= GUSA_EXCLUSIVE;

    gen_save_cpu_state(ctx, false);

    gen_helper_exclusive(cpu_env);

    ctx->bstate = BS_EXCP;



    /* We're not executing an instruction, but we must report one for the

       purposes of accounting within the TB.  We might as well report the

       entire region consumed via ctx->pc so that it's immediately available

       in the disassembly dump.  */

    ctx->pc = pc_end;

    return 1;

}

static int decode_gusa(DisasContext *ctx, CPUSH4State *env, int *pmax_insns)

{

    uint16_t insns[5];

    int ld_adr, ld_dst, ld_mop;

    int op_dst, op_src, op_opc;

    int mv_src, mt_dst, st_src, st_mop;

    TCGv op_arg;



    uint32_t pc = ctx->pc;

    uint32_t pc_end = ctx->tb->cs_base;

    int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8);

    int max_insns = (pc_end - pc) / 2;

    int i;



    if (pc != pc_end + backup || max_insns < 2) {

        



        ctx->envflags &= ~GUSA_MASK;

        return 0;

    }



    if (ctx->tbflags & GUSA_EXCLUSIVE) {

        





        *pmax_insns = max_insns;

        return 0;

    }



    



    if (max_insns > ARRAY_SIZE(insns)) {

        goto fail;

    }



    

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

        insns[i] = cpu_lduw_code(env, pc + i * 2);

    }



    ld_adr = ld_dst = ld_mop = -1;

    mv_src = -1;

    op_dst = op_src = op_opc = -1;

    mt_dst = -1;

    st_src = st_mop = -1;

    TCGV_UNUSED(op_arg);

    i = 0;



#define NEXT_INSN \

    do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0)



    





    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x6000: 

        ld_mop = MO_SB;

        break;

    case 0x6001: 

        ld_mop = MO_TESW;

        break;

    case 0x6002: 

        ld_mop = MO_TESL;

        break;

    default:

        goto fail;

    }

    ld_adr = B7_4;

    ld_dst = B11_8;

    if (ld_adr == ld_dst) {

        goto fail;

    }

    

    op_dst = ld_dst;



    





    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x6003: 

        





        op_dst = B11_8;

        mv_src = B7_4;

        if (op_dst == ld_dst) {

            

            goto fail;

        }

        if (mv_src != ld_dst) {

            

            op_src = ld_dst;

        }

        break;



    default:

        

        --i;

    }



    





    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x300c: 

        op_opc = INDEX_op_add_i32;

        goto do_reg_op;

    case 0x2009: 

        op_opc = INDEX_op_and_i32;

        goto do_reg_op;

    case 0x200a: 

        op_opc = INDEX_op_xor_i32;

        goto do_reg_op;

    case 0x200b: 

        op_opc = INDEX_op_or_i32;

    do_reg_op:

        



        if (op_dst != B11_8) {

            goto fail;

        }

        if (op_src < 0) {

            

            op_src = B7_4;

        } else if (op_src == B7_4) {

            







            op_src = mv_src;

        } else {

            goto fail;

        }

        op_arg = REG(op_src);

        break;



    case 0x6007: 

        if (ld_dst != B7_4 || mv_src >= 0) {

            goto fail;

        }

        op_dst = B11_8;

        op_opc = INDEX_op_xor_i32;

        op_arg = tcg_const_i32(-1);

        break;



    case 0x7000 ... 0x700f: 

        if (op_dst != B11_8 || mv_src >= 0) {

            goto fail;

        }

        op_opc = INDEX_op_add_i32;

        op_arg = tcg_const_i32(B7_0s);

        break;



    case 0x3000: 

        





        if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) {

            goto fail;

        }

        op_opc = INDEX_op_setcond_i32;  

        op_src = (ld_dst == B11_8 ? B7_4 : B11_8);

        op_arg = REG(op_src);



        NEXT_INSN;

        switch (ctx->opcode & 0xff00) {

        case 0x8b00: 

        case 0x8f00: 

            if (pc + (i + 1 + B7_0s) * 2 != pc_end) {

                goto fail;

            }

            if ((ctx->opcode & 0xff00) == 0x8b00) { 

                break;

            }

            





            NEXT_INSN;

            if ((ctx->opcode & 0xf0ff) == 0x0029) { 

                mt_dst = B11_8;

            } else {

                goto fail;

            }

            break;



        default:

            goto fail;

        }

        break;



    case 0x2008: 

        

        if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) {

            goto fail;

        }

        op_opc = INDEX_op_setcond_i32;

        op_arg = tcg_const_i32(0);



        NEXT_INSN;

        if ((ctx->opcode & 0xff00) != 0x8900 

            || pc + (i + 1 + B7_0s) * 2 != pc_end) {

            goto fail;

        }

        break;



    default:

        

        --i;

    }



    





    

    if (i != max_insns - 1) {

        goto fail;

    }

    NEXT_INSN;

    switch (ctx->opcode & 0xf00f) {

    case 0x2000: 

        st_mop = MO_UB;

        break;

    case 0x2001: 

        st_mop = MO_UW;

        break;

    case 0x2002: 

        st_mop = MO_UL;

        break;

    default:

        goto fail;

    }

    

    if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) {

        goto fail;

    }

    st_src = B7_4;



#undef NEXT_INSN



    





    tcg_gen_insn_start(pc, ctx->envflags);

    switch (op_opc) {

    case -1:

        

        if (st_src == ld_dst || mv_src >= 0) {

            goto fail;

        }

        tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src),

                                ctx->memidx, ld_mop);

        break;



    case INDEX_op_add_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst && st_mop == MO_UL) {

            tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

            if (op_dst != ld_dst) {

                



                tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg);

            }

        }

        break;



    case INDEX_op_and_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst) {

            tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

            tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg);

        }

        break;



    case INDEX_op_or_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst) {

            tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr),

                                        op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr),

                                        op_arg, ctx->memidx, ld_mop);

            tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg);

        }

        break;



    case INDEX_op_xor_i32:

        if (op_dst != st_src) {

            goto fail;

        }

        if (op_dst == ld_dst) {

            tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

        } else {

            tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr),

                                         op_arg, ctx->memidx, ld_mop);

            tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg);

        }

        break;



    case INDEX_op_setcond_i32:

        if (st_src == ld_dst) {

            goto fail;

        }

        tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg,

                                   REG(st_src), ctx->memidx, ld_mop);

        tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg);

        if (mt_dst >= 0) {

            tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t);

        }

        break;



    default:

        g_assert_not_reached();

    }



    

    if (op_src < 0) {

        tcg_temp_free_i32(op_arg);

    }



    

    ctx->envflags &= ~GUSA_MASK;

    ctx->pc = pc_end;

    return max_insns;



 fail:

    qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",

                  pc, pc_end);



    



    tcg_gen_insn_start(pc, ctx->envflags);

    ctx->envflags |= GUSA_EXCLUSIVE;

    gen_save_cpu_state(ctx, false);

    gen_helper_exclusive(cpu_env);

    ctx->bstate = BS_EXCP;



    







    ctx->pc = pc_end;

    return 1;

}

    if (op_src < 0) {
static int FUNC_0(DisasContext *VAR_0, CPUSH4State *VAR_1, int *VAR_2)

{

    uint16_t insns[5];

    int VAR_3, VAR_4, VAR_5;

    int VAR_6, VAR_7, VAR_8;

    int VAR_9, VAR_10, VAR_11, VAR_12;

    TCGv op_arg;



    uint32_t pc = VAR_0->pc;

    uint32_t pc_end = VAR_0->tb->cs_base;

    int VAR_13 = sextract32(VAR_0->tbflags, GUSA_SHIFT, 8);

    int VAR_14 = (pc_end - pc) / 2;

    int VAR_15;



    if (pc != pc_end + VAR_13 || VAR_14 < 2) {

        



        VAR_0->envflags &= ~GUSA_MASK;

        return 0;

    }



    if (VAR_0->tbflags & GUSA_EXCLUSIVE) {

        





        *VAR_2 = VAR_14;

        return 0;

    }



    



    if (VAR_14 > ARRAY_SIZE(insns)) {

        goto fail;

    }



    

    for (VAR_15 = 0; VAR_15 < VAR_14; ++VAR_15) {

        insns[VAR_15] = cpu_lduw_code(VAR_1, pc + VAR_15 * 2);

    }



    VAR_3 = VAR_4 = VAR_5 = -1;

    VAR_9 = -1;

    VAR_6 = VAR_7 = VAR_8 = -1;

    VAR_10 = -1;

    VAR_11 = VAR_12 = -1;

    TCGV_UNUSED(op_arg);

    VAR_15 = 0;



#define NEXT_INSN \

    do { if (VAR_15 >= VAR_14) goto fail; VAR_0->opcode = insns[VAR_15++]; } while (0)



    





    NEXT_INSN;

    switch (VAR_0->opcode & 0xf00f) {

    case 0x6000: 

        VAR_5 = MO_SB;

        break;

    case 0x6001: 

        VAR_5 = MO_TESW;

        break;

    case 0x6002: 

        VAR_5 = MO_TESL;

        break;

    default:

        goto fail;

    }

    VAR_3 = B7_4;

    VAR_4 = B11_8;

    if (VAR_3 == VAR_4) {

        goto fail;

    }

    

    VAR_6 = VAR_4;



    





    NEXT_INSN;

    switch (VAR_0->opcode & 0xf00f) {

    case 0x6003: 

        





        VAR_6 = B11_8;

        VAR_9 = B7_4;

        if (VAR_6 == VAR_4) {

            

            goto fail;

        }

        if (VAR_9 != VAR_4) {

            

            VAR_7 = VAR_4;

        }

        break;



    default:

        

        --VAR_15;

    }



    





    NEXT_INSN;

    switch (VAR_0->opcode & 0xf00f) {

    case 0x300c: 

        VAR_8 = INDEX_op_add_i32;

        goto do_reg_op;

    case 0x2009: 

        VAR_8 = INDEX_op_and_i32;

        goto do_reg_op;

    case 0x200a: 

        VAR_8 = INDEX_op_xor_i32;

        goto do_reg_op;

    case 0x200b: 

        VAR_8 = INDEX_op_or_i32;

    do_reg_op:

        



        if (VAR_6 != B11_8) {

            goto fail;

        }

        if (VAR_7 < 0) {

            

            VAR_7 = B7_4;

        } else if (VAR_7 == B7_4) {

            







            VAR_7 = VAR_9;

        } else {

            goto fail;

        }

        op_arg = REG(VAR_7);

        break;



    case 0x6007: 

        if (VAR_4 != B7_4 || VAR_9 >= 0) {

            goto fail;

        }

        VAR_6 = B11_8;

        VAR_8 = INDEX_op_xor_i32;

        op_arg = tcg_const_i32(-1);

        break;



    case 0x7000 ... 0x700f: 

        if (VAR_6 != B11_8 || VAR_9 >= 0) {

            goto fail;

        }

        VAR_8 = INDEX_op_add_i32;

        op_arg = tcg_const_i32(B7_0s);

        break;



    case 0x3000: 

        





        if ((VAR_4 == B11_8) + (VAR_4 == B7_4) != 1 || VAR_9 >= 0) {

            goto fail;

        }

        VAR_8 = INDEX_op_setcond_i32;  

        VAR_7 = (VAR_4 == B11_8 ? B7_4 : B11_8);

        op_arg = REG(VAR_7);



        NEXT_INSN;

        switch (VAR_0->opcode & 0xff00) {

        case 0x8b00: 

        case 0x8f00: 

            if (pc + (VAR_15 + 1 + B7_0s) * 2 != pc_end) {

                goto fail;

            }

            if ((VAR_0->opcode & 0xff00) == 0x8b00) { 

                break;

            }

            





            NEXT_INSN;

            if ((VAR_0->opcode & 0xf0ff) == 0x0029) { 

                VAR_10 = B11_8;

            } else {

                goto fail;

            }

            break;



        default:

            goto fail;

        }

        break;



    case 0x2008: 

        

        if (VAR_4 != B11_8 || VAR_4 != B7_4 || VAR_9 >= 0) {

            goto fail;

        }

        VAR_8 = INDEX_op_setcond_i32;

        op_arg = tcg_const_i32(0);



        NEXT_INSN;

        if ((VAR_0->opcode & 0xff00) != 0x8900 

            || pc + (VAR_15 + 1 + B7_0s) * 2 != pc_end) {

            goto fail;

        }

        break;



    default:

        

        --VAR_15;

    }



    





    

    if (VAR_15 != VAR_14 - 1) {

        goto fail;

    }

    NEXT_INSN;

    switch (VAR_0->opcode & 0xf00f) {

    case 0x2000: 

        VAR_12 = MO_UB;

        break;

    case 0x2001: 

        VAR_12 = MO_UW;

        break;

    case 0x2002: 

        VAR_12 = MO_UL;

        break;

    default:

        goto fail;

    }

    

    if (VAR_3 != B11_8 || VAR_12 != (VAR_5 & MO_SIZE)) {

        goto fail;

    }

    VAR_11 = B7_4;



#undef NEXT_INSN



    





    tcg_gen_insn_start(pc, VAR_0->envflags);

    switch (VAR_8) {

    case -1:

        

        if (VAR_11 == VAR_4 || VAR_9 >= 0) {

            goto fail;

        }

        tcg_gen_atomic_xchg_i32(REG(VAR_4), REG(VAR_3), REG(VAR_11),

                                VAR_0->memidx, VAR_5);

        break;



    case INDEX_op_add_i32:

        if (VAR_6 != VAR_11) {

            goto fail;

        }

        if (VAR_6 == VAR_4 && VAR_12 == MO_UL) {

            tcg_gen_atomic_add_fetch_i32(REG(VAR_4), REG(VAR_3),

                                         op_arg, VAR_0->memidx, VAR_5);

        } else {

            tcg_gen_atomic_fetch_add_i32(REG(VAR_4), REG(VAR_3),

                                         op_arg, VAR_0->memidx, VAR_5);

            if (VAR_6 != VAR_4) {

                



                tcg_gen_add_i32(REG(VAR_6), REG(VAR_4), op_arg);

            }

        }

        break;



    case INDEX_op_and_i32:

        if (VAR_6 != VAR_11) {

            goto fail;

        }

        if (VAR_6 == VAR_4) {

            tcg_gen_atomic_and_fetch_i32(REG(VAR_4), REG(VAR_3),

                                         op_arg, VAR_0->memidx, VAR_5);

        } else {

            tcg_gen_atomic_fetch_and_i32(REG(VAR_4), REG(VAR_3),

                                         op_arg, VAR_0->memidx, VAR_5);

            tcg_gen_and_i32(REG(VAR_6), REG(VAR_4), op_arg);

        }

        break;



    case INDEX_op_or_i32:

        if (VAR_6 != VAR_11) {

            goto fail;

        }

        if (VAR_6 == VAR_4) {

            tcg_gen_atomic_or_fetch_i32(REG(VAR_4), REG(VAR_3),

                                        op_arg, VAR_0->memidx, VAR_5);

        } else {

            tcg_gen_atomic_fetch_or_i32(REG(VAR_4), REG(VAR_3),

                                        op_arg, VAR_0->memidx, VAR_5);

            tcg_gen_or_i32(REG(VAR_6), REG(VAR_4), op_arg);

        }

        break;



    case INDEX_op_xor_i32:

        if (VAR_6 != VAR_11) {

            goto fail;

        }

        if (VAR_6 == VAR_4) {

            tcg_gen_atomic_xor_fetch_i32(REG(VAR_4), REG(VAR_3),

                                         op_arg, VAR_0->memidx, VAR_5);

        } else {

            tcg_gen_atomic_fetch_xor_i32(REG(VAR_4), REG(VAR_3),

                                         op_arg, VAR_0->memidx, VAR_5);

            tcg_gen_xor_i32(REG(VAR_6), REG(VAR_4), op_arg);

        }

        break;



    case INDEX_op_setcond_i32:

        if (VAR_11 == VAR_4) {

            goto fail;

        }

        tcg_gen_atomic_cmpxchg_i32(REG(VAR_4), REG(VAR_3), op_arg,

                                   REG(VAR_11), VAR_0->memidx, VAR_5);

        tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(VAR_4), op_arg);

        if (VAR_10 >= 0) {

            tcg_gen_mov_i32(REG(VAR_10), cpu_sr_t);

        }

        break;



    default:

        g_assert_not_reached();

    }



    

    if (VAR_7 < 0) {

        tcg_temp_free_i32(op_arg);

    }



    

    VAR_0->envflags &= ~GUSA_MASK;

    VAR_0->pc = pc_end;

    return VAR_14;



 fail:

    qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",

                  pc, pc_end);



    



    tcg_gen_insn_start(pc, VAR_0->envflags);

    VAR_0->envflags |= GUSA_EXCLUSIVE;

    gen_save_cpu_state(VAR_0, false);

    gen_helper_exclusive(cpu_env);

    VAR_0->bstate = BS_EXCP;



    







    VAR_0->pc = pc_end;

    return 1;

}

static int FUNC_0(DisasContext *VAR_0, CPUSH4State *VAR_1, int *VAR_2)
{ uint16_t insns[5]; int VAR_3, VAR_4, VAR_5; int VAR_6, VAR_7, VAR_8; int VAR_9, VAR_10, VAR_11, VAR_12; TCGv op_arg; uint32_t pc = VAR_0->pc; uint32_t pc_end = VAR_0->tb->cs_base; int VAR_13 = sextract32(VAR_0->tbflags, GUSA_SHIFT, 8); int VAR_14 = (pc_end - pc) / 2; int VAR_15; if (pc != pc_end + VAR_13 || VAR_14 < 2) { VAR_0->envflags &= ~GUSA_MASK; return 0; } if (VAR_0->tbflags & GUSA_EXCLUSIVE) { *VAR_2 = VAR_14; return 0; } if (VAR_14 > ARRAY_SIZE(insns)) { goto fail; } for (VAR_15 = 0; VAR_15 < VAR_14; ++VAR_15) { insns[VAR_15] = cpu_lduw_code(VAR_1, pc + VAR_15 * 2); } VAR_3 = VAR_4 = VAR_5 = -1; VAR_9 = -1; VAR_6 = VAR_7 = VAR_8 = -1; VAR_10 = -1; VAR_11 = VAR_12 = -1; TCGV_UNUSED(op_arg); VAR_15 = 0; #define NEXT_INSN \
do { if (VAR_15 >= VAR_14) goto fail; VAR_0->opcode = insns[VAR_15++]; } while (0) NEXT_INSN; switch (VAR_0->opcode & 0xf00f) { case 0x6000:
VAR_5 = MO_SB; break; case 0x6001:
VAR_5 = MO_TESW; break; case 0x6002:
VAR_5 = MO_TESL; break; default:
goto fail; } VAR_3 = B7_4; VAR_4 = B11_8; if (VAR_3 == VAR_4) { goto fail; } VAR_6 = VAR_4; NEXT_INSN; switch (VAR_0->opcode & 0xf00f) { case 0x6003:
VAR_6 = B11_8; VAR_9 = B7_4; if (VAR_6 == VAR_4) { goto fail; } if (VAR_9 != VAR_4) { VAR_7 = VAR_4; } break; default:
--VAR_15; } NEXT_INSN; switch (VAR_0->opcode & 0xf00f) { case 0x300c:
VAR_8 = INDEX_op_add_i32; goto do_reg_op; case 0x2009:
VAR_8 = INDEX_op_and_i32; goto do_reg_op; case 0x200a:
VAR_8 = INDEX_op_xor_i32; goto do_reg_op; case 0x200b:
VAR_8 = INDEX_op_or_i32; do_reg_op:
if (VAR_6 != B11_8) { goto fail; } if (VAR_7 < 0) { VAR_7 = B7_4; } else if (VAR_7 == B7_4) { VAR_7 = VAR_9; } else { goto fail; } op_arg = REG(VAR_7); break; case 0x6007:
if (VAR_4 != B7_4 || VAR_9 >= 0) { goto fail; } VAR_6 = B11_8; VAR_8 = INDEX_op_xor_i32; op_arg = tcg_const_i32(-1); break; case 0x7000 ... 0x700f:
if (VAR_6 != B11_8 || VAR_9 >= 0) { goto fail; } VAR_8 = INDEX_op_add_i32; op_arg = tcg_const_i32(B7_0s); break; case 0x3000:
if ((VAR_4 == B11_8) + (VAR_4 == B7_4) != 1 || VAR_9 >= 0) { goto fail; } VAR_8 = INDEX_op_setcond_i32; VAR_7 = (VAR_4 == B11_8 ? B7_4 : B11_8); op_arg = REG(VAR_7); NEXT_INSN; switch (VAR_0->opcode & 0xff00) { case 0x8b00:
case 0x8f00:
if (pc + (VAR_15 + 1 + B7_0s) * 2 != pc_end) { goto fail; } if ((VAR_0->opcode & 0xff00) == 0x8b00) { break; } NEXT_INSN; if ((VAR_0->opcode & 0xf0ff) == 0x0029) { VAR_10 = B11_8; } else { goto fail; } break; default:
goto fail; } break; case 0x2008:
if (VAR_4 != B11_8 || VAR_4 != B7_4 || VAR_9 >= 0) { goto fail; } VAR_8 = INDEX_op_setcond_i32; op_arg = tcg_const_i32(0); NEXT_INSN; if ((VAR_0->opcode & 0xff00) != 0x8900
|| pc + (VAR_15 + 1 + B7_0s) * 2 != pc_end) { goto fail; } break; default:
--VAR_15; } if (VAR_15 != VAR_14 - 1) { goto fail; } NEXT_INSN; switch (VAR_0->opcode & 0xf00f) { case 0x2000:
VAR_12 = MO_UB; break; case 0x2001:
VAR_12 = MO_UW; break; case 0x2002:
VAR_12 = MO_UL; break; default:
goto fail; } if (VAR_3 != B11_8 || VAR_12 != (VAR_5 & MO_SIZE)) { goto fail; } VAR_11 = B7_4; #undef NEXT_INSN
tcg_gen_insn_start(pc, VAR_0->envflags); switch (VAR_8) { case -1:
if (VAR_11 == VAR_4 || VAR_9 >= 0) { goto fail; } tcg_gen_atomic_xchg_i32(REG(VAR_4), REG(VAR_3), REG(VAR_11),
VAR_0->memidx, VAR_5); break; case INDEX_op_add_i32:
if (VAR_6 != VAR_11) { goto fail; } if (VAR_6 == VAR_4 && VAR_12 == MO_UL) { tcg_gen_atomic_add_fetch_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); } else { tcg_gen_atomic_fetch_add_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); if (VAR_6 != VAR_4) { tcg_gen_add_i32(REG(VAR_6), REG(VAR_4), op_arg); } } break; case INDEX_op_and_i32:
if (VAR_6 != VAR_11) { goto fail; } if (VAR_6 == VAR_4) { tcg_gen_atomic_and_fetch_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); } else { tcg_gen_atomic_fetch_and_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); tcg_gen_and_i32(REG(VAR_6), REG(VAR_4), op_arg); } break; case INDEX_op_or_i32:
if (VAR_6 != VAR_11) { goto fail; } if (VAR_6 == VAR_4) { tcg_gen_atomic_or_fetch_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); } else { tcg_gen_atomic_fetch_or_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); tcg_gen_or_i32(REG(VAR_6), REG(VAR_4), op_arg); } break; case INDEX_op_xor_i32:
if (VAR_6 != VAR_11) { goto fail; } if (VAR_6 == VAR_4) { tcg_gen_atomic_xor_fetch_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); } else { tcg_gen_atomic_fetch_xor_i32(REG(VAR_4), REG(VAR_3),
op_arg, VAR_0->memidx, VAR_5); tcg_gen_xor_i32(REG(VAR_6), REG(VAR_4), op_arg); } break; case INDEX_op_setcond_i32:
if (VAR_11 == VAR_4) { goto fail; } tcg_gen_atomic_cmpxchg_i32(REG(VAR_4), REG(VAR_3), op_arg,
REG(VAR_11), VAR_0->memidx, VAR_5); tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(VAR_4), op_arg); if (VAR_10 >= 0) { tcg_gen_mov_i32(REG(VAR_10), cpu_sr_t); } break; default:
g_assert_not_reached(); } if (VAR_7 < 0) { tcg_temp_free_i32(op_arg); } VAR_0->envflags &= ~GUSA_MASK; VAR_0->pc = pc_end; return VAR_14; fail:
qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n",
pc, pc_end); tcg_gen_insn_start(pc, VAR_0->envflags); VAR_0->envflags |= GUSA_EXCLUSIVE; gen_save_cpu_state(VAR_0, false); gen_helper_exclusive(cpu_env); VAR_0->bstate = BS_EXCP; VAR_0->pc = pc_end; return 1; }