static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)

{

    int32_t offset;

    int rs, rt, rd, sa;

    uint32_t op, op1, op2;

    int16_t imm;

    /* make sure instructions are on a word boundary */

    if (ctx->pc & 0x3) {

        env->CP0_BadVAddr = ctx->pc;

        generate_exception(ctx, EXCP_AdEL);

        return;

    }

    /* Handle blikely not taken case */

    if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {

        int l1 = gen_new_label();

        MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);

        tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);

        tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);

        gen_goto_tb(ctx, 1, ctx->pc + 4);

        gen_set_label(l1);

    }

    if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {

        tcg_gen_debug_insn_start(ctx->pc);

    }

    op = MASK_OP_MAJOR(ctx->opcode);

    rs = (ctx->opcode >> 21) & 0x1f;

    rt = (ctx->opcode >> 16) & 0x1f;

    rd = (ctx->opcode >> 11) & 0x1f;

    sa = (ctx->opcode >> 6) & 0x1f;

    imm = (int16_t)ctx->opcode;

    switch (op) {

    case OPC_SPECIAL:

        op1 = MASK_SPECIAL(ctx->opcode);

        switch (op1) {

        case OPC_SLL:          /* Shift with immediate */

        case OPC_SRA:

            gen_shift_imm(ctx, op1, rd, rt, sa);

            break;

        case OPC_SRL:

            switch ((ctx->opcode >> 21) & 0x1f) {

            case 1:

                /* rotr is decoded as srl on non-R2 CPUs */

                if (ctx->insn_flags & ISA_MIPS32R2) {

                    op1 = OPC_ROTR;

                }

                /* Fallthrough */

            case 0:

                gen_shift_imm(ctx, op1, rd, rt, sa);

                break;

            default:

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_MOVN:         /* Conditional move */

        case OPC_MOVZ:

            check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |

                                 INSN_LOONGSON2E | INSN_LOONGSON2F);

            gen_cond_move(ctx, op1, rd, rs, rt);

            break;

        case OPC_ADD ... OPC_SUBU:

            gen_arith(ctx, op1, rd, rs, rt);

            break;

        case OPC_SLLV:         /* Shifts */

        case OPC_SRAV:

            gen_shift(ctx, op1, rd, rs, rt);

            break;

        case OPC_SRLV:

            switch ((ctx->opcode >> 6) & 0x1f) {

            case 1:

                /* rotrv is decoded as srlv on non-R2 CPUs */

                if (ctx->insn_flags & ISA_MIPS32R2) {

                    op1 = OPC_ROTRV;

                }

                /* Fallthrough */

            case 0:

                gen_shift(ctx, op1, rd, rs, rt);

                break;

            default:

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_SLT:          /* Set on less than */

        case OPC_SLTU:

            gen_slt(ctx, op1, rd, rs, rt);

            break;

        case OPC_AND:          /* Logic*/

        case OPC_OR:

        case OPC_NOR:

        case OPC_XOR:

            gen_logic(ctx, op1, rd, rs, rt);

            break;

        case OPC_MULT ... OPC_DIVU:

            if (sa) {

                check_insn(ctx, INSN_VR54XX);

                op1 = MASK_MUL_VR54XX(ctx->opcode);

                gen_mul_vr54xx(ctx, op1, rd, rs, rt);

            } else

                gen_muldiv(ctx, op1, rs, rt);

            break;

        case OPC_JR ... OPC_JALR:

            gen_compute_branch(ctx, op1, 4, rs, rd, sa);

            *is_branch = 1;

            break;

        case OPC_TGE ... OPC_TEQ: /* Traps */

        case OPC_TNE:

            gen_trap(ctx, op1, rs, rt, -1);

            break;

        case OPC_MFHI:          /* Move from HI/LO */

        case OPC_MFLO:

            gen_HILO(ctx, op1, rd);

            break;

        case OPC_MTHI:

        case OPC_MTLO:          /* Move to HI/LO */

            gen_HILO(ctx, op1, rs);

            break;

        case OPC_PMON:          /* Pmon entry point, also R4010 selsl */

#ifdef MIPS_STRICT_STANDARD

            MIPS_INVAL("PMON / selsl");

            generate_exception(ctx, EXCP_RI);

#else

            gen_helper_0e0i(pmon, sa);

#endif

            break;

        case OPC_SYSCALL:

            generate_exception(ctx, EXCP_SYSCALL);

            ctx->bstate = BS_STOP;

            break;

        case OPC_BREAK:

            generate_exception(ctx, EXCP_BREAK);

            break;

        case OPC_SPIM:

#ifdef MIPS_STRICT_STANDARD

            MIPS_INVAL("SPIM");

            generate_exception(ctx, EXCP_RI);

#else

           /* Implemented as RI exception for now. */

            MIPS_INVAL("spim (unofficial)");

            generate_exception(ctx, EXCP_RI);

#endif

            break;

        case OPC_SYNC:

            /* Treat as NOP. */

            break;

        case OPC_MOVCI:

            check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);

            if (env->CP0_Config1 & (1 << CP0C1_FP)) {

                check_cp1_enabled(ctx);

                gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,

                          (ctx->opcode >> 16) & 1);

            } else {

                generate_exception_err(ctx, EXCP_CpU, 1);

            }

            break;

#if defined(TARGET_MIPS64)

       /* MIPS64 specific opcodes */

        case OPC_DSLL:

        case OPC_DSRA:

        case OPC_DSLL32:

        case OPC_DSRA32:

            check_insn(ctx, ISA_MIPS3);

            check_mips_64(ctx);

            gen_shift_imm(ctx, op1, rd, rt, sa);

            break;

        case OPC_DSRL:

            switch ((ctx->opcode >> 21) & 0x1f) {

            case 1:

                /* drotr is decoded as dsrl on non-R2 CPUs */

                if (ctx->insn_flags & ISA_MIPS32R2) {

                    op1 = OPC_DROTR;

                }

                /* Fallthrough */

            case 0:

                check_insn(ctx, ISA_MIPS3);

                check_mips_64(ctx);

                gen_shift_imm(ctx, op1, rd, rt, sa);

                break;

            default:

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_DSRL32:

            switch ((ctx->opcode >> 21) & 0x1f) {

            case 1:

                /* drotr32 is decoded as dsrl32 on non-R2 CPUs */

                if (ctx->insn_flags & ISA_MIPS32R2) {

                    op1 = OPC_DROTR32;

                }

                /* Fallthrough */

            case 0:

                check_insn(ctx, ISA_MIPS3);

                check_mips_64(ctx);

                gen_shift_imm(ctx, op1, rd, rt, sa);

                break;

            default:

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_DADD ... OPC_DSUBU:

            check_insn(ctx, ISA_MIPS3);

            check_mips_64(ctx);

            gen_arith(ctx, op1, rd, rs, rt);

            break;

        case OPC_DSLLV:

        case OPC_DSRAV:

            check_insn(ctx, ISA_MIPS3);

            check_mips_64(ctx);

            gen_shift(ctx, op1, rd, rs, rt);

            break;

        case OPC_DSRLV:

            switch ((ctx->opcode >> 6) & 0x1f) {

            case 1:

                /* drotrv is decoded as dsrlv on non-R2 CPUs */

                if (ctx->insn_flags & ISA_MIPS32R2) {

                    op1 = OPC_DROTRV;

                }

                /* Fallthrough */

            case 0:

                check_insn(ctx, ISA_MIPS3);

                check_mips_64(ctx);

                gen_shift(ctx, op1, rd, rs, rt);

                break;

            default:

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_DMULT ... OPC_DDIVU:

            check_insn(ctx, ISA_MIPS3);

            check_mips_64(ctx);

            gen_muldiv(ctx, op1, rs, rt);

            break;

#endif

        default:            /* Invalid */

            MIPS_INVAL("special");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

    case OPC_SPECIAL2:

        op1 = MASK_SPECIAL2(ctx->opcode);

        switch (op1) {

        case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */

        case OPC_MSUB ... OPC_MSUBU:

            check_insn(ctx, ISA_MIPS32);

            gen_muldiv(ctx, op1, rs, rt);

            break;

        case OPC_MUL:

            gen_arith(ctx, op1, rd, rs, rt);

            break;

        case OPC_CLO:

        case OPC_CLZ:

            check_insn(ctx, ISA_MIPS32);

            gen_cl(ctx, op1, rd, rs);

            break;

        case OPC_SDBBP:

            /* XXX: not clear which exception should be raised

             *      when in debug mode...

             */

            check_insn(ctx, ISA_MIPS32);

            if (!(ctx->hflags & MIPS_HFLAG_DM)) {

                generate_exception(ctx, EXCP_DBp);

            } else {

                generate_exception(ctx, EXCP_DBp);

            }

            /* Treat as NOP. */

            break;

        case OPC_DIV_G_2F:

        case OPC_DIVU_G_2F:

        case OPC_MULT_G_2F:

        case OPC_MULTU_G_2F:

        case OPC_MOD_G_2F:

        case OPC_MODU_G_2F:

            check_insn(ctx, INSN_LOONGSON2F);

            gen_loongson_integer(ctx, op1, rd, rs, rt);

            break;

#if defined(TARGET_MIPS64)

        case OPC_DCLO:

        case OPC_DCLZ:

            check_insn(ctx, ISA_MIPS64);

            check_mips_64(ctx);

            gen_cl(ctx, op1, rd, rs);

            break;

        case OPC_DMULT_G_2F:

        case OPC_DMULTU_G_2F:

        case OPC_DDIV_G_2F:

        case OPC_DDIVU_G_2F:

        case OPC_DMOD_G_2F:

        case OPC_DMODU_G_2F:

            check_insn(ctx, INSN_LOONGSON2F);

            gen_loongson_integer(ctx, op1, rd, rs, rt);

            break;

#endif

        default:            /* Invalid */

            MIPS_INVAL("special2");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

    case OPC_SPECIAL3:

        op1 = MASK_SPECIAL3(ctx->opcode);

        switch (op1) {

        case OPC_EXT:

        case OPC_INS:

            check_insn(ctx, ISA_MIPS32R2);

            gen_bitops(ctx, op1, rt, rs, sa, rd);

            break;

        case OPC_BSHFL:

            check_insn(ctx, ISA_MIPS32R2);

            op2 = MASK_BSHFL(ctx->opcode);

            gen_bshfl(ctx, op2, rt, rd);

            break;

        case OPC_RDHWR:

            gen_rdhwr(ctx, rt, rd);

            break;

        case OPC_FORK:

            check_insn(ctx, ASE_MT);

            {

                TCGv t0 = tcg_temp_new();

                TCGv t1 = tcg_temp_new();

                gen_load_gpr(t0, rt);

                gen_load_gpr(t1, rs);

                gen_helper_fork(t0, t1);

                tcg_temp_free(t0);

                tcg_temp_free(t1);

            }

            break;

        case OPC_YIELD:

            check_insn(ctx, ASE_MT);

            {

                TCGv t0 = tcg_temp_new();

                save_cpu_state(ctx, 1);

                gen_load_gpr(t0, rs);

                gen_helper_yield(t0, cpu_env, t0);

                gen_store_gpr(t0, rd);

                tcg_temp_free(t0);

            }

            break;

        case OPC_DIV_G_2E ... OPC_DIVU_G_2E:

        case OPC_MOD_G_2E ... OPC_MODU_G_2E:

        case OPC_MULT_G_2E ... OPC_MULTU_G_2E:

        /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have

         * the same mask and op1. */

            if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {

                op2 = MASK_ADDUH_QB(ctx->opcode);

                switch (op2) {

                case OPC_ADDUH_QB:

                case OPC_ADDUH_R_QB:

                case OPC_ADDQH_PH:

                case OPC_ADDQH_R_PH:

                case OPC_ADDQH_W:

                case OPC_ADDQH_R_W:

                case OPC_SUBUH_QB:

                case OPC_SUBUH_R_QB:

                case OPC_SUBQH_PH:

                case OPC_SUBQH_R_PH:

                case OPC_SUBQH_W:

                case OPC_SUBQH_R_W:

                    gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                    break;

                case OPC_MUL_PH:

                case OPC_MUL_S_PH:

                case OPC_MULQ_S_W:

                case OPC_MULQ_RS_W:

                    gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);

                    break;

                default:

                    MIPS_INVAL("MASK ADDUH.QB");

                    generate_exception(ctx, EXCP_RI);

                    break;

                }

            } else if (ctx->insn_flags & INSN_LOONGSON2E) {

                gen_loongson_integer(ctx, op1, rd, rs, rt);

            } else {

                generate_exception(ctx, EXCP_RI);

            }

            break;

        case OPC_LX_DSP:

            op2 = MASK_LX(ctx->opcode);

            switch (op2) {

#if defined(TARGET_MIPS64)

            case OPC_LDX:

#endif

            case OPC_LBUX:

            case OPC_LHX:

            case OPC_LWX:

                gen_mipsdsp_ld(ctx, op2, rd, rs, rt);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK LX");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_ABSQ_S_PH_DSP:

            op2 = MASK_ABSQ_S_PH(ctx->opcode);

            switch (op2) {

            case OPC_ABSQ_S_QB:

            case OPC_ABSQ_S_PH:

            case OPC_ABSQ_S_W:

            case OPC_PRECEQ_W_PHL:

            case OPC_PRECEQ_W_PHR:

            case OPC_PRECEQU_PH_QBL:

            case OPC_PRECEQU_PH_QBR:

            case OPC_PRECEQU_PH_QBLA:

            case OPC_PRECEQU_PH_QBRA:

            case OPC_PRECEU_PH_QBL:

            case OPC_PRECEU_PH_QBR:

            case OPC_PRECEU_PH_QBLA:

            case OPC_PRECEU_PH_QBRA:

                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                break;

            case OPC_BITREV:

            case OPC_REPL_QB:

            case OPC_REPLV_QB:

            case OPC_REPL_PH:

            case OPC_REPLV_PH:

                gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);

                break;

            default:

                MIPS_INVAL("MASK ABSQ_S.PH");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_ADDU_QB_DSP:

            op2 = MASK_ADDU_QB(ctx->opcode);

            switch (op2) {

            case OPC_ADDQ_PH:

            case OPC_ADDQ_S_PH:

            case OPC_ADDQ_S_W:

            case OPC_ADDU_QB:

            case OPC_ADDU_S_QB:

            case OPC_ADDU_PH:

            case OPC_ADDU_S_PH:

            case OPC_SUBQ_PH:

            case OPC_SUBQ_S_PH:

            case OPC_SUBQ_S_W:

            case OPC_SUBU_QB:

            case OPC_SUBU_S_QB:

            case OPC_SUBU_PH:

            case OPC_SUBU_S_PH:

            case OPC_ADDSC:

            case OPC_ADDWC:

            case OPC_MODSUB:

            case OPC_RADDU_W_QB:

                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                break;

            case OPC_MULEU_S_PH_QBL:

            case OPC_MULEU_S_PH_QBR:

            case OPC_MULQ_RS_PH:

            case OPC_MULEQ_S_W_PHL:

            case OPC_MULEQ_S_W_PHR:

            case OPC_MULQ_S_PH:

                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK ADDU.QB");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_CMPU_EQ_QB_DSP:

            op2 = MASK_CMPU_EQ_QB(ctx->opcode);

            switch (op2) {

            case OPC_PRECR_SRA_PH_W:

            case OPC_PRECR_SRA_R_PH_W:

                gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);

                break;

            case OPC_PRECR_QB_PH:

            case OPC_PRECRQ_QB_PH:

            case OPC_PRECRQ_PH_W:

            case OPC_PRECRQ_RS_PH_W:

            case OPC_PRECRQU_S_QB_PH:

                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                break;

            case OPC_CMPU_EQ_QB:

            case OPC_CMPU_LT_QB:

            case OPC_CMPU_LE_QB:

            case OPC_CMP_EQ_PH:

            case OPC_CMP_LT_PH:

            case OPC_CMP_LE_PH:

                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);

                break;

            case OPC_CMPGU_EQ_QB:

            case OPC_CMPGU_LT_QB:

            case OPC_CMPGU_LE_QB:

            case OPC_CMPGDU_EQ_QB:

            case OPC_CMPGDU_LT_QB:

            case OPC_CMPGDU_LE_QB:

            case OPC_PICK_QB:

            case OPC_PICK_PH:

            case OPC_PACKRL_PH:

                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK CMPU.EQ.QB");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_SHLL_QB_DSP:

            gen_mipsdsp_shift(ctx, op1, rd, rs, rt);

            break;

        case OPC_DPA_W_PH_DSP:

            op2 = MASK_DPA_W_PH(ctx->opcode);

            switch (op2) {

            case OPC_DPAU_H_QBL:

            case OPC_DPAU_H_QBR:

            case OPC_DPSU_H_QBL:

            case OPC_DPSU_H_QBR:

            case OPC_DPA_W_PH:

            case OPC_DPAX_W_PH:

            case OPC_DPAQ_S_W_PH:

            case OPC_DPAQX_S_W_PH:

            case OPC_DPAQX_SA_W_PH:

            case OPC_DPS_W_PH:

            case OPC_DPSX_W_PH:

            case OPC_DPSQ_S_W_PH:

            case OPC_DPSQX_S_W_PH:

            case OPC_DPSQX_SA_W_PH:

            case OPC_MULSAQ_S_W_PH:

            case OPC_DPAQ_SA_L_W:

            case OPC_DPSQ_SA_L_W:

            case OPC_MAQ_S_W_PHL:

            case OPC_MAQ_S_W_PHR:

            case OPC_MAQ_SA_W_PHL:

            case OPC_MAQ_SA_W_PHR:

            case OPC_MULSA_W_PH:

                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK DPAW.PH");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_INSV_DSP:

            op2 = MASK_INSV(ctx->opcode);

            switch (op2) {

            case OPC_INSV:

                check_dsp(ctx);

                {

                    TCGv t0, t1;

                    if (rt == 0) {

                        MIPS_DEBUG("NOP");

                        break;

                    }

                    t0 = tcg_temp_new();

                    t1 = tcg_temp_new();

                    gen_load_gpr(t0, rt);

                    gen_load_gpr(t1, rs);

                    gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);

                    tcg_temp_free(t0);

                    tcg_temp_free(t1);

                    break;

                }

            default:            /* Invalid */

                MIPS_INVAL("MASK INSV");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_APPEND_DSP:

            check_dspr2(ctx);

            op2 = MASK_APPEND(ctx->opcode);

            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);

            break;

        case OPC_EXTR_W_DSP:

            op2 = MASK_EXTR_W(ctx->opcode);

            switch (op2) {

            case OPC_EXTR_W:

            case OPC_EXTR_R_W:

            case OPC_EXTR_RS_W:

            case OPC_EXTR_S_H:

            case OPC_EXTRV_S_H:

            case OPC_EXTRV_W:

            case OPC_EXTRV_R_W:

            case OPC_EXTRV_RS_W:

            case OPC_EXTP:

            case OPC_EXTPV:

            case OPC_EXTPDP:

            case OPC_EXTPDPV:

                gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);

                break;

            case OPC_RDDSP:

                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);

                break;

            case OPC_SHILO:

            case OPC_SHILOV:

            case OPC_MTHLIP:

            case OPC_WRDSP:

                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK EXTR.W");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

#if defined(TARGET_MIPS64)

        case OPC_DEXTM ... OPC_DEXT:

        case OPC_DINSM ... OPC_DINS:

            check_insn(ctx, ISA_MIPS64R2);

            check_mips_64(ctx);

            gen_bitops(ctx, op1, rt, rs, sa, rd);

            break;

        case OPC_DBSHFL:

            check_insn(ctx, ISA_MIPS64R2);

            check_mips_64(ctx);

            op2 = MASK_DBSHFL(ctx->opcode);

            gen_bshfl(ctx, op2, rt, rd);

            break;

        case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:

        case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:

        case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:

            check_insn(ctx, INSN_LOONGSON2E);

            gen_loongson_integer(ctx, op1, rd, rs, rt);

            break;

        case OPC_ABSQ_S_QH_DSP:

            op2 = MASK_ABSQ_S_QH(ctx->opcode);

            switch (op2) {

            case OPC_PRECEQ_L_PWL:

            case OPC_PRECEQ_L_PWR:

            case OPC_PRECEQ_PW_QHL:

            case OPC_PRECEQ_PW_QHR:

            case OPC_PRECEQ_PW_QHLA:

            case OPC_PRECEQ_PW_QHRA:

            case OPC_PRECEQU_QH_OBL:

            case OPC_PRECEQU_QH_OBR:

            case OPC_PRECEQU_QH_OBLA:

            case OPC_PRECEQU_QH_OBRA:

            case OPC_PRECEU_QH_OBL:

            case OPC_PRECEU_QH_OBR:

            case OPC_PRECEU_QH_OBLA:

            case OPC_PRECEU_QH_OBRA:

            case OPC_ABSQ_S_OB:

            case OPC_ABSQ_S_PW:

            case OPC_ABSQ_S_QH:

                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                break;

            case OPC_REPL_OB:

            case OPC_REPL_PW:

            case OPC_REPL_QH:

            case OPC_REPLV_OB:

            case OPC_REPLV_PW:

            case OPC_REPLV_QH:

                gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK ABSQ_S.QH");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_ADDU_OB_DSP:

            op2 = MASK_ADDU_OB(ctx->opcode);

            switch (op2) {

            case OPC_RADDU_L_OB:

            case OPC_SUBQ_PW:

            case OPC_SUBQ_S_PW:

            case OPC_SUBQ_QH:

            case OPC_SUBQ_S_QH:

            case OPC_SUBU_OB:

            case OPC_SUBU_S_OB:

            case OPC_SUBU_QH:

            case OPC_SUBU_S_QH:

            case OPC_SUBUH_OB:

            case OPC_SUBUH_R_OB:

            case OPC_ADDQ_PW:

            case OPC_ADDQ_S_PW:

            case OPC_ADDQ_QH:

            case OPC_ADDQ_S_QH:

            case OPC_ADDU_OB:

            case OPC_ADDU_S_OB:

            case OPC_ADDU_QH:

            case OPC_ADDU_S_QH:

            case OPC_ADDUH_OB:

            case OPC_ADDUH_R_OB:

                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                break;

            case OPC_MULEQ_S_PW_QHL:

            case OPC_MULEQ_S_PW_QHR:

            case OPC_MULEU_S_QH_OBL:

            case OPC_MULEU_S_QH_OBR:

            case OPC_MULQ_RS_QH:

                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK ADDU.OB");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_CMPU_EQ_OB_DSP:

            op2 = MASK_CMPU_EQ_OB(ctx->opcode);

            switch (op2) {

            case OPC_PRECR_SRA_QH_PW:

            case OPC_PRECR_SRA_R_QH_PW:

                /* Return value is rt. */

                gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);

                break;

            case OPC_PRECR_OB_QH:

            case OPC_PRECRQ_OB_QH:

            case OPC_PRECRQ_PW_L:

            case OPC_PRECRQ_QH_PW:

            case OPC_PRECRQ_RS_QH_PW:

            case OPC_PRECRQU_S_OB_QH:

                gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);

                break;

            case OPC_CMPU_EQ_OB:

            case OPC_CMPU_LT_OB:

            case OPC_CMPU_LE_OB:

            case OPC_CMP_EQ_QH:

            case OPC_CMP_LT_QH:

            case OPC_CMP_LE_QH:

            case OPC_CMP_EQ_PW:

            case OPC_CMP_LT_PW:

            case OPC_CMP_LE_PW:

                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);

                break;

            case OPC_CMPGDU_EQ_OB:

            case OPC_CMPGDU_LT_OB:

            case OPC_CMPGDU_LE_OB:

            case OPC_CMPGU_EQ_OB:

            case OPC_CMPGU_LT_OB:

            case OPC_CMPGU_LE_OB:

            case OPC_PACKRL_PW:

            case OPC_PICK_OB:

            case OPC_PICK_PW:

            case OPC_PICK_QH:

                gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK CMPU_EQ.OB");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_DAPPEND_DSP:

            check_dspr2(ctx);

            op2 = MASK_DAPPEND(ctx->opcode);

            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);

            break;

        case OPC_DEXTR_W_DSP:

            op2 = MASK_DEXTR_W(ctx->opcode);

            switch (op2) {

            case OPC_DEXTP:

            case OPC_DEXTPDP:

            case OPC_DEXTPDPV:

            case OPC_DEXTPV:

            case OPC_DEXTR_L:

            case OPC_DEXTR_R_L:

            case OPC_DEXTR_RS_L:

            case OPC_DEXTR_W:

            case OPC_DEXTR_R_W:

            case OPC_DEXTR_RS_W:

            case OPC_DEXTR_S_H:

            case OPC_DEXTRV_L:

            case OPC_DEXTRV_R_L:

            case OPC_DEXTRV_RS_L:

            case OPC_DEXTRV_S_H:

            case OPC_DEXTRV_W:

            case OPC_DEXTRV_R_W:

            case OPC_DEXTRV_RS_W:

                gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);

                break;

            case OPC_DMTHLIP:

            case OPC_DSHILO:

            case OPC_DSHILOV:

                gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK EXTR.W");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_DPAQ_W_QH_DSP:

            op2 = MASK_DPAQ_W_QH(ctx->opcode);

            switch (op2) {

            case OPC_DPAU_H_OBL:

            case OPC_DPAU_H_OBR:

            case OPC_DPSU_H_OBL:

            case OPC_DPSU_H_OBR:

            case OPC_DPA_W_QH:

            case OPC_DPAQ_S_W_QH:

            case OPC_DPS_W_QH:

            case OPC_DPSQ_S_W_QH:

            case OPC_MULSAQ_S_W_QH:

            case OPC_DPAQ_SA_L_PW:

            case OPC_DPSQ_SA_L_PW:

            case OPC_MULSAQ_S_L_PW:

                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);

                break;

            case OPC_MAQ_S_W_QHLL:

            case OPC_MAQ_S_W_QHLR:

            case OPC_MAQ_S_W_QHRL:

            case OPC_MAQ_S_W_QHRR:

            case OPC_MAQ_SA_W_QHLL:

            case OPC_MAQ_SA_W_QHLR:

            case OPC_MAQ_SA_W_QHRL:

            case OPC_MAQ_SA_W_QHRR:

            case OPC_MAQ_S_L_PWL:

            case OPC_MAQ_S_L_PWR:

            case OPC_DMADD:

            case OPC_DMADDU:

            case OPC_DMSUB:

            case OPC_DMSUBU:

                gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);

                break;

            default:            /* Invalid */

                MIPS_INVAL("MASK DPAQ.W.QH");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_DINSV_DSP:

            op2 = MASK_INSV(ctx->opcode);

            switch (op2) {

            case OPC_DINSV:

                {

                    TCGv t0, t1;

                    if (rt == 0) {

                        MIPS_DEBUG("NOP");

                        break;

                    }

                    check_dsp(ctx);

                    t0 = tcg_temp_new();

                    t1 = tcg_temp_new();

                    gen_load_gpr(t0, rt);

                    gen_load_gpr(t1, rs);

                    gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);

                    break;

                }

            default:            /* Invalid */

                MIPS_INVAL("MASK DINSV");

                generate_exception(ctx, EXCP_RI);

                break;

            }

            break;

        case OPC_SHLL_OB_DSP:

            gen_mipsdsp_shift(ctx, op1, rd, rs, rt);

            break;

#endif

        default:            /* Invalid */

            MIPS_INVAL("special3");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

    case OPC_REGIMM:

        op1 = MASK_REGIMM(ctx->opcode);

        switch (op1) {

        case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */

        case OPC_BLTZAL ... OPC_BGEZALL:

            gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);

            *is_branch = 1;

            break;

        case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */

        case OPC_TNEI:

            gen_trap(ctx, op1, rs, -1, imm);

            break;

        case OPC_SYNCI:

            check_insn(ctx, ISA_MIPS32R2);

            /* Treat as NOP. */

            break;

        case OPC_BPOSGE32:    /* MIPS DSP branch */

#if defined(TARGET_MIPS64)

        case OPC_BPOSGE64:

#endif

            check_dsp(ctx);

            gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);

            *is_branch = 1;

            break;

        default:            /* Invalid */

            MIPS_INVAL("regimm");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

    case OPC_CP0:

        check_cp0_enabled(ctx);

        op1 = MASK_CP0(ctx->opcode);

        switch (op1) {

        case OPC_MFC0:

        case OPC_MTC0:

        case OPC_MFTR:

        case OPC_MTTR:

#if defined(TARGET_MIPS64)

        case OPC_DMFC0:

        case OPC_DMTC0:

#endif

#ifndef CONFIG_USER_ONLY

            gen_cp0(env, ctx, op1, rt, rd);

#endif /* !CONFIG_USER_ONLY */

            break;

        case OPC_C0_FIRST ... OPC_C0_LAST:

#ifndef CONFIG_USER_ONLY

            gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);

#endif /* !CONFIG_USER_ONLY */

            break;

        case OPC_MFMC0:

#ifndef CONFIG_USER_ONLY

            {

                TCGv t0 = tcg_temp_new();

                op2 = MASK_MFMC0(ctx->opcode);

                switch (op2) {

                case OPC_DMT:

                    check_insn(ctx, ASE_MT);

                    gen_helper_dmt(t0);

                    gen_store_gpr(t0, rt);

                    break;

                case OPC_EMT:

                    check_insn(ctx, ASE_MT);

                    gen_helper_emt(t0);

                    gen_store_gpr(t0, rt);

                    break;

                case OPC_DVPE:

                    check_insn(ctx, ASE_MT);

                    gen_helper_dvpe(t0, cpu_env);

                    gen_store_gpr(t0, rt);

                    break;

                case OPC_EVPE:

                    check_insn(ctx, ASE_MT);

                    gen_helper_evpe(t0, cpu_env);

                    gen_store_gpr(t0, rt);

                    break;

                case OPC_DI:

                    check_insn(ctx, ISA_MIPS32R2);

                    save_cpu_state(ctx, 1);

                    gen_helper_di(t0, cpu_env);

                    gen_store_gpr(t0, rt);

                    /* Stop translation as we may have switched the execution mode */

                    ctx->bstate = BS_STOP;

                    break;

                case OPC_EI:

                    check_insn(ctx, ISA_MIPS32R2);

                    save_cpu_state(ctx, 1);

                    gen_helper_ei(t0, cpu_env);

                    gen_store_gpr(t0, rt);

                    /* Stop translation as we may have switched the execution mode */

                    ctx->bstate = BS_STOP;

                    break;

                default:            /* Invalid */

                    MIPS_INVAL("mfmc0");

                    generate_exception(ctx, EXCP_RI);

                    break;

                }

                tcg_temp_free(t0);

            }

#endif /* !CONFIG_USER_ONLY */

            break;

        case OPC_RDPGPR:

            check_insn(ctx, ISA_MIPS32R2);

            gen_load_srsgpr(rt, rd);

            break;

        case OPC_WRPGPR:

            check_insn(ctx, ISA_MIPS32R2);

            gen_store_srsgpr(rt, rd);

            break;

        default:

            MIPS_INVAL("cp0");

            generate_exception(ctx, EXCP_RI);

            break;

        }

        break;

    case OPC_ADDI: /* Arithmetic with immediate opcode */

    case OPC_ADDIU:

         gen_arith_imm(ctx, op, rt, rs, imm);

         break;

    case OPC_SLTI: /* Set on less than with immediate opcode */

    case OPC_SLTIU:

         gen_slt_imm(ctx, op, rt, rs, imm);

         break;

    case OPC_ANDI: /* Arithmetic with immediate opcode */

    case OPC_LUI:

    case OPC_ORI:

    case OPC_XORI:

         gen_logic_imm(ctx, op, rt, rs, imm);

         break;

    case OPC_J ... OPC_JAL: /* Jump */

         offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;

         gen_compute_branch(ctx, op, 4, rs, rt, offset);

         *is_branch = 1;

         break;

    case OPC_BEQ ... OPC_BGTZ: /* Branch */

    case OPC_BEQL ... OPC_BGTZL:

         gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);

         *is_branch = 1;

         break;

    case OPC_LB ... OPC_LWR: /* Load and stores */

    case OPC_LL:

         gen_ld(ctx, op, rt, rs, imm);

         break;

    case OPC_SB ... OPC_SW:

    case OPC_SWR:

         gen_st(ctx, op, rt, rs, imm);

         break;

    case OPC_SC:

         gen_st_cond(ctx, op, rt, rs, imm);

         break;

    case OPC_CACHE:

        check_cp0_enabled(ctx);

        check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);

        /* Treat as NOP. */

        break;

    case OPC_PREF:

        check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);

        /* Treat as NOP. */

        break;

    /* Floating point (COP1). */

    case OPC_LWC1:

    case OPC_LDC1:

    case OPC_SWC1:

    case OPC_SDC1:

        gen_cop1_ldst(env, ctx, op, rt, rs, imm);

        break;

    case OPC_CP1:

        if (env->CP0_Config1 & (1 << CP0C1_FP)) {

            check_cp1_enabled(ctx);

            op1 = MASK_CP1(ctx->opcode);

            switch (op1) {

            case OPC_MFHC1:

            case OPC_MTHC1:

                check_insn(ctx, ISA_MIPS32R2);

            case OPC_MFC1:

            case OPC_CFC1:

            case OPC_MTC1:

            case OPC_CTC1:

                gen_cp1(ctx, op1, rt, rd);

                break;

#if defined(TARGET_MIPS64)

            case OPC_DMFC1:

            case OPC_DMTC1:

                check_insn(ctx, ISA_MIPS3);

                gen_cp1(ctx, op1, rt, rd);

                break;

#endif

            case OPC_BC1ANY2:

            case OPC_BC1ANY4:

                check_cop1x(ctx);

                check_insn(ctx, ASE_MIPS3D);

                /* fall through */

            case OPC_BC1:

                gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),

                                    (rt >> 2) & 0x7, imm << 2);

                *is_branch = 1;

                break;

            case OPC_S_FMT:

            case OPC_D_FMT:

            case OPC_W_FMT:

            case OPC_L_FMT:

            case OPC_PS_FMT:

                gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,

                           (imm >> 8) & 0x7);

                break;

            default:

                MIPS_INVAL("cp1");

                generate_exception (ctx, EXCP_RI);

                break;

            }

        } else {

            generate_exception_err(ctx, EXCP_CpU, 1);

        }

        break;

    /* COP2.  */

    case OPC_LWC2:

    case OPC_LDC2:

    case OPC_SWC2:

    case OPC_SDC2:

        /* COP2: Not implemented. */

        generate_exception_err(ctx, EXCP_CpU, 2);

        break;

    case OPC_CP2:

        check_insn(ctx, INSN_LOONGSON2F);

        /* Note that these instructions use different fields.  */

        gen_loongson_multimedia(ctx, sa, rd, rt);

        break;

    case OPC_CP3:

        if (env->CP0_Config1 & (1 << CP0C1_FP)) {

            check_cp1_enabled(ctx);

            op1 = MASK_CP3(ctx->opcode);

            switch (op1) {

            case OPC_LWXC1:

            case OPC_LDXC1:

            case OPC_LUXC1:

            case OPC_SWXC1:

            case OPC_SDXC1:

            case OPC_SUXC1:

                gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);

                break;

            case OPC_PREFX:

                /* Treat as NOP. */

                break;

            case OPC_ALNV_PS:

            case OPC_MADD_S:

            case OPC_MADD_D:

            case OPC_MADD_PS:

            case OPC_MSUB_S:

            case OPC_MSUB_D:

            case OPC_MSUB_PS:

            case OPC_NMADD_S:

            case OPC_NMADD_D:

            case OPC_NMADD_PS:

            case OPC_NMSUB_S:

            case OPC_NMSUB_D:

            case OPC_NMSUB_PS:

                gen_flt3_arith(ctx, op1, sa, rs, rd, rt);

                break;

            default:

                MIPS_INVAL("cp3");

                generate_exception (ctx, EXCP_RI);

                break;

            }

        } else {

            generate_exception_err(ctx, EXCP_CpU, 1);

        }

        break;

