static void disas_xtensa_insn(DisasContext *dc)

{

#define HAS_OPTION_BITS(opt) do { \

        if (!option_bits_enabled(dc, opt)) { \

            qemu_log("Option is not enabled %s:%d\n", \

                    __FILE__, __LINE__); \

            goto invalid_opcode; \

        } \

    } while (0)

#define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt))

#define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)

#define RESERVED() do { \

        qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \

                dc->pc, b0, b1, b2, __FILE__, __LINE__); \

        goto invalid_opcode; \

    } while (0)

#ifdef TARGET_WORDS_BIGENDIAN

#define OP0 (((b0) & 0xf0) >> 4)

#define OP1 (((b2) & 0xf0) >> 4)

#define OP2 ((b2) & 0xf)

#define RRR_R ((b1) & 0xf)

#define RRR_S (((b1) & 0xf0) >> 4)

#define RRR_T ((b0) & 0xf)

#else

#define OP0 (((b0) & 0xf))

#define OP1 (((b2) & 0xf))

#define OP2 (((b2) & 0xf0) >> 4)

#define RRR_R (((b1) & 0xf0) >> 4)

#define RRR_S (((b1) & 0xf))

#define RRR_T (((b0) & 0xf0) >> 4)

#endif

#define RRR_X ((RRR_R & 0x4) >> 2)

#define RRR_Y ((RRR_T & 0x4) >> 2)

#define RRR_W (RRR_R & 0x3)

#define RRRN_R RRR_R

#define RRRN_S RRR_S

#define RRRN_T RRR_T

#define RRI8_R RRR_R

#define RRI8_S RRR_S

#define RRI8_T RRR_T

#define RRI8_IMM8 (b2)

#define RRI8_IMM8_SE ((((b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8)

#ifdef TARGET_WORDS_BIGENDIAN

#define RI16_IMM16 (((b1) << 8) | (b2))

#else

#define RI16_IMM16 (((b2) << 8) | (b1))

#endif

#ifdef TARGET_WORDS_BIGENDIAN

#define CALL_N (((b0) & 0xc) >> 2)

#define CALL_OFFSET ((((b0) & 0x3) << 16) | ((b1) << 8) | (b2))

#else

#define CALL_N (((b0) & 0x30) >> 4)

#define CALL_OFFSET ((((b0) & 0xc0) >> 6) | ((b1) << 2) | ((b2) << 10))

#endif

#define CALL_OFFSET_SE \

    (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET)

#define CALLX_N CALL_N

#ifdef TARGET_WORDS_BIGENDIAN

#define CALLX_M ((b0) & 0x3)

#else

#define CALLX_M (((b0) & 0xc0) >> 6)

#endif

#define CALLX_S RRR_S

#define BRI12_M CALLX_M

#define BRI12_S RRR_S

#ifdef TARGET_WORDS_BIGENDIAN

#define BRI12_IMM12 ((((b1) & 0xf) << 8) | (b2))

#else

#define BRI12_IMM12 ((((b1) & 0xf0) >> 4) | ((b2) << 4))

#endif

#define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12)

#define BRI8_M BRI12_M

#define BRI8_R RRI8_R

#define BRI8_S RRI8_S

#define BRI8_IMM8 RRI8_IMM8

#define BRI8_IMM8_SE RRI8_IMM8_SE

#define RSR_SR (b1)

    uint8_t b0 = ldub_code(dc->pc);

    uint8_t b1 = ldub_code(dc->pc + 1);

    uint8_t b2 = 0;

    static const uint32_t B4CONST[] = {

        0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256

    };

    static const uint32_t B4CONSTU[] = {

        32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256

    };

    if (OP0 >= 8) {

        dc->next_pc = dc->pc + 2;

        HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);

    } else {

        dc->next_pc = dc->pc + 3;

        b2 = ldub_code(dc->pc + 2);

    }

    switch (OP0) {

    case 0: /*QRST*/

        switch (OP1) {

        case 0: /*RST0*/

            switch (OP2) {

            case 0: /*ST0*/

                if ((RRR_R & 0xc) == 0x8) {

                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);

                }

                switch (RRR_R) {

                case 0: /*SNM0*/

                    switch (CALLX_M) {

                    case 0: /*ILL*/

                        gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);

                        break;

                    case 1: /*reserved*/

                        RESERVED();

                        break;

                    case 2: /*JR*/

                        switch (CALLX_N) {

                        case 0: /*RET*/

                        case 2: /*JX*/

                            gen_window_check1(dc, CALLX_S);

                            gen_jump(dc, cpu_R[CALLX_S]);

                            break;

                        case 1: /*RETWw*/

                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                            {

                                TCGv_i32 tmp = tcg_const_i32(dc->pc);

                                gen_advance_ccount(dc);

                                gen_helper_retw(tmp, tmp);

                                gen_jump(dc, tmp);

                                tcg_temp_free(tmp);

                            }

                            break;

                        case 3: /*reserved*/

                            RESERVED();

                            break;

                        }

                        break;

                    case 3: /*CALLX*/

                        gen_window_check2(dc, CALLX_S, CALLX_N << 2);

                        switch (CALLX_N) {

                        case 0: /*CALLX0*/

                            {

                                TCGv_i32 tmp = tcg_temp_new_i32();

                                tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);

                                tcg_gen_movi_i32(cpu_R[0], dc->next_pc);

                                gen_jump(dc, tmp);

                                tcg_temp_free(tmp);

                            }

                            break;

                        case 1: /*CALLX4w*/

                        case 2: /*CALLX8w*/

                        case 3: /*CALLX12w*/

                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                            {

                                TCGv_i32 tmp = tcg_temp_new_i32();

                                tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);

                                gen_callw(dc, CALLX_N, tmp);

                                tcg_temp_free(tmp);

                            }

                            break;

                        }

                        break;

                    }

                    break;

                case 1: /*MOVSPw*/

                    HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                    gen_window_check2(dc, RRR_T, RRR_S);

                    {

                        TCGv_i32 pc = tcg_const_i32(dc->pc);

                        gen_advance_ccount(dc);

                        gen_helper_movsp(pc);

                        tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);

                        tcg_temp_free(pc);

                    }

                    break;

                case 2: /*SYNC*/

                    switch (RRR_T) {

                    case 0: /*ISYNC*/

                        break;

                    case 1: /*RSYNC*/

                        break;

                    case 2: /*ESYNC*/

                        break;

                    case 3: /*DSYNC*/

                        break;

                    case 8: /*EXCW*/

                        HAS_OPTION(XTENSA_OPTION_EXCEPTION);

                        break;

                    case 12: /*MEMW*/

                        break;

                    case 13: /*EXTW*/

                        break;

                    case 15: /*NOP*/

                        break;

                    default: /*reserved*/

                        RESERVED();

                        break;

                    }

                    break;

                case 3: /*RFEIx*/

                    switch (RRR_T) {

                    case 0: /*RFETx*/

                        HAS_OPTION(XTENSA_OPTION_EXCEPTION);

                        switch (RRR_S) {

                        case 0: /*RFEx*/

                            gen_check_privilege(dc);

                            tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);

                            gen_helper_check_interrupts(cpu_env);

                            gen_jump(dc, cpu_SR[EPC1]);

                            break;

                        case 1: /*RFUEx*/

                            RESERVED();

                            break;

                        case 2: /*RFDEx*/

                            gen_check_privilege(dc);

                            gen_jump(dc, cpu_SR[

                                    dc->config->ndepc ? DEPC : EPC1]);

                            break;

                        case 4: /*RFWOw*/

                        case 5: /*RFWUw*/

                            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                            gen_check_privilege(dc);

                            {

                                TCGv_i32 tmp = tcg_const_i32(1);

                                tcg_gen_andi_i32(

                                        cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);

                                tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);

                                if (RRR_S == 4) {

                                    tcg_gen_andc_i32(cpu_SR[WINDOW_START],

                                            cpu_SR[WINDOW_START], tmp);

                                } else {

                                    tcg_gen_or_i32(cpu_SR[WINDOW_START],

                                            cpu_SR[WINDOW_START], tmp);

                                }

                                gen_helper_restore_owb();

                                gen_helper_check_interrupts(cpu_env);

                                gen_jump(dc, cpu_SR[EPC1]);

                                tcg_temp_free(tmp);

                            }

                            break;

                        default: /*reserved*/

                            RESERVED();

                            break;

                        }

                        break;

                    case 1: /*RFIx*/

                        HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);

                        if (RRR_S >= 2 && RRR_S <= dc->config->nlevel) {

                            gen_check_privilege(dc);

                            tcg_gen_mov_i32(cpu_SR[PS],

                                    cpu_SR[EPS2 + RRR_S - 2]);

                            gen_helper_check_interrupts(cpu_env);

                            gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);

                        } else {

                            qemu_log("RFI %d is illegal\n", RRR_S);

                            gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);

                        }

                        break;

                    case 2: /*RFME*/

                        TBD();

                        break;

                    default: /*reserved*/

                        RESERVED();

                        break;

                    }

                    break;

                case 4: /*BREAKx*/

                    HAS_OPTION(XTENSA_OPTION_DEBUG);

                    if (dc->debug) {

                        gen_debug_exception(dc, DEBUGCAUSE_BI);

                    }

                    break;

                case 5: /*SYSCALLx*/

                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);

                    switch (RRR_S) {

                    case 0: /*SYSCALLx*/

                        gen_exception_cause(dc, SYSCALL_CAUSE);

                        break;

                    case 1: /*SIMCALL*/

                        if (semihosting_enabled) {

                            gen_check_privilege(dc);

                            gen_helper_simcall(cpu_env);

                        } else {

                            qemu_log("SIMCALL but semihosting is disabled\n");

                            gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);

                        }

                        break;

                    default:

                        RESERVED();

                        break;

                    }

                    break;

                case 6: /*RSILx*/

                    HAS_OPTION(XTENSA_OPTION_INTERRUPT);

                    gen_check_privilege(dc);

                    gen_window_check1(dc, RRR_T);

                    tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);

                    tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);

                    tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);

                    gen_helper_check_interrupts(cpu_env);

                    gen_jumpi_check_loop_end(dc, 0);

                    break;

                case 7: /*WAITIx*/

                    HAS_OPTION(XTENSA_OPTION_INTERRUPT);

                    gen_check_privilege(dc);

                    gen_waiti(dc, RRR_S);

                    break;

                case 8: /*ANY4p*/

                case 9: /*ALL4p*/

                case 10: /*ANY8p*/

                case 11: /*ALL8p*/

                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);

                    {

                        const unsigned shift = (RRR_R & 2) ? 8 : 4;

                        TCGv_i32 mask = tcg_const_i32(

                                ((1 << shift) - 1) << RRR_S);

                        TCGv_i32 tmp = tcg_temp_new_i32();

                        tcg_gen_and_i32(tmp, cpu_SR[BR], mask);

                        if (RRR_R & 1) { /*ALL*/

                            tcg_gen_addi_i32(tmp, tmp, 1 << RRR_S);

                        } else { /*ANY*/

                            tcg_gen_add_i32(tmp, tmp, mask);

                        }

                        tcg_gen_shri_i32(tmp, tmp, RRR_S + shift);

                        tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],

                                tmp, RRR_T, 1);

                        tcg_temp_free(mask);

                        tcg_temp_free(tmp);

                    }

                    break;

                default: /*reserved*/

                    RESERVED();

                    break;

                }

                break;

            case 1: /*AND*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 2: /*OR*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 3: /*XOR*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 4: /*ST1*/

                switch (RRR_R) {

                case 0: /*SSR*/

                    gen_window_check1(dc, RRR_S);

                    gen_right_shift_sar(dc, cpu_R[RRR_S]);

                    break;

                case 1: /*SSL*/

                    gen_window_check1(dc, RRR_S);

                    gen_left_shift_sar(dc, cpu_R[RRR_S]);

                    break;

                case 2: /*SSA8L*/

                    gen_window_check1(dc, RRR_S);

                    {

                        TCGv_i32 tmp = tcg_temp_new_i32();

                        tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);

                        gen_right_shift_sar(dc, tmp);

                        tcg_temp_free(tmp);

                    }

                    break;

                case 3: /*SSA8B*/

                    gen_window_check1(dc, RRR_S);

                    {

                        TCGv_i32 tmp = tcg_temp_new_i32();

                        tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);

                        gen_left_shift_sar(dc, tmp);

                        tcg_temp_free(tmp);

                    }

                    break;

                case 4: /*SSAI*/

                    {

                        TCGv_i32 tmp = tcg_const_i32(

                                RRR_S | ((RRR_T & 1) << 4));

                        gen_right_shift_sar(dc, tmp);

                        tcg_temp_free(tmp);

                    }

                    break;

                case 6: /*RER*/

                    TBD();

                    break;

                case 7: /*WER*/

                    TBD();

                    break;

                case 8: /*ROTWw*/

                    HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                    gen_check_privilege(dc);

                    {

                        TCGv_i32 tmp = tcg_const_i32(

                                RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));

                        gen_helper_rotw(tmp);

                        tcg_temp_free(tmp);

                        reset_used_window(dc);

                    }

                    break;

                case 14: /*NSAu*/

                    HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);

                    gen_window_check2(dc, RRR_S, RRR_T);

                    gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);

                    break;

                case 15: /*NSAUu*/

                    HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);

                    gen_window_check2(dc, RRR_S, RRR_T);

                    gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);

                    break;

                default: /*reserved*/

                    RESERVED();

                    break;

                }

                break;

            case 5: /*TLB*/

                HAS_OPTION_BITS(

                        XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |

                        XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |

                        XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION));

                gen_check_privilege(dc);

                gen_window_check2(dc, RRR_S, RRR_T);

                {

                    TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0);

                    switch (RRR_R & 7) {

                    case 3: /*RITLB0*/ /*RDTLB0*/

                        gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);

                        break;

                    case 4: /*IITLB*/ /*IDTLB*/

                        gen_helper_itlb(cpu_R[RRR_S], dtlb);

                        /* This could change memory mapping, so exit tb */

                        gen_jumpi_check_loop_end(dc, -1);

                        break;

                    case 5: /*PITLB*/ /*PDTLB*/

                        tcg_gen_movi_i32(cpu_pc, dc->pc);

                        gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);

                        break;

                    case 6: /*WITLB*/ /*WDTLB*/

                        gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);

                        /* This could change memory mapping, so exit tb */

                        gen_jumpi_check_loop_end(dc, -1);

                        break;

                    case 7: /*RITLB1*/ /*RDTLB1*/

                        gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);

                        break;

                    default:

                        tcg_temp_free(dtlb);

                        RESERVED();

                        break;

                    }

                    tcg_temp_free(dtlb);

                }

                break;

            case 6: /*RT0*/

                gen_window_check2(dc, RRR_R, RRR_T);

                switch (RRR_S) {

                case 0: /*NEG*/

                    tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);

                    break;

                case 1: /*ABS*/

                    {

                        int label = gen_new_label();

                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);

                        tcg_gen_brcondi_i32(

                                TCG_COND_GE, cpu_R[RRR_R], 0, label);

                        tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);

                        gen_set_label(label);

                    }

                    break;

                default: /*reserved*/

                    RESERVED();

                    break;

                }

                break;

            case 7: /*reserved*/

                RESERVED();

                break;

            case 8: /*ADD*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 9: /*ADD**/

            case 10:

            case 11:

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);

                    tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);

                    tcg_temp_free(tmp);

                }

                break;

            case 12: /*SUB*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 13: /*SUB**/

            case 14:

            case 15:

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);

                    tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);

                    tcg_temp_free(tmp);

                }

                break;

            }

            break;

        case 1: /*RST1*/

            switch (OP2) {

            case 0: /*SLLI*/

            case 1:

                gen_window_check2(dc, RRR_R, RRR_S);

                tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],

                        32 - (RRR_T | ((OP2 & 1) << 4)));

                break;

            case 2: /*SRAI*/

            case 3:

                gen_window_check2(dc, RRR_R, RRR_T);

                tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],

                        RRR_S | ((OP2 & 1) << 4));

                break;

            case 4: /*SRLI*/

                gen_window_check2(dc, RRR_R, RRR_T);

                tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);

                break;

            case 6: /*XSR*/

                {

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    if (RSR_SR >= 64) {

                        gen_check_privilege(dc);

                    }

                    gen_window_check1(dc, RRR_T);

                    tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);

                    gen_rsr(dc, cpu_R[RRR_T], RSR_SR);

                    gen_wsr(dc, RSR_SR, tmp);

                    tcg_temp_free(tmp);

                    if (!sregnames[RSR_SR]) {

                        TBD();

                    }

                }

                break;

                /*

                 * Note: 64 bit ops are used here solely because SAR values

                 * have range 0..63

                 */

#define gen_shift_reg(cmd, reg) do { \

                    TCGv_i64 tmp = tcg_temp_new_i64(); \

                    tcg_gen_extu_i32_i64(tmp, reg); \

                    tcg_gen_##cmd##_i64(v, v, tmp); \

                    tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \

                    tcg_temp_free_i64(v); \

                    tcg_temp_free_i64(tmp); \

                } while (0)

#define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])

            case 8: /*SRC*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    TCGv_i64 v = tcg_temp_new_i64();

                    tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);

                    gen_shift(shr);

                }

                break;

            case 9: /*SRL*/

                gen_window_check2(dc, RRR_R, RRR_T);

                if (dc->sar_5bit) {

                    tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);

                } else {

                    TCGv_i64 v = tcg_temp_new_i64();

                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);

                    gen_shift(shr);

                }

                break;

            case 10: /*SLL*/

                gen_window_check2(dc, RRR_R, RRR_S);

                if (dc->sar_m32_5bit) {

                    tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);

                } else {

                    TCGv_i64 v = tcg_temp_new_i64();

                    TCGv_i32 s = tcg_const_i32(32);

                    tcg_gen_sub_i32(s, s, cpu_SR[SAR]);

                    tcg_gen_andi_i32(s, s, 0x3f);

                    tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);

                    gen_shift_reg(shl, s);

                    tcg_temp_free(s);

                }

                break;

            case 11: /*SRA*/

                gen_window_check2(dc, RRR_R, RRR_T);

                if (dc->sar_5bit) {

                    tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);

                } else {

                    TCGv_i64 v = tcg_temp_new_i64();

                    tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);

                    gen_shift(sar);

                }

                break;

#undef gen_shift