#if defined(TARGET_MIPS64)

    /* MIPS64 opcodes */

    case OPC_LWU:

    case OPC_LDL ... OPC_LDR:

    case OPC_LLD:

    case OPC_LD:

        check_insn(ctx, ISA_MIPS3);

        check_mips_64(ctx);

        gen_ld(ctx, op, rt, rs, imm);

        break;

    case OPC_SDL ... OPC_SDR:

    case OPC_SD:

        check_insn(ctx, ISA_MIPS3);

        check_mips_64(ctx);

        gen_st(ctx, op, rt, rs, imm);

        break;

    case OPC_SCD:

        check_insn(ctx, ISA_MIPS3);

        check_mips_64(ctx);

        gen_st_cond(ctx, op, rt, rs, imm);

        break;

    case OPC_DADDI:

    case OPC_DADDIU:

        check_insn(ctx, ISA_MIPS3);

        check_mips_64(ctx);

        gen_arith_imm(ctx, op, rt, rs, imm);

        break;

#endif

    case OPC_JALX:

        check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);

        offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;

        gen_compute_branch(ctx, op, 4, rs, rt, offset);

        *is_branch = 1;

        break;

    case OPC_MDMX:

        check_insn(ctx, ASE_MDMX);

        /* MDMX: Not implemented. */

    default:            /* Invalid */

        MIPS_INVAL("major opcode");

        generate_exception(ctx, EXCP_RI);

        break;

    }

}