#undef gen_shift_reg

            case 12: /*MUL16U*/

                HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    TCGv_i32 v1 = tcg_temp_new_i32();

                    TCGv_i32 v2 = tcg_temp_new_i32();

                    tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]);

                    tcg_gen_ext16u_i32(v2, cpu_R[RRR_T]);

                    tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);

                    tcg_temp_free(v2);

                    tcg_temp_free(v1);

                }

                break;

            case 13: /*MUL16S*/

                HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    TCGv_i32 v1 = tcg_temp_new_i32();

                    TCGv_i32 v2 = tcg_temp_new_i32();

                    tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]);

                    tcg_gen_ext16s_i32(v2, cpu_R[RRR_T]);

                    tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);

                    tcg_temp_free(v2);

                    tcg_temp_free(v1);

                }

                break;

            default: /*reserved*/

                RESERVED();

                break;

            }

            break;

        case 2: /*RST2*/

            if (OP2 >= 8) {

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

            }

            if (OP2 >= 12) {

                HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV);

                int label = gen_new_label();

                tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0, label);

                gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);

                gen_set_label(label);

            }

            switch (OP2) {

#define BOOLEAN_LOGIC(fn, r, s, t) \

                do { \

                    HAS_OPTION(XTENSA_OPTION_BOOLEAN); \

                    TCGv_i32 tmp1 = tcg_temp_new_i32(); \

                    TCGv_i32 tmp2 = tcg_temp_new_i32(); \

                    \

                    tcg_gen_shri_i32(tmp1, cpu_SR[BR], s); \

                    tcg_gen_shri_i32(tmp2, cpu_SR[BR], t); \

                    tcg_gen_##fn##_i32(tmp1, tmp1, tmp2); \

                    tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, r, 1); \

                    tcg_temp_free(tmp1); \

                    tcg_temp_free(tmp2); \

                } while (0)

            case 0: /*ANDBp*/

                BOOLEAN_LOGIC(and, RRR_R, RRR_S, RRR_T);

                break;

            case 1: /*ANDBCp*/

                BOOLEAN_LOGIC(andc, RRR_R, RRR_S, RRR_T);

                break;

            case 2: /*ORBp*/

                BOOLEAN_LOGIC(or, RRR_R, RRR_S, RRR_T);

                break;

            case 3: /*ORBCp*/

                BOOLEAN_LOGIC(orc, RRR_R, RRR_S, RRR_T);

                break;

            case 4: /*XORBp*/

                BOOLEAN_LOGIC(xor, RRR_R, RRR_S, RRR_T);

                break;

#undef BOOLEAN_LOGIC

            case 8: /*MULLi*/

                HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL);

                tcg_gen_mul_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 10: /*MULUHi*/

            case 11: /*MULSHi*/

                HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL_HIGH);

                {

                    TCGv_i64 r = tcg_temp_new_i64();

                    TCGv_i64 s = tcg_temp_new_i64();

                    TCGv_i64 t = tcg_temp_new_i64();

                    if (OP2 == 10) {

                        tcg_gen_extu_i32_i64(s, cpu_R[RRR_S]);

                        tcg_gen_extu_i32_i64(t, cpu_R[RRR_T]);

                    } else {

                        tcg_gen_ext_i32_i64(s, cpu_R[RRR_S]);

                        tcg_gen_ext_i32_i64(t, cpu_R[RRR_T]);

                    }

                    tcg_gen_mul_i64(r, s, t);

                    tcg_gen_shri_i64(r, r, 32);

                    tcg_gen_trunc_i64_i32(cpu_R[RRR_R], r);

                    tcg_temp_free_i64(r);

                    tcg_temp_free_i64(s);

                    tcg_temp_free_i64(t);

                }

                break;

            case 12: /*QUOUi*/

                tcg_gen_divu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            case 13: /*QUOSi*/

            case 15: /*REMSi*/

                {

                    int label1 = gen_new_label();

                    int label2 = gen_new_label();

                    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_S], 0x80000000,

                            label1);

                    tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0xffffffff,

                            label1);

                    tcg_gen_movi_i32(cpu_R[RRR_R],

                            OP2 == 13 ? 0x80000000 : 0);

                    tcg_gen_br(label2);

                    gen_set_label(label1);

                    if (OP2 == 13) {

                        tcg_gen_div_i32(cpu_R[RRR_R],

                                cpu_R[RRR_S], cpu_R[RRR_T]);

                    } else {

                        tcg_gen_rem_i32(cpu_R[RRR_R],

                                cpu_R[RRR_S], cpu_R[RRR_T]);

                    }

                    gen_set_label(label2);

                }

                break;

            case 14: /*REMUi*/

                tcg_gen_remu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);

                break;

            default: /*reserved*/

                RESERVED();

                break;

            }

            break;

        case 3: /*RST3*/

            switch (OP2) {

            case 0: /*RSR*/

                if (RSR_SR >= 64) {

                    gen_check_privilege(dc);

                }

                gen_window_check1(dc, RRR_T);

                gen_rsr(dc, cpu_R[RRR_T], RSR_SR);

                if (!sregnames[RSR_SR]) {

                    TBD();

                }

                break;

            case 1: /*WSR*/

                if (RSR_SR >= 64) {

                    gen_check_privilege(dc);

                }

                gen_window_check1(dc, RRR_T);

                gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);

                if (!sregnames[RSR_SR]) {

                    TBD();

                }

                break;

            case 2: /*SEXTu*/

                HAS_OPTION(XTENSA_OPTION_MISC_OP_SEXT);

                gen_window_check2(dc, RRR_R, RRR_S);

                {

                    int shift = 24 - RRR_T;

                    if (shift == 24) {

                        tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                    } else if (shift == 16) {

                        tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                    } else {

                        TCGv_i32 tmp = tcg_temp_new_i32();

                        tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift);

                        tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift);

                        tcg_temp_free(tmp);

                    }

                }

                break;

            case 3: /*CLAMPSu*/

                HAS_OPTION(XTENSA_OPTION_MISC_OP_CLAMPS);

                gen_window_check2(dc, RRR_R, RRR_S);

                {

                    TCGv_i32 tmp1 = tcg_temp_new_i32();

                    TCGv_i32 tmp2 = tcg_temp_new_i32();

                    int label = gen_new_label();

                    tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);

                    tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);

                    tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));

                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                    tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);

                    tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);

                    tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,

                            0xffffffff >> (25 - RRR_T));

                    gen_set_label(label);

                    tcg_temp_free(tmp1);

                    tcg_temp_free(tmp2);

                }

                break;

            case 4: /*MINu*/

            case 5: /*MAXu*/

            case 6: /*MINUu*/

            case 7: /*MAXUu*/

                HAS_OPTION(XTENSA_OPTION_MISC_OP_MINMAX);

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    static const TCGCond cond[] = {

                        TCG_COND_LE,

                        TCG_COND_GE,

                        TCG_COND_LEU,

                        TCG_COND_GEU

                    };

                    int label = gen_new_label();

                    if (RRR_R != RRR_T) {

                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                        tcg_gen_brcond_i32(cond[OP2 - 4],

                                cpu_R[RRR_S], cpu_R[RRR_T], label);

                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);

                    } else {

                        tcg_gen_brcond_i32(cond[OP2 - 4],

                                cpu_R[RRR_T], cpu_R[RRR_S], label);

                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                    }

                    gen_set_label(label);

                }

                break;

            case 8: /*MOVEQZ*/

            case 9: /*MOVNEZ*/

            case 10: /*MOVLTZ*/

            case 11: /*MOVGEZ*/

                gen_window_check3(dc, RRR_R, RRR_S, RRR_T);

                {

                    static const TCGCond cond[] = {

                        TCG_COND_NE,

                        TCG_COND_EQ,

                        TCG_COND_GE,

                        TCG_COND_LT

                    };

                    int label = gen_new_label();

                    tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);

                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                    gen_set_label(label);

                }

                break;

            case 12: /*MOVFp*/

            case 13: /*MOVTp*/

                HAS_OPTION(XTENSA_OPTION_BOOLEAN);

                gen_window_check2(dc, RRR_R, RRR_S);

                {

                    int label = gen_new_label();

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);

                    tcg_gen_brcondi_i32(

                            OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,

                            tmp, 0, label);

                    tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);

                    gen_set_label(label);

                    tcg_temp_free(tmp);

                }

                break;

            case 14: /*RUR*/

                gen_window_check1(dc, RRR_R);

                {

                    int st = (RRR_S << 4) + RRR_T;

                    if (uregnames[st]) {

                        tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);

                    } else {

                        qemu_log("RUR %d not implemented, ", st);

                        TBD();

                    }

                }

                break;

            case 15: /*WUR*/

                gen_window_check1(dc, RRR_T);

                {

                    if (uregnames[RSR_SR]) {

                        tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);

                    } else {

                        qemu_log("WUR %d not implemented, ", RSR_SR);

                        TBD();

                    }

                }

                break;

            }

            break;

        case 4: /*EXTUI*/

        case 5:

            gen_window_check2(dc, RRR_R, RRR_T);

            {

                int shiftimm = RRR_S | (OP1 << 4);

                int maskimm = (1 << (OP2 + 1)) - 1;

                TCGv_i32 tmp = tcg_temp_new_i32();

                tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);

                tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);

                tcg_temp_free(tmp);

            }

            break;

        case 6: /*CUST0*/

            RESERVED();

            break;

        case 7: /*CUST1*/

            RESERVED();

            break;

        case 8: /*LSCXp*/

            HAS_OPTION(XTENSA_OPTION_COPROCESSOR);

            TBD();

            break;

        case 9: /*LSC4*/

            gen_window_check2(dc, RRR_S, RRR_T);

            switch (OP2) {

            case 0: /*L32E*/

                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                gen_check_privilege(dc);

                {

                    TCGv_i32 addr = tcg_temp_new_i32();

                    tcg_gen_addi_i32(addr, cpu_R[RRR_S],

                            (0xffffffc0 | (RRR_R << 2)));

                    tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, dc->ring);

                    tcg_temp_free(addr);

                }

                break;

            case 4: /*S32E*/

                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                gen_check_privilege(dc);

                {

                    TCGv_i32 addr = tcg_temp_new_i32();

                    tcg_gen_addi_i32(addr, cpu_R[RRR_S],

                            (0xffffffc0 | (RRR_R << 2)));

                    tcg_gen_qemu_st32(cpu_R[RRR_T], addr, dc->ring);

                    tcg_temp_free(addr);

                }

                break;

            default:

                RESERVED();

                break;

            }

            break;

        case 10: /*FP0*/

            HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);

            TBD();

            break;

        case 11: /*FP1*/

            HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);

            TBD();

            break;

        default: /*reserved*/

            RESERVED();

            break;

        }

        break;

    case 1: /*L32R*/

        gen_window_check1(dc, RRR_T);

        {

            TCGv_i32 tmp = tcg_const_i32(

                    ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?

                     0 : ((dc->pc + 3) & ~3)) +

                    (0xfffc0000 | (RI16_IMM16 << 2)));

            if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {

                tcg_gen_add_i32(tmp, tmp, dc->litbase);

            }

            tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);

            tcg_temp_free(tmp);

        }

        break;

    case 2: /*LSAI*/