static void stream_complete(BlockJob *job, void *opaque)

{

    StreamBlockJob *s = container_of(job, StreamBlockJob, common);

    StreamCompleteData *data = opaque;

    BlockDriverState *bs = blk_bs(job->blk);

    BlockDriverState *base = s->base;

    Error *local_err = NULL;

    if (!block_job_is_cancelled(&s->common) && data->reached_end &&

        data->ret == 0) {

        const char *base_id = NULL, *base_fmt = NULL;

        if (base) {

            base_id = s->backing_file_str;

            if (base->drv) {

                base_fmt = base->drv->format_name;

            }

        }

        data->ret = bdrv_change_backing_file(bs, base_id, base_fmt);

        bdrv_set_backing_hd(bs, base, &local_err);

        if (local_err) {

            error_report_err(local_err);

            data->ret = -EPERM;

            goto out;

        }

    }

out:

    /* Reopen the image back in read-only mode if necessary */

    if (s->bs_flags != bdrv_get_flags(bs)) {

        /* Give up write permissions before making it read-only */

        blk_set_perm(job->blk, 0, BLK_PERM_ALL, &error_abort);

        bdrv_reopen(bs, s->bs_flags, NULL);

    }

    g_free(s->backing_file_str);

    block_job_completed(&s->common, data->ret);

    g_free(data);

}


static void img_snapshot(int argc, char **argv)

{

    BlockDriverState *bs;

    QEMUSnapshotInfo sn;

    char *filename, *snapshot_name = NULL;

    int c, ret;

    int action = 0;

    qemu_timeval tv;

    /* Parse commandline parameters */

    for(;;) {

        c = getopt(argc, argv, "la:c:d:h");

        if (c == -1)

            break;

        switch(c) {

        case 'h':

            help();

            return;

        case 'l':

            if (action) {

                help();

                return;

            }

            action = SNAPSHOT_LIST;

            break;

        case 'a':

            if (action) {

                help();

                return;

            }

            action = SNAPSHOT_APPLY;

            snapshot_name = optarg;

            break;

        case 'c':

            if (action) {

                help();

                return;

            }

            action = SNAPSHOT_CREATE;

            snapshot_name = optarg;

            break;

        case 'd':

            if (action) {

                help();

                return;

            }

            action = SNAPSHOT_DELETE;

            snapshot_name = optarg;

            break;

        }

    }

    if (optind >= argc)

        help();

    filename = argv[optind++];

    /* Open the image */

    bs = bdrv_new("");

    if (!bs)

        error("Not enough memory");

    if (bdrv_open2(bs, filename, 0, NULL) < 0) {

        error("Could not open '%s'", filename);

    }

    /* Perform the requested action */

    switch(action) {

    case SNAPSHOT_LIST:

        dump_snapshots(bs);

        break;

    case SNAPSHOT_CREATE:

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

        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);

        qemu_gettimeofday(&tv);

        sn.date_sec = tv.tv_sec;

        sn.date_nsec = tv.tv_usec * 1000;

        ret = bdrv_snapshot_create(bs, &sn);

        if (ret)

            error("Could not create snapshot '%s': %d (%s)",

                snapshot_name, ret, strerror(-ret));

        break;

    case SNAPSHOT_APPLY:

        ret = bdrv_snapshot_goto(bs, snapshot_name);

        if (ret)

            error("Could not apply snapshot '%s': %d (%s)",

                snapshot_name, ret, strerror(-ret));

        break;

    case SNAPSHOT_DELETE:

        ret = bdrv_snapshot_delete(bs, snapshot_name);

        if (ret)

            error("Could not delete snapshot '%s': %d (%s)",

                snapshot_name, ret, strerror(-ret));

        break;

    }

    /* Cleanup */

    bdrv_delete(bs);

}


static void pack_yuv(TiffEncoderContext * s, uint8_t * dst, int lnum)

{

    AVFrame *p = &s->picture;

    int i, j, k;

    int w = (s->width - 1) / s->subsampling[0] + 1;

    uint8_t *pu = &p->data[1][lnum / s->subsampling[1] * p->linesize[1]];

    uint8_t *pv = &p->data[2][lnum / s->subsampling[1] * p->linesize[2]];

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

        for (j = 0; j < s->subsampling[1]; j++)

            for (k = 0; k < s->subsampling[0]; k++)

                *dst++ = p->data[0][(lnum + j) * p->linesize[0] +

                                    i * s->subsampling[0] + k];

        *dst++ = *pu++;

        *dst++ = *pv++;

    }

}


static inline void RENAME(yuv2yuvX)(SwsContext *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize,

                                    const int16_t *chrFilter, const int16_t **chrSrc, int chrFilterSize, const int16_t **alpSrc,

                                    uint8_t *dest, uint8_t *uDest, uint8_t *vDest, uint8_t *aDest, long dstW, long chrDstW)

{

#if COMPILE_TEMPLATE_MMX

    if(!(c->flags & SWS_BITEXACT)) {

        if (c->flags & SWS_ACCURATE_RND) {

            if (uDest) {

                YSCALEYUV2YV12X_ACCURATE(   "0", CHR_MMX_FILTER_OFFSET, uDest, chrDstW)

                YSCALEYUV2YV12X_ACCURATE(AV_STRINGIFY(VOF), CHR_MMX_FILTER_OFFSET, vDest, chrDstW)

            }

            if (CONFIG_SWSCALE_ALPHA && aDest) {

                YSCALEYUV2YV12X_ACCURATE(   "0", ALP_MMX_FILTER_OFFSET, aDest, dstW)

            }

            YSCALEYUV2YV12X_ACCURATE("0", LUM_MMX_FILTER_OFFSET, dest, dstW)

        } else {

            if (uDest) {

                YSCALEYUV2YV12X(   "0", CHR_MMX_FILTER_OFFSET, uDest, chrDstW)

                YSCALEYUV2YV12X(AV_STRINGIFY(VOF), CHR_MMX_FILTER_OFFSET, vDest, chrDstW)

            }

            if (CONFIG_SWSCALE_ALPHA && aDest) {

                YSCALEYUV2YV12X(   "0", ALP_MMX_FILTER_OFFSET, aDest, dstW)

            }

            YSCALEYUV2YV12X("0", LUM_MMX_FILTER_OFFSET, dest, dstW)

        }

        return;

    }

#endif

#if COMPILE_TEMPLATE_ALTIVEC

    yuv2yuvX_altivec_real(lumFilter, lumSrc, lumFilterSize,

                          chrFilter, chrSrc, chrFilterSize,

                          dest, uDest, vDest, dstW, chrDstW);

#else //COMPILE_TEMPLATE_ALTIVEC

    yuv2yuvXinC(lumFilter, lumSrc, lumFilterSize,

                chrFilter, chrSrc, chrFilterSize,

                alpSrc, dest, uDest, vDest, aDest, dstW, chrDstW);

#endif //!COMPILE_TEMPLATE_ALTIVEC

}


static void do_svc_interrupt(CPUS390XState *env)

{

    uint64_t mask, addr;

    LowCore *lowcore;

    hwaddr len = TARGET_PAGE_SIZE;

    lowcore = cpu_physical_memory_map(env->psa, &len, 1);

    lowcore->svc_code = cpu_to_be16(env->int_svc_code);

    lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);

    lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));

    lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);

    mask = be64_to_cpu(lowcore->svc_new_psw.mask);

    addr = be64_to_cpu(lowcore->svc_new_psw.addr);

    cpu_physical_memory_unmap(lowcore, len, 1, len);

    load_psw(env, mask, addr);

}


void qmp_blockdev_snapshot_sync(bool has_device, const char *device,

                                bool has_node_name, const char *node_name,

                                const char *snapshot_file,

                                bool has_snapshot_node_name,

                                const char *snapshot_node_name,

                                bool has_format, const char *format,

                                bool has_mode, NewImageMode mode, Error **errp)

{

    BlockdevSnapshotSync snapshot = {

        .has_device = has_device,

        .device = (char *) device,

        .has_node_name = has_node_name,

        .node_name = (char *) node_name,

        .snapshot_file = (char *) snapshot_file,

        .has_snapshot_node_name = has_snapshot_node_name,

        .snapshot_node_name = (char *) snapshot_node_name,

        .has_format = has_format,

        .format = (char *) format,

        .has_mode = has_mode,

        .mode = mode,

    };

    TransactionAction action = {

        .type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,

        .u.blockdev_snapshot_sync = &snapshot,

    };

    blockdev_do_action(&action, errp);

}


void *address_space_map(AddressSpace *as,

                        hwaddr addr,

                        hwaddr *plen,

                        bool is_write)

{

    AddressSpaceDispatch *d = as->dispatch;

    hwaddr len = *plen;

    hwaddr todo = 0;

    int l;

    hwaddr page;

    MemoryRegionSection *section;

    ram_addr_t raddr = RAM_ADDR_MAX;

    ram_addr_t rlen;

    void *ret;

    while (len > 0) {

        page = addr & TARGET_PAGE_MASK;

        l = (page + TARGET_PAGE_SIZE) - addr;

        if (l > len)

            l = len;

        section = phys_page_find(d, page >> TARGET_PAGE_BITS);

        if (!(memory_region_is_ram(section->mr) && !section->readonly)) {

            if (todo || bounce.buffer) {

                break;

            }

            bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE);

            bounce.addr = addr;

            bounce.len = l;

            if (!is_write) {

                address_space_read(as, addr, bounce.buffer, l);

            }

            *plen = l;

            return bounce.buffer;

        }

        if (!todo) {

            raddr = memory_region_get_ram_addr(section->mr)

                + memory_region_section_addr(section, addr);

        }

        len -= l;

        addr += l;

        todo += l;

    }

    rlen = todo;

    ret = qemu_ram_ptr_length(raddr, &rlen);

    *plen = rlen;

    return ret;

}


static void g364fb_ctrl_write(void *opaque,

                              target_phys_addr_t addr,

                              uint64_t val,

                              unsigned int size)