#define gen_load_store(type, shift) do { \

            TCGv_i32 addr = tcg_temp_new_i32(); \

            gen_window_check2(dc, RRI8_S, RRI8_T); \

            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \

            if (shift) { \

                gen_load_store_alignment(dc, shift, addr, false); \

            } \

            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \

            tcg_temp_free(addr); \

        } while (0)

        switch (RRI8_R) {

        case 0: /*L8UI*/

            gen_load_store(ld8u, 0);

            break;

        case 1: /*L16UI*/

            gen_load_store(ld16u, 1);

            break;

        case 2: /*L32I*/

            gen_load_store(ld32u, 2);

            break;

        case 4: /*S8I*/

            gen_load_store(st8, 0);

            break;

        case 5: /*S16I*/

            gen_load_store(st16, 1);

            break;

        case 6: /*S32I*/

            gen_load_store(st32, 2);

            break;

        case 7: /*CACHEc*/

            if (RRI8_T < 8) {

                HAS_OPTION(XTENSA_OPTION_DCACHE);

            }

            switch (RRI8_T) {

            case 0: /*DPFRc*/

                break;

            case 1: /*DPFWc*/

                break;

            case 2: /*DPFROc*/

                break;

            case 3: /*DPFWOc*/

                break;

            case 4: /*DHWBc*/

                break;

            case 5: /*DHWBIc*/

                break;

            case 6: /*DHIc*/

                break;

            case 7: /*DIIc*/

                break;

            case 8: /*DCEc*/

                switch (OP1) {

                case 0: /*DPFLl*/

                    HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);

                    break;

                case 2: /*DHUl*/

                    HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);

                    break;

                case 3: /*DIUl*/

                    HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);

                    break;

                case 4: /*DIWBc*/

                    HAS_OPTION(XTENSA_OPTION_DCACHE);

                    break;

                case 5: /*DIWBIc*/

                    HAS_OPTION(XTENSA_OPTION_DCACHE);

                    break;

                default: /*reserved*/

                    RESERVED();

                    break;

                }

                break;

            case 12: /*IPFc*/

                HAS_OPTION(XTENSA_OPTION_ICACHE);

                break;

            case 13: /*ICEc*/

                switch (OP1) {

                case 0: /*IPFLl*/

                    HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);

                    break;

                case 2: /*IHUl*/

                    HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);

                    break;

                case 3: /*IIUl*/

                    HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);

                    break;

                default: /*reserved*/

                    RESERVED();

                    break;

                }

                break;

            case 14: /*IHIc*/

                HAS_OPTION(XTENSA_OPTION_ICACHE);

                break;

            case 15: /*IIIc*/

                HAS_OPTION(XTENSA_OPTION_ICACHE);

                break;

            default: /*reserved*/

                RESERVED();

                break;

            }

            break;

        case 9: /*L16SI*/

            gen_load_store(ld16s, 1);

            break;

#undef gen_load_store

        case 10: /*MOVI*/

            gen_window_check1(dc, RRI8_T);

            tcg_gen_movi_i32(cpu_R[RRI8_T],

                    RRI8_IMM8 | (RRI8_S << 8) |

                    ((RRI8_S & 0x8) ? 0xfffff000 : 0));

            break;

#define gen_load_store_no_hw_align(type) do { \

            TCGv_i32 addr = tcg_temp_local_new_i32(); \

            gen_window_check2(dc, RRI8_S, RRI8_T); \

            tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \

            gen_load_store_alignment(dc, 2, addr, true); \

            tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \

            tcg_temp_free(addr); \

        } while (0)

        case 11: /*L32AIy*/

            HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);

            gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/

            break;

        case 12: /*ADDI*/

            gen_window_check2(dc, RRI8_S, RRI8_T);

            tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);

            break;

        case 13: /*ADDMI*/

            gen_window_check2(dc, RRI8_S, RRI8_T);

            tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);

            break;

        case 14: /*S32C1Iy*/

            HAS_OPTION(XTENSA_OPTION_CONDITIONAL_STORE);

            gen_window_check2(dc, RRI8_S, RRI8_T);

            {

                int label = gen_new_label();

                TCGv_i32 tmp = tcg_temp_local_new_i32();

                TCGv_i32 addr = tcg_temp_local_new_i32();

                tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);

                tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);

                gen_load_store_alignment(dc, 2, addr, true);

                tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);

                tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],

                        cpu_SR[SCOMPARE1], label);

                tcg_gen_qemu_st32(tmp, addr, dc->cring);

                gen_set_label(label);

                tcg_temp_free(addr);

                tcg_temp_free(tmp);

            }

            break;

        case 15: /*S32RIy*/

            HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);

            gen_load_store_no_hw_align(st32); /*TODO release?*/

            break;