{

    G364State *s = opaque;

    trace_g364fb_write(addr, val);

    if (addr >= REG_CLR_PAL && addr < REG_CLR_PAL + 0x800) {

        /* color palette */

        int idx = (addr - REG_CLR_PAL) >> 3;

        s->color_palette[idx][0] = (val >> 16) & 0xff;

        s->color_palette[idx][1] = (val >> 8) & 0xff;

        s->color_palette[idx][2] = val & 0xff;

        g364fb_invalidate_display(s);

    } else if (addr >= REG_CURS_PAT && addr < REG_CURS_PAT + 0x1000) {

        /* cursor pattern */

        int idx = (addr - REG_CURS_PAT) >> 3;

        s->cursor[idx] = val;

        g364fb_invalidate_display(s);

    } else if (addr >= REG_CURS_PAL && addr < REG_CURS_PAL + 0x18) {

        /* cursor palette */

        int idx = (addr - REG_CURS_PAL) >> 3;

        s->cursor_palette[idx][0] = (val >> 16) & 0xff;

        s->cursor_palette[idx][1] = (val >> 8) & 0xff;

        s->cursor_palette[idx][2] = val & 0xff;

        g364fb_invalidate_display(s);

    } else {

        switch (addr) {

        case REG_BOOT: /* Boot timing */

        case 0x00108: /* Line timing: half sync */

        case 0x00110: /* Line timing: back porch */

        case 0x00120: /* Line timing: short display */

        case 0x00128: /* Frame timing: broad pulse */

        case 0x00130: /* Frame timing: v sync */

        case 0x00138: /* Frame timing: v preequalise */

        case 0x00140: /* Frame timing: v postequalise */

        case 0x00148: /* Frame timing: v blank */

        case 0x00158: /* Line timing: line time */

        case 0x00160: /* Frame store: line start */

        case 0x00168: /* vram cycle: mem init */

        case 0x00170: /* vram cycle: transfer delay */

        case 0x00200: /* vram cycle: mask register */

            /* ignore */

            break;

        case REG_TOP:

            s->top_of_screen = val;

            g364fb_invalidate_display(s);

            break;

        case REG_DISPLAY:

            s->width = val * 4;

            break;

        case REG_VDISPLAY:

            s->height = val / 2;

            break;

        case REG_CTLA:

            s->ctla = val;

            g364fb_update_depth(s);

            g364fb_invalidate_display(s);

            break;

        case REG_CURS_POS:

            g364_invalidate_cursor_position(s);

            s->cursor_position = val;

            g364_invalidate_cursor_position(s);

            break;

        case REG_RESET:

            g364fb_reset(s);

            break;

        default:

            error_report("g364: invalid write of 0x%" PRIx64

                         " at [" TARGET_FMT_plx "]", val, addr);

            break;

        }

    }

    qemu_irq_lower(s->irq);

}


int kvm_arch_insert_hw_breakpoint(target_ulong addr,

                                  target_ulong len, int type)

{

    switch (type) {

    case GDB_BREAKPOINT_HW:

        len = 1;

        break;

    case GDB_WATCHPOINT_WRITE:

    case GDB_WATCHPOINT_ACCESS:

        switch (len) {

        case 1:

            break;

        case 2:

        case 4:

        case 8:

            if (addr & (len - 1))

                return -EINVAL;

            break;

        default:

            return -EINVAL;

        }

        break;

    default:

        return -ENOSYS;

    }

    if (nb_hw_breakpoint == 4)

        return -ENOBUFS;

    if (find_hw_breakpoint(addr, len, type) >= 0)

        return -EEXIST;

    hw_breakpoint[nb_hw_breakpoint].addr = addr;

    hw_breakpoint[nb_hw_breakpoint].len = len;

    hw_breakpoint[nb_hw_breakpoint].type = type;

    nb_hw_breakpoint++;

    return 0;

}


void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)

{

    int i, found;

    WaitObjects *w = &wait_objects;

    found = 0;

    for (i = 0; i < w->num; i++) {

        if (w->events[i] == handle)

            found = 1;

        if (found) {

            w->events[i] = w->events[i + 1];

            w->func[i] = w->func[i + 1];

            w->opaque[i] = w->opaque[i + 1];

        }

    }

    if (found)

        w->num--;

}


static void vc1_interp_mc(VC1Context *v)

{

    MpegEncContext *s = &v->s;

    DSPContext *dsp = &v->s.dsp;

    H264ChromaContext *h264chroma = &v->h264chroma;

    uint8_t *srcY, *srcU, *srcV;

    int dxy, mx, my, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y;

    int off, off_uv;

    int v_edge_pos = s->v_edge_pos >> v->field_mode;

    if (!v->field_mode && !v->s.next_picture.f.data[0])

        return;

    mx   = s->mv[1][0][0];

    my   = s->mv[1][0][1];

    uvmx = (mx + ((mx & 3) == 3)) >> 1;

    uvmy = (my + ((my & 3) == 3)) >> 1;

    if (v->field_mode) {

        if (v->cur_field_type != v->ref_field_type[1])

            my   = my   - 2 + 4 * v->cur_field_type;

            uvmy = uvmy - 2 + 4 * v->cur_field_type;

    }

    if (v->fastuvmc) {

        uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1));

        uvmy = uvmy + ((uvmy < 0) ? -(uvmy & 1) : (uvmy & 1));

    }

    srcY = s->next_picture.f.data[0];

    srcU = s->next_picture.f.data[1];

    srcV = s->next_picture.f.data[2];

    src_x   = s->mb_x * 16 + (mx   >> 2);

    src_y   = s->mb_y * 16 + (my   >> 2);

    uvsrc_x = s->mb_x *  8 + (uvmx >> 2);

    uvsrc_y = s->mb_y *  8 + (uvmy >> 2);

    if (v->profile != PROFILE_ADVANCED) {

        src_x   = av_clip(  src_x, -16, s->mb_width  * 16);

        src_y   = av_clip(  src_y, -16, s->mb_height * 16);

        uvsrc_x = av_clip(uvsrc_x,  -8, s->mb_width  *  8);

        uvsrc_y = av_clip(uvsrc_y,  -8, s->mb_height *  8);

    } else {

        src_x   = av_clip(  src_x, -17, s->avctx->coded_width);

        src_y   = av_clip(  src_y, -18, s->avctx->coded_height + 1);

        uvsrc_x = av_clip(uvsrc_x,  -8, s->avctx->coded_width  >> 1);

        uvsrc_y = av_clip(uvsrc_y,  -8, s->avctx->coded_height >> 1);

    }

    srcY += src_y   * s->linesize   + src_x;

    srcU += uvsrc_y * s->uvlinesize + uvsrc_x;

    srcV += uvsrc_y * s->uvlinesize + uvsrc_x;

    if (v->field_mode && v->ref_field_type[1]) {

        srcY += s->current_picture_ptr->f.linesize[0];

        srcU += s->current_picture_ptr->f.linesize[1];

        srcV += s->current_picture_ptr->f.linesize[2];

    }

    /* for grayscale we should not try to read from unknown area */

    if (s->flags & CODEC_FLAG_GRAY) {

        srcU = s->edge_emu_buffer + 18 * s->linesize;

        srcV = s->edge_emu_buffer + 18 * s->linesize;

    }

    if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22

        || (unsigned)(src_x - 1) > s->h_edge_pos - (mx & 3) - 16 - 3

        || (unsigned)(src_y - 1) > v_edge_pos    - (my & 3) - 16 - 3) {

        uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize;

        srcY -= s->mspel * (1 + s->linesize);

        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, srcY, s->linesize,

                                 17 + s->mspel * 2, 17 + s->mspel * 2,

                                 src_x - s->mspel, src_y - s->mspel,

                                 s->h_edge_pos, v_edge_pos);

        srcY = s->edge_emu_buffer;

        s->vdsp.emulated_edge_mc(uvbuf     , srcU, s->uvlinesize, 8 + 1, 8 + 1,

                                 uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1);

        s->vdsp.emulated_edge_mc(uvbuf + 16, srcV, s->uvlinesize, 8 + 1, 8 + 1,

                                 uvsrc_x, uvsrc_y, s->h_edge_pos >> 1, v_edge_pos >> 1);

        srcU = uvbuf;

        srcV = uvbuf + 16;

        /* if we deal with range reduction we need to scale source blocks */

        if (v->rangeredfrm) {

            int i, j;

            uint8_t *src, *src2;

            src = srcY;

            for (j = 0; j < 17 + s->mspel * 2; j++) {

                for (i = 0; i < 17 + s->mspel * 2; i++)

                    src[i] = ((src[i] - 128) >> 1) + 128;

                src += s->linesize;

            }

            src = srcU;

            src2 = srcV;

            for (j = 0; j < 9; j++) {

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

                    src[i]  = ((src[i]  - 128) >> 1) + 128;

                    src2[i] = ((src2[i] - 128) >> 1) + 128;

                }

                src  += s->uvlinesize;

                src2 += s->uvlinesize;

            }

        }

        srcY += s->mspel * (1 + s->linesize);

    }

    if (v->field_mode && v->second_field) {

        off    = s->current_picture_ptr->f.linesize[0];

        off_uv = s->current_picture_ptr->f.linesize[1];

    } else {

        off    = 0;

        off_uv = 0;

    }

    if (s->mspel) {

        dxy = ((my & 3) << 2) | (mx & 3);

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off    , srcY    , s->linesize, v->rnd);

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8, srcY + 8, s->linesize, v->rnd);

        srcY += s->linesize * 8;

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize    , srcY    , s->linesize, v->rnd);

        v->vc1dsp.avg_vc1_mspel_pixels_tab[dxy](s->dest[0] + off + 8 * s->linesize + 8, srcY + 8, s->linesize, v->rnd);

    } else { // hpel mc

        dxy = (my & 2) | ((mx & 2) >> 1);

        if (!v->rnd)

            dsp->avg_pixels_tab[0][dxy](s->dest[0] + off, srcY, s->linesize, 16);

        else

            dsp->avg_no_rnd_pixels_tab[dxy](s->dest[0] + off, srcY, s->linesize, 16);

    }

    if (s->flags & CODEC_FLAG_GRAY) return;

    /* Chroma MC always uses qpel blilinear */

    uvmx = (uvmx & 3) << 1;

    uvmy = (uvmy & 3) << 1;

    if (!v->rnd) {

        h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy);

        h264chroma->avg_h264_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy);

    } else {

        v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[1] + off_uv, srcU, s->uvlinesize, 8, uvmx, uvmy);

        v->vc1dsp.avg_no_rnd_vc1_chroma_pixels_tab[0](s->dest[2] + off_uv, srcV, s->uvlinesize, 8, uvmx, uvmy);

    }

}


static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,

                                unsigned int size)

{

    S390PCIBusDevice *pbdev;

    uint32_t io_int_word;

    uint32_t fid = data >> ZPCI_MSI_VEC_BITS;

    uint32_t vec = data & ZPCI_MSI_VEC_MASK;

    uint64_t ind_bit;

    uint32_t sum_bit;

    uint32_t e = 0;

    DPRINTF("write_msix data 0x%" PRIx64 " fid %d vec 0x%x\n", data, fid, vec);

    pbdev = s390_pci_find_dev_by_fid(fid);

    if (!pbdev) {

        e |= (vec << ERR_EVENT_MVN_OFFSET);

        s390_pci_generate_error_event(ERR_EVENT_NOMSI, 0, fid, addr, e);

        return;

    }

    if (!(pbdev->fh & FH_MASK_ENABLE)) {

        return;

    }

    ind_bit = pbdev->routes.adapter.ind_offset;

    sum_bit = pbdev->routes.adapter.summary_offset;

    set_ind_atomic(pbdev->routes.adapter.ind_addr + (ind_bit + vec) / 8,

                   0x80 >> ((ind_bit + vec) % 8));

    if (!set_ind_atomic(pbdev->routes.adapter.summary_addr + sum_bit / 8,

                                       0x80 >> (sum_bit % 8))) {

        io_int_word = (pbdev->isc << 27) | IO_INT_WORD_AI;

        s390_io_interrupt(0, 0, 0, io_int_word);

    }

}


static int qcow2_create2(const char *filename, int64_t total_size,

                         const char *backing_file, const char *backing_format,

                         int flags, size_t cluster_size, int prealloc,

                         QEMUOptionParameter *options)

{

    /* Calculate cluster_bits */

    int cluster_bits;

    cluster_bits = ffs(cluster_size) - 1;

    if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||

        (1 << cluster_bits) != cluster_size)

    {

        error_report(

            "Cluster size must be a power of two between %d and %dk",

            1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));

        return -EINVAL;

    }

    /*

     * Open the image file and write a minimal qcow2 header.

     *

     * We keep things simple and start with a zero-sized image. We also

     * do without refcount blocks or a L1 table for now. We'll fix the

     * inconsistency later.

     *

     * We do need a refcount table because growing the refcount table means

     * allocating two new refcount blocks - the seconds of which would be at

     * 2 GB for 64k clusters, and we don't want to have a 2 GB initial file

     * size for any qcow2 image.

     */

    BlockDriverState* bs;

    QCowHeader header;

    uint8_t* refcount_table;

    int ret;

    ret = bdrv_create_file(filename, options);

    if (ret < 0) {

        return ret;

    }

    ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);

    if (ret < 0) {

        return ret;

    }

    /* Write the header */

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

    header.magic = cpu_to_be32(QCOW_MAGIC);

    header.version = cpu_to_be32(QCOW_VERSION);

    header.cluster_bits = cpu_to_be32(cluster_bits);

    header.size = cpu_to_be64(0);

    header.l1_table_offset = cpu_to_be64(0);

    header.l1_size = cpu_to_be32(0);

    header.refcount_table_offset = cpu_to_be64(cluster_size);

    header.refcount_table_clusters = cpu_to_be32(1);

    if (flags & BLOCK_FLAG_ENCRYPT) {

        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);

    } else {

        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);

    }

    ret = bdrv_pwrite(bs, 0, &header, sizeof(header));

    if (ret < 0) {

        goto out;

    }

    /* Write an empty refcount table */

    refcount_table = g_malloc0(cluster_size);

    ret = bdrv_pwrite(bs, cluster_size, refcount_table, cluster_size);

    g_free(refcount_table);

    if (ret < 0) {

        goto out;

    }

    bdrv_close(bs);

    /*

     * And now open the image and make it consistent first (i.e. increase the

     * refcount of the cluster that is occupied by the header and the refcount

     * table)

     */

    BlockDriver* drv = bdrv_find_format("qcow2");

    assert(drv != NULL);

    ret = bdrv_open(bs, filename,

        BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv);

    if (ret < 0) {

        goto out;

    }

    ret = qcow2_alloc_clusters(bs, 2 * cluster_size);

    if (ret < 0) {

        goto out;

    } else if (ret != 0) {

        error_report("Huh, first cluster in empty image is already in use?");

        abort();

    }

    /* Okay, now that we have a valid image, let's give it the right size */

    ret = bdrv_truncate(bs, total_size * BDRV_SECTOR_SIZE);

    if (ret < 0) {

        goto out;

    }

    /* Want a backing file? There you go.*/

    if (backing_file) {

        ret = bdrv_change_backing_file(bs, backing_file, backing_format);

        if (ret < 0) {

            goto out;

        }

    }

    /* And if we're supposed to preallocate metadata, do that now */

    if (prealloc) {

        ret = preallocate(bs);

        if (ret < 0) {

            goto out;

        }

    }

    ret = 0;

out:

    bdrv_delete(bs);

    return ret;

}


static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,

                                          bool with_irqfd)

{

    VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);

    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);

    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);

    VirtQueue *vq = virtio_get_queue(vdev, n);

    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);

    if (assign) {

        int r = event_notifier_init(notifier, 0);

        if (r < 0) {

            return r;

        }

        virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);

    } else {

        virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);

        event_notifier_cleanup(notifier);

    }

    if (vdc->guest_notifier_mask) {

        vdc->guest_notifier_mask(vdev, n, !assign);

    }

    return 0;

}


static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,

                     Error **errp)

{

    BDRVVHDXState *s = bs->opaque;

    int ret = 0;

    uint32_t i;

    uint64_t signature;

    uint32_t data_blocks_cnt, bitmap_blocks_cnt;

    s->bat = NULL;

    s->first_visible_write = true;

    qemu_co_mutex_init(&s->lock);

    /* validate the file signature */

    ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t));

    if (ret < 0) {

        goto fail;

    }

    if (memcmp(&signature, "vhdxfile", 8)) {

        ret = -EINVAL;

        goto fail;

    }

    /* This is used for any header updates, for the file_write_guid.

     * The spec dictates that a new value should be used for the first

     * header update */

    vhdx_guid_generate(&s->session_guid);

    ret = vhdx_parse_header(bs, s);

    if (ret) {

        goto fail;

    }

    ret = vhdx_parse_log(bs, s);

    if (ret) {

        goto fail;

    }

    ret = vhdx_open_region_tables(bs, s);

    if (ret) {

        goto fail;

    }

    ret = vhdx_parse_metadata(bs, s);

    if (ret) {

        goto fail;

    }

    s->block_size = s->params.block_size;

    /* the VHDX spec dictates that virtual_disk_size is always a multiple of

     * logical_sector_size */

    bs->total_sectors = s->virtual_disk_size >> s->logical_sector_size_bits;

    data_blocks_cnt = s->virtual_disk_size >> s->block_size_bits;

    if (s->virtual_disk_size - (data_blocks_cnt << s->block_size_bits)) {

        data_blocks_cnt++;

    }

    bitmap_blocks_cnt = data_blocks_cnt >> s->chunk_ratio_bits;

    if (data_blocks_cnt - (bitmap_blocks_cnt << s->chunk_ratio_bits)) {

        bitmap_blocks_cnt++;

    }

    if (s->parent_entries) {

        s->bat_entries = bitmap_blocks_cnt * (s->chunk_ratio + 1);

    } else {

        s->bat_entries = data_blocks_cnt +

                         ((data_blocks_cnt - 1) >> s->chunk_ratio_bits);

    }

    s->bat_offset = s->bat_rt.file_offset;

    if (s->bat_entries > s->bat_rt.length / sizeof(VHDXBatEntry)) {

        /* BAT allocation is not large enough for all entries */

        ret = -EINVAL;

        goto fail;

    }

    /* s->bat is freed in vhdx_close() */

    s->bat = qemu_blockalign(bs, s->bat_rt.length);

    ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length);

    if (ret < 0) {

        goto fail;

    }

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

        le64_to_cpus(&s->bat[i]);

    }

    if (flags & BDRV_O_RDWR) {

        ret = vhdx_update_headers(bs, s, false, NULL);

        if (ret < 0) {

            goto fail;

        }

    }

    /* TODO: differencing files, write */

    /* Disable migration when VHDX images are used */

    error_set(&s->migration_blocker,

            QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,

            "vhdx", bs->device_name, "live migration");

    migrate_add_blocker(s->migration_blocker);

    return 0;

fail:

    qemu_vfree(s->headers[0]);

    qemu_vfree(s->headers[1]);

    qemu_vfree(s->bat);

    qemu_vfree(s->parent_entries);

    return ret;

}


void pci_register_bar(PCIDevice *pci_dev, int region_num,

                            pcibus_t size, int type,

                            PCIMapIORegionFunc *map_func)

{

    PCIIORegion *r;

    uint32_t addr;

    uint64_t wmask;

    if ((unsigned int)region_num >= PCI_NUM_REGIONS)

        return;

    if (size & (size-1)) {

        fprintf(stderr, "ERROR: PCI region size must be pow2 "

                    "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size);

        exit(1);

    }

    r = &pci_dev->io_regions[region_num];

    r->addr = PCI_BAR_UNMAPPED;

    r->size = size;

    r->filtered_size = size;

    r->type = type;

    r->map_func = map_func;

    wmask = ~(size - 1);

    addr = pci_bar(pci_dev, region_num);

    if (region_num == PCI_ROM_SLOT) {

        /* ROM enable bit is writeable */

        wmask |= PCI_ROM_ADDRESS_ENABLE;

    }

    pci_set_long(pci_dev->config + addr, type);

    if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) &&

        r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {

        pci_set_quad(pci_dev->wmask + addr, wmask);

        pci_set_quad(pci_dev->cmask + addr, ~0ULL);

    } else {

        pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff);

        pci_set_long(pci_dev->cmask + addr, 0xffffffff);

    }

}


static void loadvm_postcopy_handle_run_bh(void *opaque)

{

    Error *local_err = NULL;

    HandleRunBhData *data = opaque;

    /* TODO we should move all of this lot into postcopy_ram.c or a shared code

     * in migration.c

     */

    cpu_synchronize_all_post_init();

    qemu_announce_self();

    /* Make sure all file formats flush their mutable metadata.

     * If we get an error here, just don't restart the VM yet. */

    bdrv_invalidate_cache_all(&local_err);

    if (!local_err) {

        blk_resume_after_migration(&local_err);

    }

    if (local_err) {

        error_report_err(local_err);

        local_err = NULL;

        autostart = false;

    }

    trace_loadvm_postcopy_handle_run_cpu_sync();

    cpu_synchronize_all_post_init();

    trace_loadvm_postcopy_handle_run_vmstart();

    if (autostart) {

        /* Hold onto your hats, starting the CPU */

        vm_start();

    } else {

        /* leave it paused and let management decide when to start the CPU */

        runstate_set(RUN_STATE_PAUSED);

    }

    qemu_bh_delete(data->bh);

    g_free(data);

}


BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,

                            QEMUIOVector *qiov, int nb_sectors,

                            BlockCompletionFunc *cb, void *opaque)

{

    trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);

    return bdrv_co_aio_rw_vector(bs, sector_num, qiov, nb_sectors, 0,

                                 cb, opaque, true);

}


void HELPER(srstu)(CPUS390XState *env, uint32_t r1, uint32_t r2)

{

    uintptr_t ra = GETPC();

    uint32_t len;

    uint16_t v, c = env->regs[0];

    uint64_t end, str, adj_end;

    /* Bits 32-47 of R0 must be zero.  */

    if (env->regs[0] & 0xffff0000u) {

        cpu_restore_state(ENV_GET_CPU(env), ra);

        program_interrupt(env, PGM_SPECIFICATION, 6);

    }

    str = get_address(env, r2);

    end = get_address(env, r1);

    /* If the LSB of the two addresses differ, use one extra byte.  */

    adj_end = end + ((str ^ end) & 1);

    /* Lest we fail to service interrupts in a timely manner, limit the

       amount of work we're willing to do.  For now, let's cap at 8k.  */

    for (len = 0; len < 0x2000; len += 2) {

        if (str + len == adj_end) {

            /* End of input found.  */

            env->cc_op = 2;

            return;

        }

        v = cpu_lduw_data_ra(env, str + len, ra);

        if (v == c) {

            /* Character found.  Set R1 to the location; R2 is unmodified.  */

            env->cc_op = 1;

            set_address(env, r1, str + len);

            return;

        }

    }

    /* CPU-determined bytes processed.  Advance R2 to next byte to process.  */

    env->cc_op = 3;

    set_address(env, r2, str + len);

}


static void scsi_aio_complete(void *opaque, int ret)

{

    SCSIDiskReq *r = (SCSIDiskReq *)opaque;

    SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);

    assert(r->req.aiocb != NULL);

    r->req.aiocb = NULL;

    block_acct_done(bdrv_get_stats(s->qdev.conf.bs), &r->acct);

    if (r->req.io_canceled) {

        scsi_req_cancel_complete(&r->req);

        goto done;

    }

    if (ret < 0) {

        if (scsi_handle_rw_error(r, -ret)) {

            goto done;

        }

    }

    scsi_req_complete(&r->req, GOOD);

done:

    scsi_req_unref(&r->req);

}


static void set_mem_path(Object *o, const char *str, Error **errp)

{

    HostMemoryBackend *backend = MEMORY_BACKEND(o);

    HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);

    if (memory_region_size(&backend->mr)) {

        error_setg(errp, "cannot change property value");

        return;

    }

    if (fb->mem_path) {

        g_free(fb->mem_path);

    }

    fb->mem_path = g_strdup(str);

}


static always_inline void gen_store_mem (DisasContext *ctx,

                                         void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1, int flags),

                                         int ra, int rb, int32_t disp16,

                                         int fp, int clear, int local)

{

    TCGv addr;

    if (local)

        addr = tcg_temp_local_new(TCG_TYPE_I64);

    else

        addr = tcg_temp_new(TCG_TYPE_I64);

    if (rb != 31) {

        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);

        if (clear)

            tcg_gen_andi_i64(addr, addr, ~0x7);

    } else {

        if (clear)

            disp16 &= ~0x7;

        tcg_gen_movi_i64(addr, disp16);

    }

    if (ra != 31) {

        if (fp)

            tcg_gen_qemu_store(cpu_fir[ra], addr, ctx->mem_idx);

        else

            tcg_gen_qemu_store(cpu_ir[ra], addr, ctx->mem_idx);

    } else {

        TCGv zero;

        if (local)

            zero = tcg_const_local_i64(0);

        else

            zero = tcg_const_i64(0);

        tcg_gen_qemu_store(zero, addr, ctx->mem_idx);

        tcg_temp_free(zero);

    }

    tcg_temp_free(addr);

}


static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)