#undef gen_load_store_no_hw_align

        default: /*reserved*/

            RESERVED();

            break;

        }

        break;

    case 3: /*LSCIp*/

        HAS_OPTION(XTENSA_OPTION_COPROCESSOR);

        TBD();

        break;

    case 4: /*MAC16d*/

        HAS_OPTION(XTENSA_OPTION_MAC16);

        {

            enum {

                MAC16_UMUL = 0x0,

                MAC16_MUL  = 0x4,

                MAC16_MULA = 0x8,

                MAC16_MULS = 0xc,

                MAC16_NONE = 0xf,

            } op = OP1 & 0xc;

            bool is_m1_sr = (OP2 & 0x3) == 2;

            bool is_m2_sr = (OP2 & 0xc) == 0;

            uint32_t ld_offset = 0;

            if (OP2 > 9) {

                RESERVED();

            }

            switch (OP2 & 2) {

            case 0: /*MACI?/MACC?*/

                is_m1_sr = true;

                ld_offset = (OP2 & 1) ? -4 : 4;

                if (OP2 >= 8) { /*MACI/MACC*/

                    if (OP1 == 0) { /*LDINC/LDDEC*/

                        op = MAC16_NONE;

                    } else {

                        RESERVED();

                    }

                } else if (op != MAC16_MULA) { /*MULA.*.*.LDINC/LDDEC*/

                    RESERVED();

                }

                break;

            case 2: /*MACD?/MACA?*/

                if (op == MAC16_UMUL && OP2 != 7) { /*UMUL only in MACAA*/

                    RESERVED();

                }

                break;

            }

            if (op != MAC16_NONE) {

                if (!is_m1_sr) {

                    gen_window_check1(dc, RRR_S);

                }

                if (!is_m2_sr) {

                    gen_window_check1(dc, RRR_T);

                }

            }

            {

                TCGv_i32 vaddr = tcg_temp_new_i32();

                TCGv_i32 mem32 = tcg_temp_new_i32();

                if (ld_offset) {

                    gen_window_check1(dc, RRR_S);

                    tcg_gen_addi_i32(vaddr, cpu_R[RRR_S], ld_offset);

                    gen_load_store_alignment(dc, 2, vaddr, false);

                    tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);

                }

                if (op != MAC16_NONE) {

                    TCGv_i32 m1 = gen_mac16_m(

                            is_m1_sr ? cpu_SR[MR + RRR_X] : cpu_R[RRR_S],

                            OP1 & 1, op == MAC16_UMUL);

                    TCGv_i32 m2 = gen_mac16_m(

                            is_m2_sr ? cpu_SR[MR + 2 + RRR_Y] : cpu_R[RRR_T],

                            OP1 & 2, op == MAC16_UMUL);

                    if (op == MAC16_MUL || op == MAC16_UMUL) {

                        tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2);

                        if (op == MAC16_UMUL) {

                            tcg_gen_movi_i32(cpu_SR[ACCHI], 0);

                        } else {

                            tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31);

                        }

                    } else {

                        TCGv_i32 res = tcg_temp_new_i32();

                        TCGv_i64 res64 = tcg_temp_new_i64();

                        TCGv_i64 tmp = tcg_temp_new_i64();

                        tcg_gen_mul_i32(res, m1, m2);

                        tcg_gen_ext_i32_i64(res64, res);

                        tcg_gen_concat_i32_i64(tmp,

                                cpu_SR[ACCLO], cpu_SR[ACCHI]);

                        if (op == MAC16_MULA) {

                            tcg_gen_add_i64(tmp, tmp, res64);

                        } else {

                            tcg_gen_sub_i64(tmp, tmp, res64);

                        }

                        tcg_gen_trunc_i64_i32(cpu_SR[ACCLO], tmp);

                        tcg_gen_shri_i64(tmp, tmp, 32);

                        tcg_gen_trunc_i64_i32(cpu_SR[ACCHI], tmp);

                        tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]);

                        tcg_temp_free(res);

                        tcg_temp_free_i64(res64);

                        tcg_temp_free_i64(tmp);

                    }

                    tcg_temp_free(m1);

                    tcg_temp_free(m2);

                }

                if (ld_offset) {

                    tcg_gen_mov_i32(cpu_R[RRR_S], vaddr);

                    tcg_gen_mov_i32(cpu_SR[MR + RRR_W], mem32);

                }

                tcg_temp_free(vaddr);

                tcg_temp_free(mem32);

            }

        }

        break;

    case 5: /*CALLN*/

        switch (CALL_N) {

        case 0: /*CALL0*/

            tcg_gen_movi_i32(cpu_R[0], dc->next_pc);

            gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);

            break;

        case 1: /*CALL4w*/

        case 2: /*CALL8w*/

        case 3: /*CALL12w*/

            HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

            gen_window_check1(dc, CALL_N << 2);

            gen_callwi(dc, CALL_N,

                    (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);

            break;

        }

        break;

    case 6: /*SI*/

        switch (CALL_N) {

        case 0: /*J*/

            gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);

            break;

        case 1: /*BZ*/

            gen_window_check1(dc, BRI12_S);

            {

                static const TCGCond cond[] = {

                    TCG_COND_EQ, /*BEQZ*/

                    TCG_COND_NE, /*BNEZ*/

                    TCG_COND_LT, /*BLTZ*/

                    TCG_COND_GE, /*BGEZ*/

                };

                gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0,

                        4 + BRI12_IMM12_SE);

            }

            break;

        case 2: /*BI0*/

            gen_window_check1(dc, BRI8_S);

            {

                static const TCGCond cond[] = {

                    TCG_COND_EQ, /*BEQI*/

                    TCG_COND_NE, /*BNEI*/

                    TCG_COND_LT, /*BLTI*/

                    TCG_COND_GE, /*BGEI*/

                };

                gen_brcondi(dc, cond[BRI8_M & 3],

                        cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE);

            }

            break;

        case 3: /*BI1*/

            switch (BRI8_M) {

            case 0: /*ENTRYw*/

                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                {

                    TCGv_i32 pc = tcg_const_i32(dc->pc);

                    TCGv_i32 s = tcg_const_i32(BRI12_S);

                    TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);

                    gen_advance_ccount(dc);

                    gen_helper_entry(pc, s, imm);

                    tcg_temp_free(imm);

                    tcg_temp_free(s);

                    tcg_temp_free(pc);

                    reset_used_window(dc);

                }

                break;

            case 1: /*B1*/

                switch (BRI8_R) {

                case 0: /*BFp*/

                case 1: /*BTp*/

                    HAS_OPTION(XTENSA_OPTION_BOOLEAN);

                    {

                        TCGv_i32 tmp = tcg_temp_new_i32();

                        tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRI8_S);

                        gen_brcondi(dc,

                                BRI8_R == 1 ? TCG_COND_NE : TCG_COND_EQ,

                                tmp, 0, 4 + RRI8_IMM8_SE);

                        tcg_temp_free(tmp);

                    }

                    break;

                case 8: /*LOOP*/

                case 9: /*LOOPNEZ*/

                case 10: /*LOOPGTZ*/

                    HAS_OPTION(XTENSA_OPTION_LOOP);

                    gen_window_check1(dc, RRI8_S);

                    {

                        uint32_t lend = dc->pc + RRI8_IMM8 + 4;

                        TCGv_i32 tmp = tcg_const_i32(lend);

                        tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);

                        tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);

                        gen_wsr_lend(dc, LEND, tmp);

                        tcg_temp_free(tmp);

                        if (BRI8_R > 8) {

                            int label = gen_new_label();

                            tcg_gen_brcondi_i32(

                                    BRI8_R == 9 ? TCG_COND_NE : TCG_COND_GT,

                                    cpu_R[RRI8_S], 0, label);

                            gen_jumpi(dc, lend, 1);

                            gen_set_label(label);

                        }

                        gen_jumpi(dc, dc->next_pc, 0);

                    }

                    break;

                default: /*reserved*/

                    RESERVED();

                    break;

                }

                break;

            case 2: /*BLTUI*/

            case 3: /*BGEUI*/

                gen_window_check1(dc, BRI8_S);

                gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,

                        cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);

                break;

            }

            break;

        }

        break;

    case 7: /*B*/

        {

            TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ;

            switch (RRI8_R & 7) {

            case 0: /*BNONE*/ /*BANY*/

                gen_window_check2(dc, RRI8_S, RRI8_T);

                {

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);

                    gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);

                    tcg_temp_free(tmp);

                }

                break;

            case 1: /*BEQ*/ /*BNE*/

            case 2: /*BLT*/ /*BGE*/

            case 3: /*BLTU*/ /*BGEU*/

                gen_window_check2(dc, RRI8_S, RRI8_T);

                {

                    static const TCGCond cond[] = {

                        [1] = TCG_COND_EQ,

                        [2] = TCG_COND_LT,

                        [3] = TCG_COND_LTU,

                        [9] = TCG_COND_NE,

                        [10] = TCG_COND_GE,

                        [11] = TCG_COND_GEU,

                    };

                    gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T],

                            4 + RRI8_IMM8_SE);

                }

                break;

            case 4: /*BALL*/ /*BNALL*/

                gen_window_check2(dc, RRI8_S, RRI8_T);

                {

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);

                    gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],

                            4 + RRI8_IMM8_SE);

                    tcg_temp_free(tmp);

                }

                break;

            case 5: /*BBC*/ /*BBS*/

                gen_window_check2(dc, RRI8_S, RRI8_T);

                {

                    TCGv_i32 bit = tcg_const_i32(1);

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f);

                    tcg_gen_shl_i32(bit, bit, tmp);

                    tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit);

                    gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);

                    tcg_temp_free(tmp);

                    tcg_temp_free(bit);

                }

                break;

            case 6: /*BBCI*/ /*BBSI*/

            case 7:

                gen_window_check1(dc, RRI8_S);

                {

                    TCGv_i32 tmp = tcg_temp_new_i32();

                    tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],

                            1 << (((RRI8_R & 1) << 4) | RRI8_T));

                    gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);

                    tcg_temp_free(tmp);

                }

                break;

            }

        }

        break;

#define gen_narrow_load_store(type) do { \

            TCGv_i32 addr = tcg_temp_new_i32(); \

            gen_window_check2(dc, RRRN_S, RRRN_T); \

            tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \

            gen_load_store_alignment(dc, 2, addr, false); \

            tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \

            tcg_temp_free(addr); \

        } while (0)

    case 8: /*L32I.Nn*/

        gen_narrow_load_store(ld32u);

        break;

    case 9: /*S32I.Nn*/

        gen_narrow_load_store(st32);

        break;

#undef gen_narrow_load_store

    case 10: /*ADD.Nn*/

        gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T);

        tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);

        break;

    case 11: /*ADDI.Nn*/

        gen_window_check2(dc, RRRN_R, RRRN_S);

        tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);

        break;

    case 12: /*ST2n*/

        gen_window_check1(dc, RRRN_S);

        if (RRRN_T < 8) { /*MOVI.Nn*/

            tcg_gen_movi_i32(cpu_R[RRRN_S],

                    RRRN_R | (RRRN_T << 4) |

                    ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));

        } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/

            TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ;

            gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0,

                    4 + (RRRN_R | ((RRRN_T & 3) << 4)));

        }

        break;

    case 13: /*ST3n*/

        switch (RRRN_R) {

        case 0: /*MOV.Nn*/

            gen_window_check2(dc, RRRN_S, RRRN_T);

            tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);

            break;

        case 15: /*S3*/

            switch (RRRN_T) {

            case 0: /*RET.Nn*/

                gen_jump(dc, cpu_R[0]);

                break;

            case 1: /*RETW.Nn*/

                HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);

                {

                    TCGv_i32 tmp = tcg_const_i32(dc->pc);

                    gen_advance_ccount(dc);

                    gen_helper_retw(tmp, tmp);

                    gen_jump(dc, tmp);

                    tcg_temp_free(tmp);

                }

                break;

            case 2: /*BREAK.Nn*/

                HAS_OPTION(XTENSA_OPTION_DEBUG);

                if (dc->debug) {

                    gen_debug_exception(dc, DEBUGCAUSE_BN);

                }

                break;

            case 3: /*NOP.Nn*/

                break;

            case 6: /*ILL.Nn*/

                gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);

                break;

            default: /*reserved*/

                RESERVED();

                break;

            }

            break;

        default: /*reserved*/

            RESERVED();

            break;

        }

        break;

    default: /*reserved*/

        RESERVED();

        break;

    }

    gen_check_loop_end(dc, 0);

    dc->pc = dc->next_pc;

    return;

invalid_opcode:

    qemu_log("INVALID(pc = %08x)\n", dc->pc);

    gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);

#undef HAS_OPTION

}


static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp opc,

                               TCGReg addrlo, TCGReg addrhi,

                               int mem_index, bool is_read)