{

    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);

    return snprintf(dest, len, "%" PRIu16, *ptr);

}


static int get_sot(Jpeg2000DecoderContext *s, int n)
{
    Jpeg2000TilePart *tp;
    uint16_t Isot;
    uint32_t Psot;
    uint8_t TPsot;
    if (bytestream2_get_bytes_left(&s->g) < 8)
    Isot = bytestream2_get_be16u(&s->g);        // Isot
    if (Isot) {
        avpriv_request_sample(s->avctx, "Support for more than one tile");
        return AVERROR_PATCHWELCOME;
    }
    Psot  = bytestream2_get_be32u(&s->g);       // Psot
    TPsot = bytestream2_get_byteu(&s->g);       // TPsot
    /* Read TNSot but not used */
    bytestream2_get_byteu(&s->g);               // TNsot
    if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) {
        av_log(s->avctx, AV_LOG_ERROR, "Psot %d too big\n", Psot);
    }
    if (TPsot >= FF_ARRAY_ELEMS(s->tile[Isot].tile_part)) {
        avpriv_request_sample(s->avctx, "Support for %d components", TPsot);
        return AVERROR_PATCHWELCOME;
    }
    tp             = s->tile[s->curtileno].tile_part + TPsot;
    tp->tile_index = Isot;
    tp->tp_len     = Psot;
    tp->tp_idx     = TPsot;
    /* Start of bit stream. Pointer to SOD marker
     * Check SOD marker is present. */
    if (JPEG2000_SOD == bytestream2_get_be16(&s->g)) {
        bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_len - n - 4);
        bytestream2_skip(&s->g, tp->tp_len - n - 4);
    } else {
        av_log(s->avctx, AV_LOG_ERROR, "SOD marker not found \n");
    }
    /* End address of bit stream =
     *     start address + (Psot - size of SOT HEADER(n)
     *     - size of SOT MARKER(2)  - size of SOD marker(2) */
    return 0;
}


static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)

{

    int sx = 0, sy = 0;

    int dx = 0, dy = 0;

    int depth = 0;

    int notify = 0;

    /* make sure to only copy if it's a plain copy ROP */

    if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||

        *s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {

        int width, height;

        depth = s->vga.get_bpp(&s->vga) / 8;

        if (!depth) {

            return 0;

        }

        s->vga.get_resolution(&s->vga, &width, &height);

        /* extra x, y */

        sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;

        sy = (src / ABS(s->cirrus_blt_srcpitch));

        dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;

        dy = (dst / ABS(s->cirrus_blt_dstpitch));

        /* normalize width */

        w /= depth;

        /* if we're doing a backward copy, we have to adjust

           our x/y to be the upper left corner (instead of the lower

           right corner) */

        if (s->cirrus_blt_dstpitch < 0) {

            sx -= (s->cirrus_blt_width / depth) - 1;

            dx -= (s->cirrus_blt_width / depth) - 1;

            sy -= s->cirrus_blt_height - 1;

            dy -= s->cirrus_blt_height - 1;

        }

        /* are we in the visible portion of memory? */

        if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&

            (sx + w) <= width && (sy + h) <= height &&

            (dx + w) <= width && (dy + h) <= height) {

            notify = 1;

        }

    }

    /* we have to flush all pending changes so that the copy

       is generated at the appropriate moment in time */

    if (notify)

        graphic_hw_update(s->vga.con);

    (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr,

                      s->vga.vram_ptr + s->cirrus_blt_srcaddr,

		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,

		      s->cirrus_blt_width, s->cirrus_blt_height);

    if (notify) {

        qemu_console_copy(s->vga.con,

			  sx, sy, dx, dy,

			  s->cirrus_blt_width / depth,

			  s->cirrus_blt_height);

    }

    /* we don't have to notify the display that this portion has

       changed since qemu_console_copy implies this */

    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,

				s->cirrus_blt_dstpitch, s->cirrus_blt_width,

				s->cirrus_blt_height);

    return 1;

}


static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
{
    AResampleContext *aresample = inlink->dst->priv;
    const int n_in  = insamplesref->audio->nb_samples;
    int n_out       = FFMAX(n_in * aresample->ratio * 2, 1);
    AVFilterLink *const outlink = inlink->dst->outputs[0];
    AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n_out);
    int ret;
    avfilter_copy_buffer_ref_props(outsamplesref, insamplesref);
    outsamplesref->format                = outlink->format;
    outsamplesref->audio->channel_layout = outlink->channel_layout;
    outsamplesref->audio->sample_rate    = outlink->sample_rate;
    if(insamplesref->pts != AV_NOPTS_VALUE) {
        int64_t inpts = av_rescale(insamplesref->pts, inlink->time_base.num * (int64_t)outlink->sample_rate * inlink->sample_rate, inlink->time_base.den);
        int64_t outpts= swr_next_pts(aresample->swr, inpts);
        aresample->next_pts =
        outsamplesref->pts  = (outpts + inlink->sample_rate/2) / inlink->sample_rate;
    } else {
        outsamplesref->pts  = AV_NOPTS_VALUE;
    }
    n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out,
                                 (void *)insamplesref->extended_data, n_in);
    if (n_out <= 0) {
        avfilter_unref_buffer(outsamplesref);
        avfilter_unref_buffer(insamplesref);
        return 0;
    }
    outsamplesref->audio->nb_samples  = n_out;
    ret = ff_filter_samples(outlink, outsamplesref);
    aresample->req_fullfilled= 1;
    avfilter_unref_buffer(insamplesref);
    return ret;
}


static int decode_subframe_lpc(FLACContext *s, int channel, int pred_order)

{

    int sum, i, j;

    int coeff_prec, qlevel;

    int coeffs[pred_order];

//    av_log(s->avctx, AV_LOG_DEBUG, "  SUBFRAME LPC\n");

    /* warm up samples */

//    av_log(s->avctx, AV_LOG_DEBUG, "   warm up samples: %d\n", pred_order);

    for (i = 0; i < pred_order; i++)

    {

        s->decoded[channel][i] = get_sbits(&s->gb, s->curr_bps);

//        av_log(s->avctx, AV_LOG_DEBUG, "    %d: %d\n", i, s->decoded[channel][i]);

    }

    coeff_prec = get_bits(&s->gb, 4) + 1;

    if (coeff_prec == 16)

    {

        av_log(s->avctx, AV_LOG_DEBUG, "invalid coeff precision\n");

        return -1;

    }

    av_log(s->avctx, AV_LOG_DEBUG, "   qlp coeff prec: %d\n", coeff_prec);

    qlevel = get_sbits(&s->gb, 5);

    av_log(s->avctx, AV_LOG_DEBUG, "   quant level: %d\n", qlevel);

assert(qlevel >= 0); //FIXME

    for (i = 0; i < pred_order; i++)

    {

        coeffs[i] = get_sbits(&s->gb, coeff_prec);

//        av_log(s->avctx, AV_LOG_DEBUG, "    %d: %d\n", i, coeffs[i]);

    }

    if (decode_residuals(s, channel, pred_order) < 0)

        return -1;

    for (i = pred_order; i < s->blocksize; i++)

    {

        sum = 0;

        for (j = 0; j < pred_order; j++)

            sum += coeffs[j] * s->decoded[channel][i-j-1];

        s->decoded[channel][i] += sum >> qlevel;

    }

    return 0;

}


static int compare_floats(const float *a, const float *b, int len,

                          float max_diff)

{

    int i;

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

        if (fabsf(a[i] - b[i]) > max_diff) {

            av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",

                   i, a[i], b[i], a[i] - b[i]);

            return -1;

        }

    }

    return 0;

}


static int mtv_read_packet(AVFormatContext *s, AVPacket *pkt)

{

    MTVDemuxContext *mtv = s->priv_data;

    ByteIOContext *pb = s->pb;

    int ret;

#if !HAVE_BIGENDIAN

    int i;

#endif

    if((url_ftell(pb) - s->data_offset + mtv->img_segment_size) % mtv->full_segment_size)

    {

        url_fskip(pb, MTV_AUDIO_PADDING_SIZE);

        ret = av_get_packet(pb, pkt, MTV_ASUBCHUNK_DATA_SIZE);

        if(ret != MTV_ASUBCHUNK_DATA_SIZE)

            return AVERROR(EIO);

        pkt->pos -= MTV_AUDIO_PADDING_SIZE;

        pkt->stream_index = AUDIO_SID;

    }else

    {

        ret = av_get_packet(pb, pkt, mtv->img_segment_size);

        if(ret != mtv->img_segment_size)

            return AVERROR(EIO);

#if !HAVE_BIGENDIAN

        /* pkt->data is GGGRRRR BBBBBGGG

         * and we need RRRRRGGG GGGBBBBB

         * for PIX_FMT_RGB565 so here we

         * just swap bytes as they come

         */

        for(i=0;i<mtv->img_segment_size/2;i++)

            *((uint16_t *)pkt->data+i) = bswap_16(*((uint16_t *)pkt->data+i));

#endif

        pkt->stream_index = VIDEO_SID;

    }

    return ret;

}


void esp_init(target_phys_addr_t espaddr, int it_shift,

              espdma_memory_read_write dma_memory_read,

              espdma_memory_read_write dma_memory_write,

              void *dma_opaque, qemu_irq irq, qemu_irq *reset)

{

    DeviceState *dev;

    SysBusDevice *s;

    ESPState *esp;

    dev = qdev_create(NULL, "esp");

    esp = DO_UPCAST(ESPState, busdev.qdev, dev);

    esp->dma_memory_read = dma_memory_read;

    esp->dma_memory_write = dma_memory_write;

    esp->dma_opaque = dma_opaque;

    esp->it_shift = it_shift;

    qdev_init(dev);

    s = sysbus_from_qdev(dev);

    sysbus_connect_irq(s, 0, irq);

    sysbus_mmio_map(s, 0, espaddr);

    *reset = qdev_get_gpio_in(dev, 0);

}


static void mptsas_process_scsi_task_mgmt(MPTSASState *s, MPIMsgSCSITaskMgmt *req)

{

    MPIMsgSCSITaskMgmtReply reply;

    MPIMsgSCSITaskMgmtReply *reply_async;

    int status, count;

    SCSIDevice *sdev;

    SCSIRequest *r, *next;

    BusChild *kid;

    mptsas_fix_scsi_task_mgmt_endianness(req);

    QEMU_BUILD_BUG_ON(MPTSAS_MAX_REQUEST_SIZE < sizeof(*req));

    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_msg) < sizeof(*req));

    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_reply) < sizeof(reply));

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

    reply.TargetID   = req->TargetID;

    reply.Bus        = req->Bus;

    reply.MsgLength  = sizeof(reply) / 4;

    reply.Function   = req->Function;

    reply.TaskType   = req->TaskType;

    reply.MsgContext = req->MsgContext;

    switch (req->TaskType) {

    case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK:

    case MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }

        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            MPTSASRequest *cmd_req = r->hba_private;

            if (cmd_req && cmd_req->scsi_io.MsgContext == req->TaskMsgContext) {

                break;

            }

        }

        if (r) {

            /*

             * Assert that the request has not been completed yet, we

             * check for it in the loop above.

             */

            assert(r->hba_private);

            if (req->TaskType == MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {

                /* "If the specified command is present in the task set, then

                 * return a service response set to FUNCTION SUCCEEDED".

                 */

                reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED;

            } else {

                MPTSASCancelNotifier *notifier;

                reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

                reply_async->IOCLogInfo = INT_MAX;

                count = 1;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->s = s;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

                goto reply_maybe_async;

            }

        }

        break;

    case MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:

    case MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }

        reply_async = g_memdup(&reply, sizeof(MPIMsgSCSITaskMgmtReply));

        reply_async->IOCLogInfo = INT_MAX;

        count = 0;

        QTAILQ_FOREACH_SAFE(r, &sdev->requests, next, next) {

            if (r->hba_private) {

                MPTSASCancelNotifier *notifier;

                count++;

                notifier = g_new(MPTSASCancelNotifier, 1);

                notifier->s = s;

                notifier->reply = reply_async;

                notifier->notifier.notify = mptsas_cancel_notify;

                scsi_req_cancel_async(r, &notifier->notifier);

            }

        }

reply_maybe_async:

        if (reply_async->TerminationCount < count) {

            reply_async->IOCLogInfo = count;

            return;

        }

        reply.TerminationCount = count;

        break;

    case MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:

        status = mptsas_scsi_device_find(s, req->Bus, req->TargetID,

                                         req->LUN, &sdev);

        if (status) {

            reply.IOCStatus = status;

            goto out;

        }

        if (sdev->lun != req->LUN[1]) {

            reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN;

            goto out;

        }

        qdev_reset_all(&sdev->qdev);

        break;

    case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET:

        if (req->Bus != 0) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_BUS;

            goto out;

        }

        if (req->TargetID > s->max_devices) {

            reply.IOCStatus = MPI_IOCSTATUS_SCSI_INVALID_TARGETID;

            goto out;

        }

        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {

            sdev = SCSI_DEVICE(kid->child);

            if (sdev->channel == 0 && sdev->id == req->TargetID) {

                qdev_reset_all(kid->child);

            }

        }

        break;

    case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS:

        qbus_reset_all(&s->bus.qbus);

        break;

    default:

        reply.ResponseCode = MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED;

        break;

    }

out:

    mptsas_fix_scsi_task_mgmt_reply_endianness(&reply);

    mptsas_post_reply(s, (MPIDefaultReply *)&reply);

}


static void cpu_class_init(ObjectClass *oc, void *data)

{

    SCLPEventClass *k = SCLP_EVENT_CLASS(oc);

    DeviceClass *dc = DEVICE_CLASS(oc);

    k->get_send_mask = send_mask;

    k->get_receive_mask = receive_mask;

    k->read_event_data = read_event_data;

    set_bit(DEVICE_CATEGORY_MISC, dc->categories);

}


BlockDriverAIOCB *dma_bdrv_io(

    BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,

    DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,

    void *opaque, DMADirection dir)

{

    DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);

    trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));

    dbs->acb = NULL;

    dbs->bs = bs;

    dbs->sg = sg;

    dbs->sector_num = sector_num;

    dbs->sg_cur_index = 0;

    dbs->sg_cur_byte = 0;

    dbs->dir = dir;

    dbs->io_func = io_func;

    dbs->bh = NULL;

    qemu_iovec_init(&dbs->iov, sg->nsg);

    dma_bdrv_cb(dbs, 0);

    return &dbs->common;

}


int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,

                          uint64_t bytes, QEMUIOVector *qiov, int flags)

{

    NBDClientSession *client = nbd_get_client_session(bs);

    NBDRequest request = {

        .type = NBD_CMD_WRITE,

        .from = offset,

        .len = bytes,

    };

    if (flags & BDRV_REQ_FUA) {

        assert(client->info.flags & NBD_FLAG_SEND_FUA);

        request.flags |= NBD_CMD_FLAG_FUA;

    }

    assert(bytes <= NBD_MAX_BUFFER_SIZE);

    return nbd_co_request(bs, &request, qiov);

}


static abi_long host_to_target_data_route(struct nlmsghdr *nlh)

{

    uint32_t nlmsg_len;

    struct ifinfomsg *ifi;

    struct ifaddrmsg *ifa;

    struct rtmsg *rtm;

    nlmsg_len = nlh->nlmsg_len;

    switch (nlh->nlmsg_type) {

    case RTM_NEWLINK:

    case RTM_DELLINK:

    case RTM_GETLINK:

        ifi = NLMSG_DATA(nlh);

        ifi->ifi_type = tswap16(ifi->ifi_type);

        ifi->ifi_index = tswap32(ifi->ifi_index);

        ifi->ifi_flags = tswap32(ifi->ifi_flags);

        ifi->ifi_change = tswap32(ifi->ifi_change);

        host_to_target_link_rtattr(IFLA_RTA(ifi),

                                   nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));

        break;

    case RTM_NEWADDR:

    case RTM_DELADDR:

    case RTM_GETADDR:

        ifa = NLMSG_DATA(nlh);

        ifa->ifa_index = tswap32(ifa->ifa_index);

        host_to_target_addr_rtattr(IFA_RTA(ifa),

                                   nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));

        break;

    case RTM_NEWROUTE:

    case RTM_DELROUTE:

    case RTM_GETROUTE:

        rtm = NLMSG_DATA(nlh);

        rtm->rtm_flags = tswap32(rtm->rtm_flags);

        host_to_target_route_rtattr(RTM_RTA(rtm),

                                    nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));

        break;

    default:

        return -TARGET_EINVAL;

    }

    return 0;

}


static int pcm_decode_frame(AVCodecContext *avctx,

                            void *data, int *data_size,

                            uint8_t *buf, int buf_size)

{

    PCMDecode *s = avctx->priv_data;

    int n;

    short *samples;

    uint8_t *src;

    samples = data;

    src = buf;

    if(buf_size > AVCODEC_MAX_AUDIO_FRAME_SIZE/2)

        buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE/2;

    switch(avctx->codec->id) {

    case CODEC_ID_PCM_S32LE:

        decode_to16(4, 1, 0, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_S32BE:

        decode_to16(4, 0, 0, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_U32LE:

        decode_to16(4, 1, 1, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_U32BE:

        decode_to16(4, 0, 1, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_S24LE:

        decode_to16(3, 1, 0, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_S24BE:

        decode_to16(3, 0, 0, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_U24LE:

        decode_to16(3, 1, 1, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_U24BE:

        decode_to16(3, 0, 1, &src, &samples, buf_size);

        break;

    case CODEC_ID_PCM_S24DAUD:

        n = buf_size / 3;

        for(;n>0;n--) {

          uint32_t v = src[0] << 16 | src[1] << 8 | src[2];

          v >>= 4; // sync flags are here

          *samples++ = ff_reverse[(v >> 8) & 0xff] +

                       (ff_reverse[v & 0xff] << 8);

          src += 3;

        }

        break;

    case CODEC_ID_PCM_S16LE:

        n = buf_size >> 1;

        for(;n>0;n--) {

            *samples++ = src[0] | (src[1] << 8);

            src += 2;

        }

        break;

    case CODEC_ID_PCM_S16BE:

        n = buf_size >> 1;

        for(;n>0;n--) {

            *samples++ = (src[0] << 8) | src[1];

            src += 2;

        }

        break;

    case CODEC_ID_PCM_U16LE:

        n = buf_size >> 1;

        for(;n>0;n--) {

            *samples++ = (src[0] | (src[1] << 8)) - 0x8000;

            src += 2;

        }

        break;

    case CODEC_ID_PCM_U16BE:

        n = buf_size >> 1;

        for(;n>0;n--) {

            *samples++ = ((src[0] << 8) | src[1]) - 0x8000;

            src += 2;

        }

        break;

    case CODEC_ID_PCM_S8:

        n = buf_size;

        for(;n>0;n--) {

            *samples++ = src[0] << 8;

            src++;

        }

        break;

    case CODEC_ID_PCM_U8:

        n = buf_size;

        for(;n>0;n--) {

            *samples++ = ((int)src[0] - 128) << 8;

            src++;

        }

        break;

    case CODEC_ID_PCM_ALAW:

    case CODEC_ID_PCM_MULAW:

        n = buf_size;

        for(;n>0;n--) {

            *samples++ = s->table[src[0]];

            src++;

        }

        break;

    default:

        return -1;

    }

    *data_size = (uint8_t *)samples - (uint8_t *)data;

    return src - buf;

}


static inline void RENAME(rgb32to16)(const uint8_t *src, uint8_t *dst, long src_size)

{

	const uint8_t *s = src;

	const uint8_t *end;

#ifdef HAVE_MMX

	const uint8_t *mm_end;

#endif

	uint16_t *d = (uint16_t *)dst;

	end = s + src_size;

#ifdef HAVE_MMX

	mm_end = end - 15;

#if 1 //is faster only if multiplies are reasonable fast (FIXME figure out on which cpus this is faster, on Athlon its slightly faster)

	asm volatile(

		"movq %3, %%mm5			\n\t"

		"movq %4, %%mm6			\n\t"

		"movq %5, %%mm7			\n\t"

		ASMALIGN16

		"1:				\n\t"

		PREFETCH" 32(%1)		\n\t"

		"movd	(%1), %%mm0		\n\t"

		"movd	4(%1), %%mm3		\n\t"

		"punpckldq 8(%1), %%mm0		\n\t"

		"punpckldq 12(%1), %%mm3	\n\t"

		"movq %%mm0, %%mm1		\n\t"

		"movq %%mm3, %%mm4		\n\t"

		"pand %%mm6, %%mm0		\n\t"

		"pand %%mm6, %%mm3		\n\t"

		"pmaddwd %%mm7, %%mm0		\n\t"

		"pmaddwd %%mm7, %%mm3		\n\t"

		"pand %%mm5, %%mm1		\n\t"

		"pand %%mm5, %%mm4		\n\t"

		"por %%mm1, %%mm0		\n\t"

		"por %%mm4, %%mm3		\n\t"

		"psrld $5, %%mm0		\n\t"

		"pslld $11, %%mm3		\n\t"

		"por %%mm3, %%mm0		\n\t"

		MOVNTQ"	%%mm0, (%0)		\n\t"

		"add $16, %1			\n\t"

		"add $8, %0			\n\t"

		"cmp %2, %1			\n\t"

		" jb 1b				\n\t"

		: "+r" (d), "+r"(s)

		: "r" (mm_end), "m" (mask3216g), "m" (mask3216br), "m" (mul3216)

	);

#else

	__asm __volatile(PREFETCH"	%0"::"m"(*src):"memory");

	__asm __volatile(

	    "movq	%0, %%mm7\n\t"

	    "movq	%1, %%mm6\n\t"

	    ::"m"(red_16mask),"m"(green_16mask));

	while(s < mm_end)

	{

	    __asm __volatile(

		PREFETCH" 32%1\n\t"

		"movd	%1, %%mm0\n\t"

		"movd	4%1, %%mm3\n\t"

		"punpckldq 8%1, %%mm0\n\t"

		"punpckldq 12%1, %%mm3\n\t"

		"movq	%%mm0, %%mm1\n\t"

		"movq	%%mm0, %%mm2\n\t"

		"movq	%%mm3, %%mm4\n\t"

		"movq	%%mm3, %%mm5\n\t"

		"psrlq	$3, %%mm0\n\t"

		"psrlq	$3, %%mm3\n\t"

		"pand	%2, %%mm0\n\t"

		"pand	%2, %%mm3\n\t"

		"psrlq	$5, %%mm1\n\t"

		"psrlq	$5, %%mm4\n\t"

		"pand	%%mm6, %%mm1\n\t"

		"pand	%%mm6, %%mm4\n\t"

		"psrlq	$8, %%mm2\n\t"

		"psrlq	$8, %%mm5\n\t"

		"pand	%%mm7, %%mm2\n\t"

		"pand	%%mm7, %%mm5\n\t"

		"por	%%mm1, %%mm0\n\t"

		"por	%%mm4, %%mm3\n\t"

		"por	%%mm2, %%mm0\n\t"

		"por	%%mm5, %%mm3\n\t"

		"psllq	$16, %%mm3\n\t"

		"por	%%mm3, %%mm0\n\t"

		MOVNTQ"	%%mm0, %0\n\t"

		:"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");

		d += 4;

		s += 16;

	}

#endif

	__asm __volatile(SFENCE:::"memory");

	__asm __volatile(EMMS:::"memory");

#endif

	while(s < end)

	{

		register int rgb = *(uint32_t*)s; s += 4;

		*d++ = ((rgb&0xFF)>>3) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>8);

	}

}


static int64_t find_best_filter(const DCAADPCMEncContext *s, const int32_t *in, int len)

{

    const premultiplied_coeffs *precalc_data = s->private_data;

    int i, j, k = 0;

    int vq;

    int64_t err;

    int64_t min_err = 1ll << 62;

    int64_t corr[15];

    for (i = 0; i <= DCA_ADPCM_COEFFS; i++)

        for (j = i; j <= DCA_ADPCM_COEFFS; j++)

            corr[k++] = calc_corr(in+4, len, i, j);

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

        err = apply_filter(ff_dca_adpcm_vb[i], corr, *precalc_data);

        if (err < min_err) {

            min_err = err;

            vq = i;

        }

        precalc_data++;

    }

    return vq;

}