{

    int cmp_off

        = (is_read

           ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)

           : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));

    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);

    TCGReg base = TCG_AREG0;

    TCGMemOp s_bits = opc & MO_SIZE;

    /* Extract the page index, shifted into place for tlb index.  */

    if (TCG_TARGET_REG_BITS == 64) {

        if (TARGET_LONG_BITS == 32) {

            /* Zero-extend the address into a place helpful for further use. */

            tcg_out_ext32u(s, TCG_REG_R4, addrlo);

            addrlo = TCG_REG_R4;

        } else {

            tcg_out_rld(s, RLDICL, TCG_REG_R3, addrlo,

                        64 - TARGET_PAGE_BITS, 64 - CPU_TLB_BITS);

        }

    }

    /* Compensate for very large offsets.  */

    if (add_off >= 0x8000) {

        /* Most target env are smaller than 32k; none are larger than 64k.

           Simplify the logic here merely to offset by 0x7ff0, giving us a

           range just shy of 64k.  Check this assumption.  */

        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,

                                   tlb_table[NB_MMU_MODES - 1][1])

                          > 0x7ff0 + 0x7fff);

        tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, base, 0x7ff0));

        base = TCG_REG_TMP1;

        cmp_off -= 0x7ff0;

        add_off -= 0x7ff0;

    }

    /* Extraction and shifting, part 2.  */

    if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {

        tcg_out_rlw(s, RLWINM, TCG_REG_R3, addrlo,

                    32 - (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),

                    32 - (CPU_TLB_BITS + CPU_TLB_ENTRY_BITS),

                    31 - CPU_TLB_ENTRY_BITS);

    } else {

        tcg_out_shli64(s, TCG_REG_R3, TCG_REG_R3, CPU_TLB_ENTRY_BITS);

    }

    tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, base));

    /* Load the tlb comparator.  */

    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {

        tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R4, TCG_REG_R3, cmp_off);

        tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP1, TCG_REG_R3, cmp_off + 4);

    } else {

        tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP1, TCG_REG_R3, cmp_off);

    }

    /* Load the TLB addend for use on the fast path.  Do this asap

       to minimize any load use delay.  */

    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3, add_off);

    /* Clear the non-page, non-alignment bits from the address */

    if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {

        /* We don't support unaligned accesses on 32-bits, preserve

         * the bottom bits and thus trigger a comparison failure on

         * unaligned accesses

         */

        tcg_out_rlw(s, RLWINM, TCG_REG_R0, addrlo, 0,

                    (32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);

    } else if (s_bits) {

        /* > byte access, we need to handle alignment */

        if ((opc & MO_AMASK) == MO_ALIGN) {

            /* Alignment required by the front-end, same as 32-bits */

            tcg_out_rld(s, RLDICL, TCG_REG_R0, addrlo,

                        64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);

            tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);

       } else {

           /* We support unaligned accesses, we need to make sure we fail

            * if we cross a page boundary. The trick is to add the

            * access_size-1 to the address before masking the low bits.

            * That will make the address overflow to the next page if we

            * cross a page boundary which will then force a mismatch of

            * the TLB compare since the next page cannot possibly be in

            * the same TLB index.

            */

            tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, (1 << s_bits) - 1));

            tcg_out_rld(s, RLDICR, TCG_REG_R0, TCG_REG_R0,

                        0, 63 - TARGET_PAGE_BITS);

        }

    } else {

        /* Byte access, just chop off the bits below the page index */

        tcg_out_rld(s, RLDICR, TCG_REG_R0, addrlo, 0, 63 - TARGET_PAGE_BITS);

    }

    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {

        tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,

                    0, 7, TCG_TYPE_I32);

        tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_R4, 0, 6, TCG_TYPE_I32);

        tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));

    } else {

        tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,

                    0, 7, TCG_TYPE_TL);

    }

    return addrlo;

}


static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx,

                                                   RowContext *row,

                                                   int n,

                                                   int index_bits,

                                                   int level_bias,

                                                   int level_shift,

                                                   int dc_shift)

{

    int i, j, index1, index2, len, flags;

    int level, component, sign;

    const int *scale;

    const uint8_t *weight_matrix;

    const uint8_t *ac_info = ctx->cid_table->ac_info;

    int16_t *block = row->blocks[n];

    const int eob_index     = ctx->cid_table->eob_index;

    int ret = 0;

    OPEN_READER(bs, &row->gb);

    ctx->bdsp.clear_block(block);

    if (!ctx->is_444) {

        if (n & 2) {

            component     = 1 + (n & 1);

            scale = row->chroma_scale;

            weight_matrix = ctx->cid_table->chroma_weight;

        } else {

            component     = 0;

            scale = row->luma_scale;

            weight_matrix = ctx->cid_table->luma_weight;

        }

    } else {

        component = (n >> 1) % 3;

        if (component) {

            scale = row->chroma_scale;

            weight_matrix = ctx->cid_table->chroma_weight;

        } else {

            scale = row->luma_scale;

            weight_matrix = ctx->cid_table->luma_weight;

        }

    }

    UPDATE_CACHE(bs, &row->gb);

    GET_VLC(len, bs, &row->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1);

    if (len) {

        level = GET_CACHE(bs, &row->gb);

        LAST_SKIP_BITS(bs, &row->gb, len);

        sign  = ~level >> 31;

        level = (NEG_USR32(sign ^ level, len) ^ sign) - sign;

        row->last_dc[component] += level << dc_shift;

    }

    block[0] = row->last_dc[component];

    i = 0;

    UPDATE_CACHE(bs, &row->gb);

    GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,

            DNXHD_VLC_BITS, 2);

    while (index1 != eob_index) {

        level = ac_info[2*index1+0];

        flags = ac_info[2*index1+1];

        sign = SHOW_SBITS(bs, &row->gb, 1);

        SKIP_BITS(bs, &row->gb, 1);

        if (flags & 1) {

            level += SHOW_UBITS(bs, &row->gb, index_bits) << 7;

            SKIP_BITS(bs, &row->gb, index_bits);

        }

        if (flags & 2) {

            UPDATE_CACHE(bs, &row->gb);

            GET_VLC(index2, bs, &row->gb, ctx->run_vlc.table,

                    DNXHD_VLC_BITS, 2);

            i += ctx->cid_table->run[index2];

        }

        if (++i > 63) {

            av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i);

            ret = -1;

            break;

        }

        j     = ctx->scantable.permutated[i];

        level *= scale[i];

        level += scale[i] >> 1;

        if (level_bias < 32 || weight_matrix[i] != level_bias)

            level += level_bias; // 1<<(level_shift-1)

        level >>= level_shift;

        block[j] = (level ^ sign) - sign;

        UPDATE_CACHE(bs, &row->gb);

        GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,

                DNXHD_VLC_BITS, 2);

    }

    CLOSE_READER(bs, &row->gb);

    return ret;

}


static uint64_t build_channel_report_mcic(void)

{

    uint64_t mcic;

    /* subclass: indicate channel report pending */

    mcic = MCIC_SC_CP |

    /* subclass modifiers: none */

    /* storage errors: none */

    /* validity bits: no damage */

        MCIC_VB_WP | MCIC_VB_MS | MCIC_VB_PM | MCIC_VB_IA | MCIC_VB_FP |

        MCIC_VB_GR | MCIC_VB_CR | MCIC_VB_ST | MCIC_VB_AR | MCIC_VB_PR |

        MCIC_VB_FC | MCIC_VB_CT | MCIC_VB_CC;

    if (s390_has_feat(S390_FEAT_VECTOR)) {

        mcic |= MCIC_VB_VR;

    }

    if (s390_has_feat(S390_FEAT_GUARDED_STORAGE)) {

        mcic |= MCIC_VB_GS;

    }

    return mcic;

}


static int do_virtio_net_can_receive(VirtIONet *n, int bufsize)

{

    if (!virtio_queue_ready(n->rx_vq) ||

        !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))

        return 0;

    if (virtio_queue_empty(n->rx_vq) ||

        (n->mergeable_rx_bufs &&

         !virtqueue_avail_bytes(n->rx_vq, bufsize, 0))) {

        virtio_queue_set_notification(n->rx_vq, 1);

        return 0;

    }

    virtio_queue_set_notification(n->rx_vq, 0);

    return 1;

}


static inline void gen_bcond(DisasContext *ctx, int type)

{

    uint32_t bo = BO(ctx->opcode);

    int l1;

    TCGv target;

    ctx->exception = POWERPC_EXCP_BRANCH;

    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {

        target = tcg_temp_local_new();

        if (type == BCOND_CTR)

            tcg_gen_mov_tl(target, cpu_ctr);

        else if (type == BCOND_TAR)

            gen_load_spr(target, SPR_TAR);

        else

            tcg_gen_mov_tl(target, cpu_lr);

    } else {

        TCGV_UNUSED(target);

    }

    if (LK(ctx->opcode))

        gen_setlr(ctx, ctx->nip);

    l1 = gen_new_label();

    if ((bo & 0x4) == 0) {

        /* Decrement and test CTR */

        TCGv temp = tcg_temp_new();

        if (unlikely(type == BCOND_CTR)) {

            gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);

            return;

        }

        tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);

        if (NARROW_MODE(ctx)) {

            tcg_gen_ext32u_tl(temp, cpu_ctr);

        } else {

            tcg_gen_mov_tl(temp, cpu_ctr);

        }

        if (bo & 0x2) {

            tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);

        } else {

            tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);

        }

        tcg_temp_free(temp);

    }

    if ((bo & 0x10) == 0) {

        /* Test CR */

        uint32_t bi = BI(ctx->opcode);

        uint32_t mask = 0x08 >> (bi & 0x03);

        TCGv_i32 temp = tcg_temp_new_i32();

        if (bo & 0x8) {

            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);

            tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);

        } else {

            tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);

            tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);

        }

        tcg_temp_free_i32(temp);

    }

    gen_update_cfar(ctx, ctx->nip);

    if (type == BCOND_IM) {

        target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));

        if (likely(AA(ctx->opcode) == 0)) {

            gen_goto_tb(ctx, 0, ctx->nip + li - 4);

        } else {

            gen_goto_tb(ctx, 0, li);

        }

        gen_set_label(l1);

        gen_goto_tb(ctx, 1, ctx->nip);

    } else {

        if (NARROW_MODE(ctx)) {

            tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);

        } else {

            tcg_gen_andi_tl(cpu_nip, target, ~3);

        }

        tcg_gen_exit_tb(0);

        gen_set_label(l1);

        gen_update_nip(ctx, ctx->nip);

        tcg_gen_exit_tb(0);

    }

    if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {

        tcg_temp_free(target);

    }

}


static void menelaus_pre_save(void *opaque)

{

    MenelausState *s = opaque;

    /* Should be <= 1000 */

    s->rtc_next_vmstate =  s->rtc.next - qemu_get_clock(rt_clock);

}


static inline uint64_t bdrv_get_align(BlockDriverState *bs)

{

    /* TODO Lift BDRV_SECTOR_SIZE restriction in BlockDriver interface */

    return MAX(BDRV_SECTOR_SIZE, bs->request_alignment);

}


static int mipsnet_can_receive(void *opaque)

{

    MIPSnetState *s = opaque;

    if (s->busy)

        return 0;

    return !mipsnet_buffer_full(s);

}


void hmp_host_net_remove(Monitor *mon, const QDict *qdict)

{

    NetClientState *nc;

    int vlan_id = qdict_get_int(qdict, "vlan_id");

    const char *device = qdict_get_str(qdict, "device");

    nc = net_hub_find_client_by_name(vlan_id, device);

    if (!nc) {

        error_report("Host network device '%s' on hub '%d' not found",

                     device, vlan_id);

        return;

    }

    if (!net_host_check_device(nc->model)) {

        error_report("invalid host network device '%s'", device);

        return;

    }

    qemu_del_net_client(nc->peer);

    qemu_del_net_client(nc);

}


static int ssd0303_init(I2CSlave *i2c)

{

    ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);

    s->con = graphic_console_init(ssd0303_update_display,

                                  ssd0303_invalidate_display,

                                  NULL, NULL, s);

    qemu_console_resize(s->con, 96 * MAGNIFY, 16 * MAGNIFY);

    return 0;

}


static enum AVPixelFormat webp_get_format(AVCodecContext *avctx,

                                          const enum AVPixelFormat *formats)

{

    WebPContext *s = avctx->priv_data;

    if (s->has_alpha)

        return AV_PIX_FMT_YUVA420P;

    else

        return AV_PIX_FMT_YUV420P;

}


static void coded_frame_add(void *list, struct FrameListData *cx_frame)

{

    struct FrameListData **p = list;

    while (*p != NULL)

        p = &(*p)->next;

    *p = cx_frame;

    cx_frame->next = NULL;

}


void swri_resample_dsp_x86_init(ResampleContext *c)

{

    int av_unused mm_flags = av_get_cpu_flags();

    switch(c->format){

    case AV_SAMPLE_FMT_S16P:

        if (ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL && mm_flags & AV_CPU_FLAG_MMX2) {

            c->dsp.resample = c->linear ? ff_resample_linear_int16_mmxext

                                        : ff_resample_common_int16_mmxext;

        }

        if (HAVE_SSE2_EXTERNAL && mm_flags & AV_CPU_FLAG_SSE2) {

            c->dsp.resample = c->linear ? ff_resample_linear_int16_sse2

                                        : ff_resample_common_int16_sse2;

        }

        if (HAVE_XOP_EXTERNAL && mm_flags & AV_CPU_FLAG_XOP) {

            c->dsp.resample = c->linear ? ff_resample_linear_int16_xop

                                        : ff_resample_common_int16_xop;

        }

        break;

    case AV_SAMPLE_FMT_FLTP:

        if (HAVE_SSE_EXTERNAL && mm_flags & AV_CPU_FLAG_SSE) {

            c->dsp.resample = c->linear ? ff_resample_linear_float_sse

                                        : ff_resample_common_float_sse;

        }

        if (HAVE_AVX_EXTERNAL && mm_flags & AV_CPU_FLAG_AVX) {

            c->dsp.resample = c->linear ? ff_resample_linear_float_avx

                                        : ff_resample_common_float_avx;

        }

        if (HAVE_FMA3_EXTERNAL && mm_flags & AV_CPU_FLAG_FMA3) {

            c->dsp.resample = c->linear ? ff_resample_linear_float_fma3

                                        : ff_resample_common_float_fma3;

        }

        if (HAVE_FMA4_EXTERNAL && mm_flags & AV_CPU_FLAG_FMA4) {

            c->dsp.resample = c->linear ? ff_resample_linear_float_fma4

                                        : ff_resample_common_float_fma4;

        }

        break;

    case AV_SAMPLE_FMT_DBLP:

        if (HAVE_SSE2_EXTERNAL && mm_flags & AV_CPU_FLAG_SSE2) {

            c->dsp.resample = c->linear ? ff_resample_linear_double_sse2

                                        : ff_resample_common_double_sse2;

        }

        break;

    }

}


void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,

                               DisplaySurface *surface)

{

    SimpleSpiceUpdate *update;

    bool need_destroy;

    if (surface && ssd->surface &&

        surface_width(surface) == pixman_image_get_width(ssd->surface) &&

        surface_height(surface) == pixman_image_get_height(ssd->surface)) {

        /* no-resize fast path: just swap backing store */

        dprint(1, "%s/%d: fast (%dx%d)\n", __func__, ssd->qxl.id,

               surface_width(surface), surface_height(surface));

        qemu_mutex_lock(&ssd->lock);

        ssd->ds = surface;

        pixman_image_unref(ssd->surface);

        ssd->surface = pixman_image_ref(ssd->ds->image);

        qemu_mutex_unlock(&ssd->lock);

        qemu_spice_display_update(ssd, 0, 0,

                                  surface_width(surface),

                                  surface_height(surface));

        return;

    }

    /* full mode switch */

    dprint(1, "%s/%d: full (%dx%d -> %dx%d)\n", __func__, ssd->qxl.id,

           ssd->surface ? pixman_image_get_width(ssd->surface)  : 0,

           ssd->surface ? pixman_image_get_height(ssd->surface) : 0,

           surface ? surface_width(surface)  : 0,

           surface ? surface_height(surface) : 0);

    memset(&ssd->dirty, 0, sizeof(ssd->dirty));

    if (ssd->surface) {

        pixman_image_unref(ssd->surface);

        ssd->surface = NULL;

        pixman_image_unref(ssd->mirror);

        ssd->mirror = NULL;

    }

    qemu_mutex_lock(&ssd->lock);

    need_destroy = (ssd->ds != NULL);

    ssd->ds = surface;

    while ((update = QTAILQ_FIRST(&ssd->updates)) != NULL) {

        QTAILQ_REMOVE(&ssd->updates, update, next);

        qemu_spice_destroy_update(ssd, update);

    }

    qemu_mutex_unlock(&ssd->lock);

    if (need_destroy) {

        qemu_spice_destroy_host_primary(ssd);

    }

    if (ssd->ds) {

        ssd->surface = pixman_image_ref(ssd->ds->image);

        ssd->mirror  = qemu_pixman_mirror_create(ssd->ds->format,

                                                 ssd->ds->image);

        qemu_spice_create_host_primary(ssd);

    }

    memset(&ssd->dirty, 0, sizeof(ssd->dirty));

    ssd->notify++;

}


GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)

{

    GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;

    struct ifaddrs *ifap, *ifa;

    char err_msg[512];

    if (getifaddrs(&ifap) < 0) {

        snprintf(err_msg, sizeof(err_msg),

                 "getifaddrs failed: %s", strerror(errno));

        error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);

        goto error;

    }

    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {

        GuestNetworkInterfaceList *info;

        GuestIpAddressList **address_list = NULL, *address_item = NULL;

        char addr4[INET_ADDRSTRLEN];

        char addr6[INET6_ADDRSTRLEN];

        int sock;

        struct ifreq ifr;

        unsigned char *mac_addr;

        void *p;

        g_debug("Processing %s interface", ifa->ifa_name);

        info = guest_find_interface(head, ifa->ifa_name);

        if (!info) {

            info = g_malloc0(sizeof(*info));

            info->value = g_malloc0(sizeof(*info->value));

            info->value->name = g_strdup(ifa->ifa_name);

            if (!cur_item) {

                head = cur_item = info;

            } else {

                cur_item->next = info;

                cur_item = info;

            }

        }

        if (!info->value->has_hardware_address &&

            ifa->ifa_flags & SIOCGIFHWADDR) {

            /* we haven't obtained HW address yet */

            sock = socket(PF_INET, SOCK_STREAM, 0);

            if (sock == -1) {

                snprintf(err_msg, sizeof(err_msg),

                         "failed to create socket: %s", strerror(errno));

                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);

                goto error;

            }

            memset(&ifr, 0, sizeof(ifr));

            strncpy(ifr.ifr_name,  info->value->name, IF_NAMESIZE);

            if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {

                snprintf(err_msg, sizeof(err_msg),

                         "failed to get MAC addres of %s: %s",

                         ifa->ifa_name,

                         strerror(errno));

                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);

                goto error;

            }

            mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;

            if (asprintf(&info->value->hardware_address,

                         "%02x:%02x:%02x:%02x:%02x:%02x",

                         (int) mac_addr[0], (int) mac_addr[1],

                         (int) mac_addr[2], (int) mac_addr[3],

                         (int) mac_addr[4], (int) mac_addr[5]) == -1) {

                snprintf(err_msg, sizeof(err_msg),

                         "failed to format MAC: %s", strerror(errno));

                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);

                goto error;

            }

            info->value->has_hardware_address = true;

            close(sock);

        }

        if (ifa->ifa_addr &&

            ifa->ifa_addr->sa_family == AF_INET) {

            /* interface with IPv4 address */

            address_item = g_malloc0(sizeof(*address_item));

            address_item->value = g_malloc0(sizeof(*address_item->value));

            p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;

            if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {

                snprintf(err_msg, sizeof(err_msg),

                         "inet_ntop failed : %s", strerror(errno));

                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);

                goto error;

            }

            address_item->value->ip_address = g_strdup(addr4);

            address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;

            if (ifa->ifa_netmask) {

                /* Count the number of set bits in netmask.

                 * This is safe as '1' and '0' cannot be shuffled in netmask. */

                p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;

                address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);

            }

        } else if (ifa->ifa_addr &&

                   ifa->ifa_addr->sa_family == AF_INET6) {

            /* interface with IPv6 address */

            address_item = g_malloc0(sizeof(*address_item));

            address_item->value = g_malloc0(sizeof(*address_item->value));

            p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;

            if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {

                snprintf(err_msg, sizeof(err_msg),

                         "inet_ntop failed : %s", strerror(errno));

                error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg);

                goto error;

            }

            address_item->value->ip_address = g_strdup(addr6);

            address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;

            if (ifa->ifa_netmask) {

                /* Count the number of set bits in netmask.

                 * This is safe as '1' and '0' cannot be shuffled in netmask. */

                p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;

                address_item->value->prefix =

                    ctpop32(((uint32_t *) p)[0]) +

                    ctpop32(((uint32_t *) p)[1]) +

                    ctpop32(((uint32_t *) p)[2]) +

                    ctpop32(((uint32_t *) p)[3]);

            }

        }

        if (!address_item) {

            continue;

        }

        address_list = &info->value->ip_addresses;

        while (*address_list && (*address_list)->next) {

            address_list = &(*address_list)->next;

        }

        if (!*address_list) {

            *address_list = address_item;

        } else {

            (*address_list)->next = address_item;

        }

        info->value->has_ip_addresses = true;

    }

    freeifaddrs(ifap);

    return head;

error:

    freeifaddrs(ifap);

    qapi_free_GuestNetworkInterfaceList(head);

    return NULL;

}


static inline int coef_test_compression(int coef)

{

    int tmp = coef >> 2;

    int res = ff_ctz(tmp);

    if (res > 1)

        return 1;       /* ...00 ->  compressable    */

    else if (res == 1)

        return 0;       /* ...10 ->  uncompressable  */

    else if (ff_ctz(tmp >> 1) > 0)

        return 0;       /* ...0 1 -> uncompressable  */

    else

        return 1;       /* ...1 1 -> compressable    */

}


static int ac97_load (QEMUFile *f, void *opaque, int version_id)

{

    int ret;

    size_t i;

    uint8_t active[LAST_INDEX];

    AC97LinkState *s = opaque;

    if (version_id != 2)

        return -EINVAL;

    ret = pci_device_load (s->pci_dev, f);

    if (ret)

        return ret;

    qemu_get_be32s (f, &s->glob_cnt);

    qemu_get_be32s (f, &s->glob_sta);

    qemu_get_be32s (f, &s->cas);

    for (i = 0; i < ARRAY_SIZE (s->bm_regs); ++i) {

        AC97BusMasterRegs *r = &s->bm_regs[i];

        qemu_get_be32s (f, &r->bdbar);

        qemu_get_8s (f, &r->civ);

        qemu_get_8s (f, &r->lvi);

        qemu_get_be16s (f, &r->sr);

        qemu_get_be16s (f, &r->picb);

        qemu_get_8s (f, &r->piv);

        qemu_get_8s (f, &r->cr);

        qemu_get_be32s (f, &r->bd_valid);

        qemu_get_be32s (f, &r->bd.addr);

        qemu_get_be32s (f, &r->bd.ctl_len);

    }

    qemu_get_buffer (f, s->mixer_data, sizeof (s->mixer_data));

    qemu_get_buffer (f, active, sizeof (active));

#ifdef USE_MIXER

    record_select (s, mixer_load (s, AC97_Record_Select));

#define V_(a, b) set_volume (s, a, b, mixer_load (s, a))

    V_ (AC97_Master_Volume_Mute, AUD_MIXER_VOLUME);

    V_ (AC97_PCM_Out_Volume_Mute, AUD_MIXER_PCM);

    V_ (AC97_Line_In_Volume_Mute, AUD_MIXER_LINE_IN);

#undef V_

#endif

    reset_voices (s, active);

    s->bup_flag = 0;

    s->last_samp = 0;

    return 0;

}


void usb_test_hotplug(const char *hcd_id, const int port,

                      void (*port_check)(void))

{

    QDict *response;

    char  *cmd;

    cmd = g_strdup_printf("{'execute': 'device_add',"

                          " 'arguments': {"

                          "   'driver': 'usb-tablet',"

                          "   'port': '%d',"

                          "   'bus': '%s.0',"

                          "   'id': 'usbdev%d'"

                          "}}", port, hcd_id, port);

    response = qmp(cmd);

    g_free(cmd);

    g_assert(response);

    g_assert(!qdict_haskey(response, "error"));

    QDECREF(response);

    if (port_check) {

        port_check();

    }

    cmd = g_strdup_printf("{'execute': 'device_del',"

                           " 'arguments': {"

                           "   'id': 'usbdev%d'"

                           "}}", port);

    response = qmp(cmd);

    g_free(cmd);

    g_assert(response);

    g_assert(qdict_haskey(response, "event"));

    g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));

    QDECREF(response);

}


bool qemu_signalfd_available(void)

{

#ifdef CONFIG_SIGNALFD

    errno = 0;

    syscall(SYS_signalfd, -1, NULL, _NSIG / 8);

    return errno != ENOSYS;

#else

    return false;

#endif

}


static int xen_pt_byte_reg_write(XenPCIPassthroughState *s, XenPTReg *cfg_entry,

                                 uint8_t *val, uint8_t dev_value,

                                 uint8_t valid_mask)

{

    XenPTRegInfo *reg = cfg_entry->reg;

    uint8_t writable_mask = 0;

    uint8_t throughable_mask = get_throughable_mask(s, reg, valid_mask);

    /* modify emulate register */

    writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;

    cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);

    /* create value for writing to I/O device register */

    *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);

    return 0;

}


static void omap_update_display(void *opaque)

{

    struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;

    DisplaySurface *surface = qemu_console_surface(omap_lcd->con);

    draw_line_func draw_line;

    int size, height, first, last;

    int width, linesize, step, bpp, frame_offset;

    hwaddr frame_base;

    if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable ||

        !surface_bits_per_pixel(surface)) {

        return;

    }

    frame_offset = 0;

    if (omap_lcd->plm != 2) {

        cpu_physical_memory_read(omap_lcd->dma->phys_framebuffer[

                                  omap_lcd->dma->current_frame],

                                 (void *)omap_lcd->palette, 0x200);

        switch (omap_lcd->palette[0] >> 12 & 7) {

        case 3 ... 7:

            frame_offset += 0x200;

            break;

        default:

            frame_offset += 0x20;

        }

    }

    /* Colour depth */

    switch ((omap_lcd->palette[0] >> 12) & 7) {

    case 1:

        draw_line = draw_line_table2[surface_bits_per_pixel(surface)];

        bpp = 2;

        break;

    case 2:

        draw_line = draw_line_table4[surface_bits_per_pixel(surface)];

        bpp = 4;

        break;

    case 3:

        draw_line = draw_line_table8[surface_bits_per_pixel(surface)];

        bpp = 8;

        break;

    case 4 ... 7:

        if (!omap_lcd->tft)

            draw_line = draw_line_table12[surface_bits_per_pixel(surface)];

        else

            draw_line = draw_line_table16[surface_bits_per_pixel(surface)];

        bpp = 16;

        break;

    default:

        /* Unsupported at the moment.  */

        return;

    }

    /* Resolution */

    width = omap_lcd->width;

    if (width != surface_width(surface) ||

        omap_lcd->height != surface_height(surface)) {

        qemu_console_resize(omap_lcd->con,

                            omap_lcd->width, omap_lcd->height);

        surface = qemu_console_surface(omap_lcd->con);

        omap_lcd->invalidate = 1;

    }

    if (omap_lcd->dma->current_frame == 0)

        size = omap_lcd->dma->src_f1_bottom - omap_lcd->dma->src_f1_top;

    else

        size = omap_lcd->dma->src_f2_bottom - omap_lcd->dma->src_f2_top;

    if (frame_offset + ((width * omap_lcd->height * bpp) >> 3) > size + 2) {

        omap_lcd->sync_error = 1;

        omap_lcd_interrupts(omap_lcd);

        omap_lcd->enable = 0;

        return;

    }

    /* Content */

    frame_base = omap_lcd->dma->phys_framebuffer[

            omap_lcd->dma->current_frame] + frame_offset;

    omap_lcd->dma->condition |= 1 << omap_lcd->dma->current_frame;

    if (omap_lcd->dma->interrupts & 1)

        qemu_irq_raise(omap_lcd->dma->irq);

    if (omap_lcd->dma->dual)

        omap_lcd->dma->current_frame ^= 1;

    if (!surface_bits_per_pixel(surface)) {

        return;

    }

    first = 0;

    height = omap_lcd->height;

    if (omap_lcd->subpanel & (1 << 31)) {

        if (omap_lcd->subpanel & (1 << 29))

            first = (omap_lcd->subpanel >> 16) & 0x3ff;

        else

            height = (omap_lcd->subpanel >> 16) & 0x3ff;

        /* TODO: fill the rest of the panel with DPD */

    }

    step = width * bpp >> 3;

    linesize = surface_stride(surface);

    framebuffer_update_display(surface, omap_lcd->sysmem,

                               frame_base, width, height,

                               step, linesize, 0,

                               omap_lcd->invalidate,

                               draw_line, omap_lcd->palette,

                               &first, &last);

    if (first >= 0) {

        dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);

    }

    omap_lcd->invalidate = 0;

}


static void rcu_qtest(const char *test, int duration, int nreaders)

{

    int i;

    long long n_removed_local = 0;

    struct list_element *el, *prev_el;

    rcu_qtest_init();

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

        create_thread(rcu_q_reader);

    }

    create_thread(rcu_q_updater);

    rcu_qtest_run(duration, nreaders);

    QLIST_FOREACH_SAFE_RCU(prev_el, &Q_list_head, entry, el) {

        QLIST_REMOVE_RCU(prev_el, entry);

        call_rcu1(&prev_el->rcu, reclaim_list_el);

        n_removed_local++;

    }

    atomic_add(&n_nodes_removed, n_removed_local);

    synchronize_rcu();

    while (n_nodes_removed > n_reclaims) {

        g_usleep(100);

        synchronize_rcu();

    }

    if (g_test_in_charge) {

        g_assert_cmpint(n_nodes_removed, ==, n_reclaims);

    } else {

        printf("%s: %d readers; 1 updater; nodes read: "  \

               "%lld, nodes removed: %lld; nodes reclaimed: %lld\n",

               test, nthreadsrunning - 1, n_reads, n_nodes_removed, n_reclaims);

        exit(0);

    }

}


void qemu_chr_close(CharDriverState *chr)

{

    TAILQ_REMOVE(&chardevs, chr, next);

    if (chr->chr_close)

        chr->chr_close(chr);

    qemu_free(chr->filename);

    qemu_free(chr->label);

    qemu_free(chr);

}