static int disas_vfp_insn(DisasContext *s, uint32_t insn)

{

    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;

    int dp, veclen;

    TCGv_i32 addr;

    TCGv_i32 tmp;

    TCGv_i32 tmp2;

    if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {

        return 1;

    }

    /* FIXME: this access check should not take precedence over UNDEF

     * for invalid encodings; we will generate incorrect syndrome information

     * for attempts to execute invalid vfp/neon encodings with FP disabled.

     */

    if (!s->cpacr_fpen) {

        gen_exception_insn(s, 4, EXCP_UDEF,

                           syn_fp_access_trap(1, 0xe, s->thumb),

                           default_exception_el(s));

        return 0;

    }

    if (!s->vfp_enabled) {

        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */

        if ((insn & 0x0fe00fff) != 0x0ee00a10)

            return 1;

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

        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2

            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {

            return 1;

        }

    }

    if (extract32(insn, 28, 4) == 0xf) {

        /* Encodings with T=1 (Thumb) or unconditional (ARM):

         * only used in v8 and above.

         */

        return disas_vfp_v8_insn(s, insn);

    }

    dp = ((insn & 0xf00) == 0xb00);

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

    case 0xe:

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

            /* single register transfer */

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

            if (dp) {

                int size;

                int pass;

                VFP_DREG_N(rn, insn);

                if (insn & 0xf)

                    return 1;

                if (insn & 0x00c00060

                    && !arm_dc_feature(s, ARM_FEATURE_NEON)) {

                    return 1;

                }

                pass = (insn >> 21) & 1;

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

                    size = 0;

                    offset = ((insn >> 5) & 3) * 8;

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

                    size = 1;

                    offset = (insn & (1 << 6)) ? 16 : 0;

                } else {

                    size = 2;

                    offset = 0;

                }

                if (insn & ARM_CP_RW_BIT) {

                    /* vfp->arm */

                    tmp = neon_load_reg(rn, pass);

                    switch (size) {

                    case 0:

                        if (offset)

                            tcg_gen_shri_i32(tmp, tmp, offset);

                        if (insn & (1 << 23))

                            gen_uxtb(tmp);

                        else

                            gen_sxtb(tmp);

                        break;

                    case 1:

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

                            if (offset) {

                                tcg_gen_shri_i32(tmp, tmp, 16);

                            } else {

                                gen_uxth(tmp);

                            }

                        } else {

                            if (offset) {

                                tcg_gen_sari_i32(tmp, tmp, 16);

                            } else {

                                gen_sxth(tmp);

                            }

                        }

                        break;

                    case 2:

                        break;

                    }

                    store_reg(s, rd, tmp);

                } else {

                    /* arm->vfp */

                    tmp = load_reg(s, rd);

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

                        /* VDUP */

                        if (size == 0) {

                            gen_neon_dup_u8(tmp, 0);

                        } else if (size == 1) {

                            gen_neon_dup_low16(tmp);

                        }

                        for (n = 0; n <= pass * 2; n++) {

                            tmp2 = tcg_temp_new_i32();

                            tcg_gen_mov_i32(tmp2, tmp);

                            neon_store_reg(rn, n, tmp2);

                        }

                        neon_store_reg(rn, n, tmp);

                    } else {

                        /* VMOV */

                        switch (size) {

                        case 0:

                            tmp2 = neon_load_reg(rn, pass);

                            tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);

                            tcg_temp_free_i32(tmp2);

                            break;

                        case 1:

                            tmp2 = neon_load_reg(rn, pass);

                            tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);

                            tcg_temp_free_i32(tmp2);

                            break;

                        case 2:

                            break;

                        }

                        neon_store_reg(rn, pass, tmp);

                    }

                }

            } else { /* !dp */

                if ((insn & 0x6f) != 0x00)

                    return 1;

                rn = VFP_SREG_N(insn);

                if (insn & ARM_CP_RW_BIT) {

                    /* vfp->arm */

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

                        /* system register */

                        rn >>= 1;

                        switch (rn) {

                        case ARM_VFP_FPSID:

                            /* VFP2 allows access to FSID from userspace.

                               VFP3 restricts all id registers to privileged

                               accesses.  */

                            if (IS_USER(s)

                                && arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                                return 1;

                            }

                            tmp = load_cpu_field(vfp.xregs[rn]);

                            break;

                        case ARM_VFP_FPEXC:

                            if (IS_USER(s))

                                return 1;

                            tmp = load_cpu_field(vfp.xregs[rn]);

                            break;

                        case ARM_VFP_FPINST:

                        case ARM_VFP_FPINST2:

                            /* Not present in VFP3.  */

                            if (IS_USER(s)

                                || arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                                return 1;

                            }

                            tmp = load_cpu_field(vfp.xregs[rn]);

                            break;

                        case ARM_VFP_FPSCR:

                            if (rd == 15) {

                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);

                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);

                            } else {

                                tmp = tcg_temp_new_i32();

                                gen_helper_vfp_get_fpscr(tmp, cpu_env);

                            }

                            break;

                        case ARM_VFP_MVFR2:

                            if (!arm_dc_feature(s, ARM_FEATURE_V8)) {

                                return 1;

                            }

                            /* fall through */

                        case ARM_VFP_MVFR0:

                        case ARM_VFP_MVFR1:

                            if (IS_USER(s)

                                || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {

                                return 1;

                            }

                            tmp = load_cpu_field(vfp.xregs[rn]);

                            break;

                        default:

                            return 1;

                        }

                    } else {

                        gen_mov_F0_vreg(0, rn);

                        tmp = gen_vfp_mrs();

                    }

                    if (rd == 15) {

                        /* Set the 4 flag bits in the CPSR.  */

                        gen_set_nzcv(tmp);

                        tcg_temp_free_i32(tmp);

                    } else {

                        store_reg(s, rd, tmp);

                    }

                } else {

                    /* arm->vfp */

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

                        rn >>= 1;

                        /* system register */

                        switch (rn) {

                        case ARM_VFP_FPSID:

                        case ARM_VFP_MVFR0:

                        case ARM_VFP_MVFR1:

                            /* Writes are ignored.  */

                            break;

                        case ARM_VFP_FPSCR:

                            tmp = load_reg(s, rd);

                            gen_helper_vfp_set_fpscr(cpu_env, tmp);

                            tcg_temp_free_i32(tmp);

                            gen_lookup_tb(s);

                            break;

                        case ARM_VFP_FPEXC:

                            if (IS_USER(s))

                                return 1;

                            /* TODO: VFP subarchitecture support.

                             * For now, keep the EN bit only */

                            tmp = load_reg(s, rd);

                            tcg_gen_andi_i32(tmp, tmp, 1 << 30);

                            store_cpu_field(tmp, vfp.xregs[rn]);

                            gen_lookup_tb(s);

                            break;

                        case ARM_VFP_FPINST:

                        case ARM_VFP_FPINST2:

                            if (IS_USER(s)) {

                                return 1;

                            }

                            tmp = load_reg(s, rd);

                            store_cpu_field(tmp, vfp.xregs[rn]);

                            break;

                        default:

                            return 1;

                        }

                    } else {

                        tmp = load_reg(s, rd);

                        gen_vfp_msr(tmp);

                        gen_mov_vreg_F0(0, rn);

                    }

                }

            }

        } else {

            /* data processing */

            /* The opcode is in bits 23, 21, 20 and 6.  */

            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);

            if (dp) {

                if (op == 15) {

                    /* rn is opcode */

                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);

                } else {

                    /* rn is register number */

                    VFP_DREG_N(rn, insn);

                }

                if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||

                                 ((rn & 0x1e) == 0x6))) {

                    /* Integer or single/half precision destination.  */

                    rd = VFP_SREG_D(insn);

                } else {

                    VFP_DREG_D(rd, insn);

                }

                if (op == 15 &&

                    (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||

                     ((rn & 0x1e) == 0x4))) {

                    /* VCVT from int or half precision is always from S reg

                     * regardless of dp bit. VCVT with immediate frac_bits

                     * has same format as SREG_M.

                     */

                    rm = VFP_SREG_M(insn);

                } else {

                    VFP_DREG_M(rm, insn);

                }

            } else {

                rn = VFP_SREG_N(insn);

                if (op == 15 && rn == 15) {

                    /* Double precision destination.  */

                    VFP_DREG_D(rd, insn);

                } else {

                    rd = VFP_SREG_D(insn);

                }

                /* NB that we implicitly rely on the encoding for the frac_bits

                 * in VCVT of fixed to float being the same as that of an SREG_M

                 */

                rm = VFP_SREG_M(insn);

            }

            veclen = s->vec_len;

            if (op == 15 && rn > 3)

                veclen = 0;

            /* Shut up compiler warnings.  */

            delta_m = 0;

            delta_d = 0;

            bank_mask = 0;

            if (veclen > 0) {

                if (dp)

                    bank_mask = 0xc;

                else

                    bank_mask = 0x18;

                /* Figure out what type of vector operation this is.  */

                if ((rd & bank_mask) == 0) {

                    /* scalar */

                    veclen = 0;

                } else {

                    if (dp)

                        delta_d = (s->vec_stride >> 1) + 1;

                    else

                        delta_d = s->vec_stride + 1;

                    if ((rm & bank_mask) == 0) {

                        /* mixed scalar/vector */

                        delta_m = 0;

                    } else {

                        /* vector */

                        delta_m = delta_d;

                    }

                }

            }

            /* Load the initial operands.  */

            if (op == 15) {

                switch (rn) {

                case 16:

                case 17:

                    /* Integer source */

                    gen_mov_F0_vreg(0, rm);

                    break;

                case 8:

                case 9:

                    /* Compare */

                    gen_mov_F0_vreg(dp, rd);

                    gen_mov_F1_vreg(dp, rm);

                    break;

                case 10:

                case 11:

                    /* Compare with zero */

                    gen_mov_F0_vreg(dp, rd);

                    gen_vfp_F1_ld0(dp);

                    break;

                case 20:

                case 21:

                case 22:

                case 23:

                case 28:

                case 29:

                case 30:

                case 31:

                    /* Source and destination the same.  */

                    gen_mov_F0_vreg(dp, rd);

                    break;

                case 4:

                case 5:

                case 6:

                case 7:

                    /* VCVTB, VCVTT: only present with the halfprec extension

                     * UNPREDICTABLE if bit 8 is set prior to ARMv8

                     * (we choose to UNDEF)

                     */

                    if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||

                        !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {

                        return 1;

                    }

                    if (!extract32(rn, 1, 1)) {

                        /* Half precision source.  */

                        gen_mov_F0_vreg(0, rm);

                        break;

                    }

                    /* Otherwise fall through */

                default:

                    /* One source operand.  */

                    gen_mov_F0_vreg(dp, rm);

                    break;

                }

            } else {

                /* Two source operands.  */

                gen_mov_F0_vreg(dp, rn);

                gen_mov_F1_vreg(dp, rm);

            }

            for (;;) {

                /* Perform the calculation.  */

                switch (op) {

                case 0: /* VMLA: fd + (fn * fm) */

                    /* Note that order of inputs to the add matters for NaNs */

                    gen_vfp_F1_mul(dp);

                    gen_mov_F0_vreg(dp, rd);

                    gen_vfp_add(dp);

                    break;

                case 1: /* VMLS: fd + -(fn * fm) */

                    gen_vfp_mul(dp);

                    gen_vfp_F1_neg(dp);

                    gen_mov_F0_vreg(dp, rd);

                    gen_vfp_add(dp);

                    break;

                case 2: /* VNMLS: -fd + (fn * fm) */

                    /* Note that it isn't valid to replace (-A + B) with (B - A)

                     * or similar plausible looking simplifications

                     * because this will give wrong results for NaNs.

                     */

                    gen_vfp_F1_mul(dp);

                    gen_mov_F0_vreg(dp, rd);

                    gen_vfp_neg(dp);

                    gen_vfp_add(dp);

                    break;

                case 3: /* VNMLA: -fd + -(fn * fm) */

                    gen_vfp_mul(dp);

                    gen_vfp_F1_neg(dp);

                    gen_mov_F0_vreg(dp, rd);

                    gen_vfp_neg(dp);

                    gen_vfp_add(dp);

                    break;

                case 4: /* mul: fn * fm */

                    gen_vfp_mul(dp);

                    break;

                case 5: /* nmul: -(fn * fm) */

                    gen_vfp_mul(dp);

                    gen_vfp_neg(dp);

                    break;

                case 6: /* add: fn + fm */

                    gen_vfp_add(dp);

                    break;

                case 7: /* sub: fn - fm */

                    gen_vfp_sub(dp);

                    break;

                case 8: /* div: fn / fm */

                    gen_vfp_div(dp);

                    break;

                case 10: /* VFNMA : fd = muladd(-fd,  fn, fm) */

                case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */

                case 12: /* VFMA  : fd = muladd( fd,  fn, fm) */

                case 13: /* VFMS  : fd = muladd( fd, -fn, fm) */

                    /* These are fused multiply-add, and must be done as one

                     * floating point operation with no rounding between the

                     * multiplication and addition steps.

                     * NB that doing the negations here as separate steps is

                     * correct : an input NaN should come out with its sign bit

                     * flipped if it is a negated-input.

                     */

                    if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {

                        return 1;

                    }

                    if (dp) {

                        TCGv_ptr fpst;

                        TCGv_i64 frd;

                        if (op & 1) {

                            /* VFNMS, VFMS */

                            gen_helper_vfp_negd(cpu_F0d, cpu_F0d);

                        }

                        frd = tcg_temp_new_i64();

                        tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));

                        if (op & 2) {

                            /* VFNMA, VFNMS */

                            gen_helper_vfp_negd(frd, frd);

                        }

                        fpst = get_fpstatus_ptr(0);

                        gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,

                                               cpu_F1d, frd, fpst);

                        tcg_temp_free_ptr(fpst);

                        tcg_temp_free_i64(frd);

                    } else {

                        TCGv_ptr fpst;

                        TCGv_i32 frd;

                        if (op & 1) {

                            /* VFNMS, VFMS */

                            gen_helper_vfp_negs(cpu_F0s, cpu_F0s);

                        }

                        frd = tcg_temp_new_i32();

                        tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));

                        if (op & 2) {

                            gen_helper_vfp_negs(frd, frd);

                        }

                        fpst = get_fpstatus_ptr(0);

                        gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,

                                               cpu_F1s, frd, fpst);

                        tcg_temp_free_ptr(fpst);

                        tcg_temp_free_i32(frd);

                    }

                    break;

                case 14: /* fconst */

                    if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                        return 1;

                    }

                    n = (insn << 12) & 0x80000000;

                    i = ((insn >> 12) & 0x70) | (insn & 0xf);

                    if (dp) {

                        if (i & 0x40)

                            i |= 0x3f80;

                        else

                            i |= 0x4000;

                        n |= i << 16;

                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);

                    } else {

                        if (i & 0x40)

                            i |= 0x780;

                        else

                            i |= 0x800;

                        n |= i << 19;

                        tcg_gen_movi_i32(cpu_F0s, n);

                    }

                    break;

                case 15: /* extension space */

                    switch (rn) {

                    case 0: /* cpy */

                        /* no-op */

                        break;

                    case 1: /* abs */

                        gen_vfp_abs(dp);

                        break;

                    case 2: /* neg */

                        gen_vfp_neg(dp);

                        break;

                    case 3: /* sqrt */

                        gen_vfp_sqrt(dp);

                        break;

                    case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */

                        tmp = gen_vfp_mrs();

                        tcg_gen_ext16u_i32(tmp, tmp);

                        if (dp) {

                            gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,

                                                           cpu_env);

                        } else {

                            gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,

                                                           cpu_env);

                        }

                        tcg_temp_free_i32(tmp);

                        break;

                    case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */

                        tmp = gen_vfp_mrs();

                        tcg_gen_shri_i32(tmp, tmp, 16);

                        if (dp) {

                            gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,

                                                           cpu_env);

                        } else {

                            gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,

                                                           cpu_env);

                        }

                        tcg_temp_free_i32(tmp);

                        break;

                    case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */

                        tmp = tcg_temp_new_i32();

                        if (dp) {

                            gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,

                                                           cpu_env);

                        } else {

                            gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,

                                                           cpu_env);

                        }

                        gen_mov_F0_vreg(0, rd);

                        tmp2 = gen_vfp_mrs();

                        tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

                        tcg_gen_or_i32(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                        gen_vfp_msr(tmp);

                        break;

                    case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */

                        tmp = tcg_temp_new_i32();

                        if (dp) {

                            gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,

                                                           cpu_env);

                        } else {

                            gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,

                                                           cpu_env);

                        }

                        tcg_gen_shli_i32(tmp, tmp, 16);

                        gen_mov_F0_vreg(0, rd);

                        tmp2 = gen_vfp_mrs();

                        tcg_gen_ext16u_i32(tmp2, tmp2);

                        tcg_gen_or_i32(tmp, tmp, tmp2);

                        tcg_temp_free_i32(tmp2);

                        gen_vfp_msr(tmp);

                        break;

                    case 8: /* cmp */

                        gen_vfp_cmp(dp);

                        break;

                    case 9: /* cmpe */

                        gen_vfp_cmpe(dp);

                        break;

                    case 10: /* cmpz */

                        gen_vfp_cmp(dp);

                        break;

                    case 11: /* cmpez */

                        gen_vfp_F1_ld0(dp);

                        gen_vfp_cmpe(dp);

                        break;

                    case 12: /* vrintr */

                    {

                        TCGv_ptr fpst = get_fpstatus_ptr(0);

                        if (dp) {

                            gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);

                        } else {

                            gen_helper_rints(cpu_F0s, cpu_F0s, fpst);

                        }

                        tcg_temp_free_ptr(fpst);

                        break;

                    }

                    case 13: /* vrintz */

                    {

                        TCGv_ptr fpst = get_fpstatus_ptr(0);

                        TCGv_i32 tcg_rmode;

                        tcg_rmode = tcg_const_i32(float_round_to_zero);

                        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);

                        if (dp) {

                            gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);

                        } else {

                            gen_helper_rints(cpu_F0s, cpu_F0s, fpst);

                        }

                        gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);

                        tcg_temp_free_i32(tcg_rmode);

                        tcg_temp_free_ptr(fpst);

                        break;

                    }

                    case 14: /* vrintx */

                    {

                        TCGv_ptr fpst = get_fpstatus_ptr(0);

                        if (dp) {

                            gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);

                        } else {

                            gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);

                        }

                        tcg_temp_free_ptr(fpst);

                        break;

                    }

                    case 15: /* single<->double conversion */

                        if (dp)

                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);

                        else

                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);

                        break;

                    case 16: /* fuito */

                        gen_vfp_uito(dp, 0);

                        break;

                    case 17: /* fsito */

                        gen_vfp_sito(dp, 0);

                        break;

                    case 20: /* fshto */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_shto(dp, 16 - rm, 0);

                        break;

                    case 21: /* fslto */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_slto(dp, 32 - rm, 0);

                        break;

                    case 22: /* fuhto */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_uhto(dp, 16 - rm, 0);

                        break;

                    case 23: /* fulto */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_ulto(dp, 32 - rm, 0);

                        break;

                    case 24: /* ftoui */

                        gen_vfp_toui(dp, 0);

                        break;

                    case 25: /* ftouiz */

                        gen_vfp_touiz(dp, 0);

                        break;

                    case 26: /* ftosi */

                        gen_vfp_tosi(dp, 0);

                        break;

                    case 27: /* ftosiz */

                        gen_vfp_tosiz(dp, 0);

                        break;

                    case 28: /* ftosh */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_tosh(dp, 16 - rm, 0);

                        break;

                    case 29: /* ftosl */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_tosl(dp, 32 - rm, 0);

                        break;

                    case 30: /* ftouh */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_touh(dp, 16 - rm, 0);

                        break;

                    case 31: /* ftoul */

                        if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {

                            return 1;

                        }

                        gen_vfp_toul(dp, 32 - rm, 0);

                        break;

                    default: /* undefined */

                        return 1;

                    }

                    break;

                default: /* undefined */

                    return 1;

                }

                /* Write back the result.  */

                if (op == 15 && (rn >= 8 && rn <= 11)) {

                    /* Comparison, do nothing.  */

                } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||

                                              (rn & 0x1e) == 0x6)) {

                    /* VCVT double to int: always integer result.

                     * VCVT double to half precision is always a single

                     * precision result.

                     */

                    gen_mov_vreg_F0(0, rd);

                } else if (op == 15 && rn == 15) {

                    /* conversion */

                    gen_mov_vreg_F0(!dp, rd);

                } else {

                    gen_mov_vreg_F0(dp, rd);

                }

                /* break out of the loop if we have finished  */

                if (veclen == 0)

                    break;

                if (op == 15 && delta_m == 0) {

                    /* single source one-many */

                    while (veclen--) {

                        rd = ((rd + delta_d) & (bank_mask - 1))

                             | (rd & bank_mask);

                        gen_mov_vreg_F0(dp, rd);

                    }

                    break;

                }

                /* Setup the next operands.  */

                veclen--;

                rd = ((rd + delta_d) & (bank_mask - 1))

                     | (rd & bank_mask);

                if (op == 15) {

                    /* One source operand.  */

                    rm = ((rm + delta_m) & (bank_mask - 1))

                         | (rm & bank_mask);

                    gen_mov_F0_vreg(dp, rm);

                } else {

                    /* Two source operands.  */

                    rn = ((rn + delta_d) & (bank_mask - 1))

                         | (rn & bank_mask);

                    gen_mov_F0_vreg(dp, rn);

                    if (delta_m) {

                        rm = ((rm + delta_m) & (bank_mask - 1))

                             | (rm & bank_mask);

                        gen_mov_F1_vreg(dp, rm);

                    }

                }

            }

        }

        break;

    case 0xc:

    case 0xd:

        if ((insn & 0x03e00000) == 0x00400000) {

            /* two-register transfer */

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

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

            if (dp) {

                VFP_DREG_M(rm, insn);

            } else {

                rm = VFP_SREG_M(insn);

            }

            if (insn & ARM_CP_RW_BIT) {

                /* vfp->arm */

                if (dp) {

                    gen_mov_F0_vreg(0, rm * 2);

                    tmp = gen_vfp_mrs();

                    store_reg(s, rd, tmp);

                    gen_mov_F0_vreg(0, rm * 2 + 1);

                    tmp = gen_vfp_mrs();

                    store_reg(s, rn, tmp);

                } else {

                    gen_mov_F0_vreg(0, rm);

                    tmp = gen_vfp_mrs();

                    store_reg(s, rd, tmp);

                    gen_mov_F0_vreg(0, rm + 1);

                    tmp = gen_vfp_mrs();

                    store_reg(s, rn, tmp);

                }

            } else {

                /* arm->vfp */

                if (dp) {

                    tmp = load_reg(s, rd);

                    gen_vfp_msr(tmp);

                    gen_mov_vreg_F0(0, rm * 2);

                    tmp = load_reg(s, rn);

                    gen_vfp_msr(tmp);

                    gen_mov_vreg_F0(0, rm * 2 + 1);

                } else {

                    tmp = load_reg(s, rd);

                    gen_vfp_msr(tmp);

                    gen_mov_vreg_F0(0, rm);

                    tmp = load_reg(s, rn);

                    gen_vfp_msr(tmp);

                    gen_mov_vreg_F0(0, rm + 1);

                }

            }

        } else {

            /* Load/store */

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

            if (dp)

                VFP_DREG_D(rd, insn);

            else

                rd = VFP_SREG_D(insn);

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

                /* Single load/store */

                offset = (insn & 0xff) << 2;

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

                    offset = -offset;

                if (s->thumb && rn == 15) {

                    /* This is actually UNPREDICTABLE */

                    addr = tcg_temp_new_i32();

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

                } else {

                    addr = load_reg(s, rn);

                }

                tcg_gen_addi_i32(addr, addr, offset);

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

                    gen_vfp_ld(s, dp, addr);

                    gen_mov_vreg_F0(dp, rd);

                } else {

                    gen_mov_F0_vreg(dp, rd);

                    gen_vfp_st(s, dp, addr);

                }

                tcg_temp_free_i32(addr);

            } else {

                /* load/store multiple */

                int w = insn & (1 << 21);

                if (dp)

                    n = (insn >> 1) & 0x7f;

                else

                    n = insn & 0xff;

                if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {

                    /* P == U , W == 1  => UNDEF */

                    return 1;

                }

                if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {

                    /* UNPREDICTABLE cases for bad immediates: we choose to

                     * UNDEF to avoid generating huge numbers of TCG ops

                     */

                    return 1;

                }

                if (rn == 15 && w) {

                    /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */

                    return 1;

                }

                if (s->thumb && rn == 15) {

                    /* This is actually UNPREDICTABLE */

                    addr = tcg_temp_new_i32();

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

                } else {

                    addr = load_reg(s, rn);

                }

                if (insn & (1 << 24)) /* pre-decrement */

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

                if (dp)

                    offset = 8;

                else

                    offset = 4;

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

                    if (insn & ARM_CP_RW_BIT) {

                        /* load */

                        gen_vfp_ld(s, dp, addr);

                        gen_mov_vreg_F0(dp, rd + i);

                    } else {

                        /* store */

                        gen_mov_F0_vreg(dp, rd + i);

                        gen_vfp_st(s, dp, addr);

                    }

                    tcg_gen_addi_i32(addr, addr, offset);

                }

                if (w) {

                    /* writeback */

                    if (insn & (1 << 24))

                        offset = -offset * n;

                    else if (dp && (insn & 1))

                        offset = 4;

                    else

                        offset = 0;

                    if (offset != 0)

                        tcg_gen_addi_i32(addr, addr, offset);

                    store_reg(s, rn, addr);

                } else {

                    tcg_temp_free_i32(addr);

                }

            }

        }

        break;

    default:

        /* Should never happen.  */

        return 1;

    }

    return 0;

}


uint32_t cpu_mips_get_random (CPUMIPSState *env)

{

    static uint32_t seed = 1;

    static uint32_t prev_idx = 0;

    uint32_t idx;

    /* Don't return same value twice, so get another value */

    do {

        /* Use a simple algorithm of Linear Congruential Generator

         * from ISO/IEC 9899 standard. */

        seed = 1103515245 * seed + 12345;

        idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) +

              env->CP0_Wired;

    } while (idx == prev_idx);

    prev_idx = idx;

    return idx;

}


void ppc_hash64_store_hpte(PowerPCCPU *cpu,

                           target_ulong pte_index,

                           target_ulong pte0, target_ulong pte1)

{

    CPUPPCState *env = &cpu->env;

    if (env->external_htab == MMU_HASH64_KVM_MANAGED_HPT) {

        kvmppc_hash64_write_pte(env, pte_index, pte0, pte1);

        return;

    }

    pte_index *= HASH_PTE_SIZE_64;

    if (env->external_htab) {

        stq_p(env->external_htab + pte_index, pte0);

        stq_p(env->external_htab + pte_index + HASH_PTE_SIZE_64 / 2, pte1);

    } else {

        stq_phys(CPU(cpu)->as, env->htab_base + pte_index, pte0);

        stq_phys(CPU(cpu)->as,

                 env->htab_base + pte_index + HASH_PTE_SIZE_64 / 2, pte1);

    }

}


static uint64_t softusb_read(void *opaque, target_phys_addr_t addr,

                             unsigned size)

{

    MilkymistSoftUsbState *s = opaque;

    uint32_t r = 0;

    addr >>= 2;

    switch (addr) {

    case R_CTRL:

        r = s->regs[addr];

        break;

    default:

        error_report("milkymist_softusb: read access to unknown register 0x"

                TARGET_FMT_plx, addr << 2);

        break;

    }

    trace_milkymist_softusb_memory_read(addr << 2, r);

    return r;

}


GuestExec *qmp_guest_exec(const char *path,

                       bool has_arg, strList *arg,

                       bool has_env, strList *env,

                       bool has_input_data, const char *input_data,

                       bool has_capture_output, bool capture_output,

                       Error **err)

{

    GPid pid;

    GuestExec *ge = NULL;

    GuestExecInfo *gei;

    char **argv, **envp;

    strList arglist;

    gboolean ret;

    GError *gerr = NULL;

    gint in_fd, out_fd, err_fd;

    GIOChannel *in_ch, *out_ch, *err_ch;

    GSpawnFlags flags;

    bool has_output = (has_capture_output && capture_output);

    arglist.value = (char *)path;

    arglist.next = has_arg ? arg : NULL;

    argv = guest_exec_get_args(&arglist, true);

    envp = has_env ? guest_exec_get_args(env, false) : NULL;

    flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD;

#if GLIB_CHECK_VERSION(2, 33, 2)

    flags |= G_SPAWN_SEARCH_PATH_FROM_ENVP;

#endif

    if (!has_output) {

        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;

    }

    ret = g_spawn_async_with_pipes(NULL, argv, envp, flags,

            guest_exec_task_setup, NULL, &pid, has_input_data ? &in_fd : NULL,

            has_output ? &out_fd : NULL, has_output ? &err_fd : NULL, &gerr);

    if (!ret) {

        error_setg(err, QERR_QGA_COMMAND_FAILED, gerr->message);

        g_error_free(gerr);

        goto done;

    }

    ge = g_new0(GuestExec, 1);

    ge->pid = gpid_to_int64(pid);

    gei = guest_exec_info_add(pid);

    gei->has_output = has_output;

    g_child_watch_add(pid, guest_exec_child_watch, gei);

    if (has_input_data) {

        gei->in.data = g_base64_decode(input_data, &gei->in.size);

#ifdef G_OS_WIN32

        in_ch = g_io_channel_win32_new_fd(in_fd);

#else

        in_ch = g_io_channel_unix_new(in_fd);

#endif

        g_io_channel_set_encoding(in_ch, NULL, NULL);

        g_io_channel_set_buffered(in_ch, false);

        g_io_channel_set_flags(in_ch, G_IO_FLAG_NONBLOCK, NULL);

        g_io_add_watch(in_ch, G_IO_OUT, guest_exec_input_watch, &gei->in);

    }

    if (has_output) {

#ifdef G_OS_WIN32

        out_ch = g_io_channel_win32_new_fd(out_fd);

        err_ch = g_io_channel_win32_new_fd(err_fd);

#else

        out_ch = g_io_channel_unix_new(out_fd);

        err_ch = g_io_channel_unix_new(err_fd);

#endif

        g_io_channel_set_encoding(out_ch, NULL, NULL);

        g_io_channel_set_encoding(err_ch, NULL, NULL);

        g_io_channel_set_buffered(out_ch, false);

        g_io_channel_set_buffered(err_ch, false);

        g_io_add_watch(out_ch, G_IO_IN | G_IO_HUP,

                guest_exec_output_watch, &gei->out);

        g_io_add_watch(err_ch, G_IO_IN | G_IO_HUP,

                guest_exec_output_watch, &gei->err);

    }

done:

    g_free(argv);

    g_free(envp);

    return ge;

}


static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)

{

    CUDAState *s = opaque;

    uint32_t val;

    addr = (addr >> 9) & 0xf;

    switch(addr) {

    case 0:

        val = s->b;

        break;

    case 1:

        val = s->a;

        break;

    case 2:

        val = s->dirb;

        break;

    case 3:

        val = s->dira;

        break;

    case 4:

        val = get_counter(&s->timers[0]) & 0xff;

        s->ifr &= ~T1_INT;

        cuda_update_irq(s);

        break;

    case 5:

        val = get_counter(&s->timers[0]) >> 8;

        cuda_update_irq(s);

        break;

    case 6:

        val = s->timers[0].latch & 0xff;

        break;

    case 7:

        /* XXX: check this */

        val = (s->timers[0].latch >> 8) & 0xff;

        break;

    case 8:

        val = get_counter(&s->timers[1]) & 0xff;

        s->ifr &= ~T2_INT;

        break;

    case 9:

        val = get_counter(&s->timers[1]) >> 8;

        break;

    case 10:

        val = s->sr;

        s->ifr &= ~SR_INT;

        cuda_update_irq(s);

        break;

    case 11:

        val = s->acr;

        break;

    case 12:

        val = s->pcr;

        break;

    case 13:

        val = s->ifr;

        if (s->ifr & s->ier)

            val |= 0x80;

        break;

    case 14:

        val = s->ier | 0x80;

        break;

    default:

    case 15:

        val = s->anh;

        break;

    }

    if (addr != 13 || val != 0) {

        CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);

    }

    return val;

}


assigned_dev_msix_mmio_read(void *opaque, target_phys_addr_t addr,

                            unsigned size)

{

    AssignedDevice *adev = opaque;

    uint64_t val;

    memcpy(&val, (void *)((uint8_t *)adev->msix_table + addr), size);

    return val;

}


void ff_jpegls_init_state(JLSState *state){

    int i;

    state->twonear = state->near * 2 + 1;

    state->range = ((state->maxval + state->twonear - 1) / state->twonear) + 1;

    // QBPP = ceil(log2(RANGE))

    for(state->qbpp = 0; (1 << state->qbpp) < state->range; state->qbpp++);

    if(state->bpp < 8)

        state->limit = 16 + 2 * state->bpp - state->qbpp;

    else

        state->limit = (4 * state->bpp) - state->qbpp;

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

        state->A[i] = FFMAX((state->range + 32) >> 6, 2);

        state->N[i] = 1;

    }

}


static int rtl8139_can_receive(void *opaque)

{

    RTL8139State *s = opaque;

    int avail;

    /* Receive (drop) packets if card is disabled.  */

    if (!s->clock_enabled)

      return 1;

    if (!rtl8139_receiver_enabled(s))

      return 1;

    if (rtl8139_cp_receiver_enabled(s)) {

        /* ??? Flow control not implemented in c+ mode.

           This is a hack to work around slirp deficiencies anyway.  */

        return 1;

    } else {

        avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr,

                     s->RxBufferSize);

        return (avail == 0 || avail >= 1514);

    }

}


TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)

{

    TC6393xbState *s;

    DriveInfo *nand;

    static const MemoryRegionOps tc6393xb_ops = {

        .read = tc6393xb_readb,

        .write = tc6393xb_writeb,

        .endianness = DEVICE_NATIVE_ENDIAN,

        .impl = {

            .min_access_size = 1,

            .max_access_size = 1,

        },

    };

    s = (TC6393xbState *) g_malloc0(sizeof(TC6393xbState));

    s->irq = irq;

    s->gpio_in = qemu_allocate_irqs(tc6393xb_gpio_set, s, TC6393XB_GPIOS);

    s->l3v = *qemu_allocate_irqs(tc6393xb_l3v, s, 1);

    s->blanked = 1;

    s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);

    nand = drive_get(IF_MTD, 0, 0);

    s->flash = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,

                         NAND_MFR_TOSHIBA, 0x76);

    memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000);

    memory_region_add_subregion(sysmem, base, &s->iomem);

    memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000,

                           &error_abort);

    vmstate_register_ram_global(&s->vram);

    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);

    memory_region_add_subregion(sysmem, base + 0x100000, &s->vram);

    s->scr_width = 480;

    s->scr_height = 640;

    s->con = graphic_console_init(NULL, 0, &tc6393xb_gfx_ops, s);

    return s;

}


int coroutine_fn bdrv_co_copy_on_readv(BlockDriverState *bs,

    int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)

{

    trace_bdrv_co_copy_on_readv(bs, sector_num, nb_sectors);

    return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov,

                            BDRV_REQ_COPY_ON_READ);

}


static void v9fs_lcreate(void *opaque)

{

    int32_t dfid, flags, mode;

    gid_t gid;

    ssize_t err = 0;

    ssize_t offset = 7;

    V9fsString name;

    V9fsFidState *fidp;

    struct stat stbuf;

    V9fsQID qid;

    int32_t iounit;

    V9fsPDU *pdu = opaque;

    pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,

                  &mode, &gid);

    trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);

    fidp = get_fid(pdu, dfid);

    if (fidp == NULL) {

        err = -ENOENT;

        goto out_nofid;

    }

    flags = get_dotl_openflags(pdu->s, flags);

    err = v9fs_co_open2(pdu, fidp, &name, gid,

                        flags | O_CREAT, mode, &stbuf);

    if (err < 0) {

        goto out;

    }

    fidp->fid_type = P9_FID_FILE;

    fidp->open_flags = flags;

    if (flags & O_EXCL) {

        /*

         * We let the host file system do O_EXCL check

         * We should not reclaim such fd

         */

        fidp->flags |= FID_NON_RECLAIMABLE;

    }

    iounit =  get_iounit(pdu, &fidp->path);

    stat_to_qid(&stbuf, &qid);

    offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit);

    err = offset;

    trace_v9fs_lcreate_return(pdu->tag, pdu->id,

                              qid.type, qid.version, qid.path, iounit);

out:

    put_fid(pdu, fidp);

out_nofid:

    complete_pdu(pdu->s, pdu, err);

    v9fs_string_free(&name);

}


void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)

{

    if (kvm_enabled()) {

        kvm_s390_virtio_irq(cpu, config_change, token);

    } else {

        cpu_inject_ext(cpu, EXT_VIRTIO, config_change, token);

    }

}


static int aiocb_needs_copy(struct qemu_paiocb *aiocb)

{

    if (aiocb->aio_flags & QEMU_AIO_SECTOR_ALIGNED) {

        int i;

        for (i = 0; i < aiocb->aio_niov; i++)

            if ((uintptr_t) aiocb->aio_iov[i].iov_base % 512)

                return 1;

    }

    return 0;

}


static void virtio_net_class_init(ObjectClass *klass, void *data)

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_net_init_pci;

    k->exit = virtio_net_exit_pci;

    k->romfile = "pxe-virtio.rom";

    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;

    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;

    k->revision = VIRTIO_PCI_ABI_VERSION;

    k->class_id = PCI_CLASS_NETWORK_ETHERNET;

    dc->alias = "virtio-net";

    dc->reset = virtio_pci_reset;

    dc->props = virtio_net_properties;

}


static int jpg_decode_data(JPGContext *c, int width, int height,

                           const uint8_t *src, int src_size,

                           uint8_t *dst, int dst_stride,

                           const uint8_t *mask, int mask_stride, int num_mbs,

                           int swapuv)

{

    GetBitContext gb;

    int mb_w, mb_h, mb_x, mb_y, i, j;

    int bx, by;

    int unesc_size;

    int ret;

    if ((ret = av_reallocp(&c->buf,

                           src_size + FF_INPUT_BUFFER_PADDING_SIZE)) < 0)

        return ret;

    jpg_unescape(src, src_size, c->buf, &unesc_size);

    memset(c->buf + unesc_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    init_get_bits8(&gb, c->buf, unesc_size);

    width = FFALIGN(width, 16);

    mb_w  =  width        >> 4;

    mb_h  = (height + 15) >> 4;

    if (!num_mbs)

        num_mbs = mb_w * mb_h * 4;

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

        c->prev_dc[i] = 1024;

    bx =

    by = 0;

    c->bdsp.clear_blocks(c->block[0]);

    for (mb_y = 0; mb_y < mb_h; mb_y++) {

        for (mb_x = 0; mb_x < mb_w; mb_x++) {

            if (mask && !mask[mb_x * 2] && !mask[mb_x * 2 + 1] &&

                !mask[mb_x * 2 +     mask_stride] &&

                !mask[mb_x * 2 + 1 + mask_stride]) {

                bx += 16;

                continue;

            }

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

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

                    if (mask && !mask[mb_x * 2 + i + j * mask_stride])

                        continue;

                    num_mbs--;

                    if ((ret = jpg_decode_block(c, &gb, 0,

                                                c->block[i + j * 2])) != 0)

                        return ret;

                    c->idsp.idct(c->block[i + j * 2]);

                }

            }

            for (i = 1; i < 3; i++) {

                if ((ret = jpg_decode_block(c, &gb, i, c->block[i + 3])) != 0)

                    return ret;

                c->idsp.idct(c->block[i + 3]);

            }

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

                uint8_t *out = dst + bx * 3 + (by + j) * dst_stride;

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

                    int Y, U, V;

                    Y = c->block[(j >> 3) * 2 + (i >> 3)][(i & 7) + (j & 7) * 8];

                    U = c->block[4 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;

                    V = c->block[5 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;

                    yuv2rgb(out + i * 3, Y, U, V);

                }

            }

            if (!num_mbs)

                return 0;

            bx += 16;

        }

        bx  = 0;

        by += 16;

        if (mask)

            mask += mask_stride * 2;

    }

    return 0;

}


static inline void upmix_mono_to_stereo(AC3DecodeContext *ctx)

{

    int i;

    float (*output)[256] = ctx->audio_block.block_output;

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

        output[2][i] = output[1][i];

}


static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, int fd,

                            int fr, int fs, int ft)

{

    const char *opn = "flt3_arith";

    /* All of those work only on 64bit FPUs. */

    gen_op_cp1_64bitmode();

    switch (opc) {

    case OPC_ALNV_PS:

        GEN_LOAD_REG_TN(T0, fr);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        gen_op_float_alnv_ps();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "alnv.ps";

        break;

    case OPC_MADD_S:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        gen_op_float_muladd_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "madd.s";

        break;

    case OPC_MADD_D:

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        GEN_LOAD_FREG_FTN(DT2, fr);

        gen_op_float_muladd_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "madd.d";

        break;

    case OPC_MADD_PS:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        GEN_LOAD_FREG_FTN(WTH2, fr);

        gen_op_float_muladd_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "madd.ps";

        break;

    case OPC_MSUB_S:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        gen_op_float_mulsub_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "msub.s";

        break;

    case OPC_MSUB_D:

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        GEN_LOAD_FREG_FTN(DT2, fr);

        gen_op_float_mulsub_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "msub.d";

        break;

    case OPC_MSUB_PS:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        GEN_LOAD_FREG_FTN(WTH2, fr);

        gen_op_float_mulsub_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "msub.ps";

        break;

    case OPC_NMADD_S:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        gen_op_float_nmuladd_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "nmadd.s";

        break;

    case OPC_NMADD_D:

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        GEN_LOAD_FREG_FTN(DT2, fr);

        gen_op_float_nmuladd_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "nmadd.d";

        break;

    case OPC_NMADD_PS:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        GEN_LOAD_FREG_FTN(WTH2, fr);

        gen_op_float_nmuladd_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "nmadd.ps";

        break;

    case OPC_NMSUB_S:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        gen_op_float_nmulsub_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "nmsub.s";

        break;

    case OPC_NMSUB_D:

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        GEN_LOAD_FREG_FTN(DT2, fr);

        gen_op_float_nmulsub_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "nmsub.d";

        break;

    case OPC_NMSUB_PS:

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        GEN_LOAD_FREG_FTN(WT2, fr);

        GEN_LOAD_FREG_FTN(WTH2, fr);

        gen_op_float_nmulsub_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "nmsub.ps";

        break;

    default:

        MIPS_INVAL(opn);

        generate_exception (ctx, EXCP_RI);

        return;

    }

    MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],

               fregnames[fs], fregnames[ft]);

}


static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf)

{

    return s->ops->lstat(&s->ctx, path->data, stbuf);

}


static void test_source_timer_schedule(void)

{

    TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,

                           .max = 2,

                           .clock_type = QEMU_CLOCK_VIRTUAL };

    int pipefd[2];

    int64_t expiry;

    /* aio_poll will not block to wait for timers to complete unless it has

     * an fd to wait on. Fixing this breaks other tests. So create a dummy one.

     */

    g_assert(!qemu_pipe(pipefd));

    qemu_set_nonblock(pipefd[0]);

    qemu_set_nonblock(pipefd[1]);

    aio_set_fd_handler(ctx, pipefd[0],

                       dummy_io_handler_read, NULL, NULL);

    do {} while (g_main_context_iteration(NULL, false));

    aio_timer_init(ctx, &data.timer, data.clock_type,

                   SCALE_NS, timer_test_cb, &data);

    expiry = qemu_clock_get_ns(data.clock_type) +

        data.ns;

    timer_mod(&data.timer, expiry);

    g_assert_cmpint(data.n, ==, 0);

    g_usleep(1 * G_USEC_PER_SEC);

    g_assert_cmpint(data.n, ==, 0);

    g_assert(g_main_context_iteration(NULL, false));

    g_assert_cmpint(data.n, ==, 1);

    /* The comment above was not kidding when it said this wakes up itself */

    do {

        g_assert(g_main_context_iteration(NULL, true));

    } while (qemu_clock_get_ns(data.clock_type) <= expiry);

    g_usleep(1 * G_USEC_PER_SEC);

    g_main_context_iteration(NULL, false);

    g_assert_cmpint(data.n, ==, 2);

    aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);

    close(pipefd[0]);

    close(pipefd[1]);

    timer_del(&data.timer);

}


static void xenfv_machine_options(MachineClass *m)

{

    pc_common_machine_options(m);

    m->desc = "Xen Fully-virtualized PC";

    m->max_cpus = HVM_MAX_VCPUS;

    m->default_machine_opts = "accel=xen";

    m->hot_add_cpu = pc_hot_add_cpu;

}


static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)

{

    CharDriverState *chr = NULL;

    TCPCharDriver *s = NULL;

    int fd = -1;

    int is_listen;

    int is_waitconnect;

    int do_nodelay;

    int is_unix;

    int is_telnet;

    is_listen      = qemu_opt_get_bool(opts, "server", 0);

    is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);

    is_telnet      = qemu_opt_get_bool(opts, "telnet", 0);

    do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);

    is_unix        = qemu_opt_get(opts, "path") != NULL;

    if (!is_listen)

        is_waitconnect = 0;

    chr = g_malloc0(sizeof(CharDriverState));

    s = g_malloc0(sizeof(TCPCharDriver));

    if (is_unix) {

        if (is_listen) {

            fd = unix_listen_opts(opts);

        } else {

            fd = unix_connect_opts(opts);

        }

    } else {

        if (is_listen) {

            fd = inet_listen_opts(opts, 0, NULL);

        } else {

            fd = inet_connect_opts(opts, NULL);

        }

    }

    if (fd < 0) {

        goto fail;

    }

    if (!is_waitconnect)

        socket_set_nonblock(fd);

    s->connected = 0;

    s->fd = -1;

    s->listen_fd = -1;

    s->msgfd = -1;

    s->is_unix = is_unix;

    s->do_nodelay = do_nodelay && !is_unix;

    chr->opaque = s;

    chr->chr_write = tcp_chr_write;

    chr->chr_close = tcp_chr_close;

    chr->get_msgfd = tcp_get_msgfd;

    chr->chr_add_client = tcp_chr_add_client;

    if (is_listen) {

        s->listen_fd = fd;

        qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);

        if (is_telnet)

            s->do_telnetopt = 1;

    } else {

        s->connected = 1;

        s->fd = fd;

        socket_set_nodelay(fd);

        tcp_chr_connect(chr);

    }

    /* for "info chardev" monitor command */

    chr->filename = g_malloc(256);

    if (is_unix) {

        snprintf(chr->filename, 256, "unix:%s%s",

                 qemu_opt_get(opts, "path"),

                 qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");

    } else if (is_telnet) {

        snprintf(chr->filename, 256, "telnet:%s:%s%s",

                 qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"),

                 qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");

    } else {

        snprintf(chr->filename, 256, "tcp:%s:%s%s",

                 qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"),

                 qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");

    }

    if (is_listen && is_waitconnect) {

        printf("QEMU waiting for connection on: %s\n",

               chr->filename);

        tcp_chr_accept(chr);

        socket_set_nonblock(s->listen_fd);

    }

    return chr;

 fail:

    if (fd >= 0)

        closesocket(fd);

    g_free(s);

    g_free(chr);

    return NULL;

}


static void vfio_enable_intx_kvm(VFIODevice *vdev)

{

#ifdef CONFIG_KVM

    struct kvm_irqfd irqfd = {

        .fd = event_notifier_get_fd(&vdev->intx.interrupt),

        .gsi = vdev->intx.route.irq,

        .flags = KVM_IRQFD_FLAG_RESAMPLE,

    };

    struct vfio_irq_set *irq_set;

    int ret, argsz;

    int32_t *pfd;

    if (!kvm_irqfds_enabled() ||

        vdev->intx.route.mode != PCI_INTX_ENABLED ||

        !kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {

        return;

    }

    /* Get to a known interrupt state */

    qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);

    vfio_mask_intx(vdev);

    vdev->intx.pending = false;

    qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);

    /* Get an eventfd for resample/unmask */

    if (event_notifier_init(&vdev->intx.unmask, 0)) {

        error_report("vfio: Error: event_notifier_init failed eoi");

        goto fail;

    }

    /* KVM triggers it, VFIO listens for it */

    irqfd.resamplefd = event_notifier_get_fd(&vdev->intx.unmask);

    if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) {

        error_report("vfio: Error: Failed to setup resample irqfd: %m");

        goto fail_irqfd;

    }

    argsz = sizeof(*irq_set) + sizeof(*pfd);

    irq_set = g_malloc0(argsz);

    irq_set->argsz = argsz;

    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_UNMASK;

    irq_set->index = VFIO_PCI_INTX_IRQ_INDEX;

    irq_set->start = 0;

    irq_set->count = 1;

    pfd = (int32_t *)&irq_set->data;

    *pfd = irqfd.resamplefd;

    ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);

    g_free(irq_set);

    if (ret) {

        error_report("vfio: Error: Failed to setup INTx unmask fd: %m");

        goto fail_vfio;

    }

    /* Let'em rip */

    vfio_unmask_intx(vdev);

    vdev->intx.kvm_accel = true;

    DPRINTF("%s(%04x:%02x:%02x.%x) KVM INTx accel enabled\n",

            __func__, vdev->host.domain, vdev->host.bus,

            vdev->host.slot, vdev->host.function);

    return;

fail_vfio:

    irqfd.flags = KVM_IRQFD_FLAG_DEASSIGN;

    kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd);

fail_irqfd:

    event_notifier_cleanup(&vdev->intx.unmask);

fail:

    qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev);

    vfio_unmask_intx(vdev);

#endif

}


static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,

                               int sh, int mb)

{

    assert(TCG_TARGET_REG_BITS == 64);

    sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);

    mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));

    tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);

}


static int opt_list(void *obj, void *av_log_obj, char *unit)

{

    AVOption *opt=NULL;

    while((opt= av_next_option(obj, opt))){

        if(!(opt->flags & (AV_OPT_FLAG_ENCODING_PARAM|AV_OPT_FLAG_DECODING_PARAM)))

            continue;

        /* Don't print CONST's on level one.

         * Don't print anything but CONST's on level two.

         * Only print items from the requested unit.

         */

        if (!unit && opt->type==FF_OPT_TYPE_CONST)

            continue;

        else if (unit && opt->type!=FF_OPT_TYPE_CONST)

            continue;

        else if (unit && opt->type==FF_OPT_TYPE_CONST && strcmp(unit, opt->unit))

            continue;

        else if (unit && opt->type == FF_OPT_TYPE_CONST)

            av_log(av_log_obj, AV_LOG_INFO, "   %-15s ", opt->name);

        else

            av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name);

        switch( opt->type )

        {

            case FF_OPT_TYPE_FLAGS:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>" );

                break;

            case FF_OPT_TYPE_INT:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int>" );

                break;

            case FF_OPT_TYPE_INT64:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>" );

                break;

            case FF_OPT_TYPE_DOUBLE:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<double>" );

                break;

            case FF_OPT_TYPE_FLOAT:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<float>" );

                break;

            case FF_OPT_TYPE_STRING:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<string>" );

                break;

            case FF_OPT_TYPE_RATIONAL:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>" );

                break;

            case FF_OPT_TYPE_CONST:

            default:

                av_log( av_log_obj, AV_LOG_INFO, "%-7s ", "" );

                break;

        }

        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.');

        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.');

        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM   ) ? 'V' : '.');

        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM   ) ? 'A' : '.');

        av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.');

        if(opt->help)

            av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help);

        av_log(av_log_obj, AV_LOG_INFO, "\n");

        if (opt->unit && opt->type != FF_OPT_TYPE_CONST) {

            opt_list(obj, av_log_obj, opt->unit);

        }

    }

}


static int set_dirty_tracking(void)

{

    BlkMigDevState *bmds;

    int ret;

    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {

        bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,

                                                      NULL);

        if (!bmds->dirty_bitmap) {

            ret = -errno;

            goto fail;

        }

    }

    return 0;

fail:

    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {

        if (bmds->dirty_bitmap) {

            bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);

        }

    }

    return ret;

}


static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)

{

    s->tray_locked = buf[4] & 1;

    bdrv_lock_medium(s->bs, buf[4] & 1);

    ide_atapi_cmd_ok(s);

}


void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)

{

    int l;

    while (size > 0) {

        l = IO_BUF_SIZE - f->buf_index;

        if (l > size)

            l = size;

        memcpy(f->buf + f->buf_index, buf, l);

        f->buf_index += l;

        buf += l;

        size -= l;

        if (f->buf_index >= IO_BUF_SIZE)

            qemu_fflush(f);

    }

}


void cpu_exec_init_all(void)

{

#if !defined(CONFIG_USER_ONLY)

    qemu_mutex_init(&ram_list.mutex);

    memory_map_init();

    io_mem_init();

#endif

}


static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as)

{

    hwaddr base = vbi->memmap[VIRT_FW_CFG].base;

    hwaddr size = vbi->memmap[VIRT_FW_CFG].size;

    char *nodename;

    fw_cfg_init_mem_wide(base + 8, base, 8, base + 16, as);

    nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base);

    qemu_fdt_add_subnode(vbi->fdt, nodename);

    qemu_fdt_setprop_string(vbi->fdt, nodename,

                            "compatible", "qemu,fw-cfg-mmio");

    qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",

                                 2, base, 2, size);

    g_free(nodename);

}


int av_file_map(const char *filename, uint8_t **bufptr, size_t *size,

                int log_offset, void *log_ctx)

{

    FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };

    int err, fd = open(filename, O_RDONLY);

    struct stat st;

    av_unused void *ptr;

    off_t off_size;

    char errbuf[128];

    *bufptr = NULL;

    if (fd < 0) {

        err = AVERROR(errno);

        av_strerror(err, errbuf, sizeof(errbuf));

        av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf);

        return err;

    }

    if (fstat(fd, &st) < 0) {

        err = AVERROR(errno);

        av_strerror(err, errbuf, sizeof(errbuf));

        av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf);

        close(fd);

        return err;

    }

    off_size = st.st_size;

    if (off_size > SIZE_MAX) {

        av_log(&file_log_ctx, AV_LOG_ERROR,

               "File size for file '%s' is too big\n", filename);

        close(fd);

        return AVERROR(EINVAL);

    }

    *size = off_size;

#if HAVE_MMAP

    ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);

    if ((int)(ptr) == -1) {

        err = AVERROR(errno);

        av_strerror(err, errbuf, sizeof(errbuf));

        av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf);

        close(fd);

        return err;

    }

    *bufptr = ptr;

#elif HAVE_MAPVIEWOFFILE

    {

        HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);

        mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);

        if (!mh) {

            av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n");

            close(fd);

            return -1;

        }

        ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size);

        CloseHandle(mh);

        if (!ptr) {

            av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n");

            close(fd);

            return -1;

        }

        *bufptr = ptr;

    }

#else

    *bufptr = av_malloc(*size);

    if (!*bufptr) {

        av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n");

        close(fd);

        return AVERROR(ENOMEM);

    }

    read(fd, *bufptr, *size);

#endif

    close(fd);

    return 0;

}


static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGReg arg1,

                               int32_t arg2, int const_arg2, int label)

{

    tcg_out_cmp(s, arg1, arg2, const_arg2);

    tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label);

    tcg_out_nop(s);

}


static void test_flush(void)

{

    AHCIQState *ahci;

    ahci = ahci_boot_and_enable();

    ahci_test_flush(ahci);

    ahci_shutdown(ahci);

}


static void xtensa_lx200_init(MachineState *machine)

{

    static const LxBoardDesc lx200_board = {

        .flash_base = 0xf8000000,

        .flash_size = 0x01000000,

        .flash_sector_size = 0x20000,

        .sram_size = 0x2000000,

    };

    lx_init(&lx200_board, machine);

}


static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)

{

    unsigned int extimm = dc->tb_flags & IMM_FLAG;

    /* Should be set to one if r1 is used by loadstores.  */

    int stackprot = 0;

    /* All load/stores use ra.  */

    if (dc->ra == 1) {

        stackprot = 1;

    }

    /* Treat the common cases first.  */

    if (!dc->type_b) {

        /* If any of the regs is r0, return a ptr to the other.  */

        if (dc->ra == 0) {

            return &cpu_R[dc->rb];

        } else if (dc->rb == 0) {

            return &cpu_R[dc->ra];

        }

        if (dc->rb == 1) {

            stackprot = 1;

        }

        *t = tcg_temp_new();

        tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);

        if (stackprot) {

            gen_helper_stackprot(cpu_env, *t);

        }

        return t;

    }

    /* Immediate.  */

    if (!extimm) {

        if (dc->imm == 0) {

            return &cpu_R[dc->ra];

        }

        *t = tcg_temp_new();

        tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm));

        tcg_gen_add_tl(*t, cpu_R[dc->ra], *t);

    } else {

        *t = tcg_temp_new();

        tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));

    }

    if (stackprot) {

        gen_helper_stackprot(cpu_env, *t);

    }

    return t;

}


static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)

{

    int op1;

    int32_t r1, r2, r3;

    int32_t address, const16;

    int8_t b, const4;

    int32_t bpos;

    TCGv temp, temp2, temp3;

    op1 = MASK_OP_MAJOR(ctx->opcode);

    /* handle JNZ.T opcode only being 6 bit long */

    if (unlikely((op1 & 0x3f) == OPCM_32_BRN_JTT)) {

        op1 = OPCM_32_BRN_JTT;

    }

    switch (op1) {

/* ABS-format */

    case OPCM_32_ABS_LDW:

        decode_abs_ldw(env, ctx);

        break;

    case OPCM_32_ABS_LDB:

        decode_abs_ldb(env, ctx);

        break;

    case OPCM_32_ABS_LDMST_SWAP:

        decode_abs_ldst_swap(env, ctx);

        break;

    case OPCM_32_ABS_LDST_CONTEXT:

        decode_abs_ldst_context(env, ctx);

        break;

    case OPCM_32_ABS_STORE:

        decode_abs_store(env, ctx);

        break;

    case OPCM_32_ABS_STOREB_H:

        decode_abs_storeb_h(env, ctx);

        break;

    case OPC1_32_ABS_STOREQ:

        address = MASK_OP_ABS_OFF18(ctx->opcode);

        r1 = MASK_OP_ABS_S1D(ctx->opcode);

        temp = tcg_const_i32(EA_ABS_FORMAT(address));

        temp2 = tcg_temp_new();

        tcg_gen_shri_tl(temp2, cpu_gpr_d[r1], 16);

        tcg_gen_qemu_st_tl(temp2, temp, ctx->mem_idx, MO_LEUW);

        tcg_temp_free(temp2);

        tcg_temp_free(temp);

        break;

    case OPC1_32_ABS_LD_Q:

        address = MASK_OP_ABS_OFF18(ctx->opcode);

        r1 = MASK_OP_ABS_S1D(ctx->opcode);

        temp = tcg_const_i32(EA_ABS_FORMAT(address));

        tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUW);

        tcg_gen_shli_tl(cpu_gpr_d[r1], cpu_gpr_d[r1], 16);

        tcg_temp_free(temp);

        break;

    case OPC1_32_ABS_LEA:

        address = MASK_OP_ABS_OFF18(ctx->opcode);

        r1 = MASK_OP_ABS_S1D(ctx->opcode);

        tcg_gen_movi_tl(cpu_gpr_a[r1], EA_ABS_FORMAT(address));

        break;

/* ABSB-format */

    case OPC1_32_ABSB_ST_T:

        address = MASK_OP_ABS_OFF18(ctx->opcode);

        b = MASK_OP_ABSB_B(ctx->opcode);

        bpos = MASK_OP_ABSB_BPOS(ctx->opcode);

        temp = tcg_const_i32(EA_ABS_FORMAT(address));

        temp2 = tcg_temp_new();

        tcg_gen_qemu_ld_tl(temp2, temp, ctx->mem_idx, MO_UB);

        tcg_gen_andi_tl(temp2, temp2, ~(0x1u << bpos));

        tcg_gen_ori_tl(temp2, temp2, (b << bpos));

        tcg_gen_qemu_st_tl(temp2, temp, ctx->mem_idx, MO_UB);

        tcg_temp_free(temp);

        tcg_temp_free(temp2);

        break;

/* B-format */

    case OPC1_32_B_CALL:

    case OPC1_32_B_CALLA:

    case OPC1_32_B_J:

    case OPC1_32_B_JA:

    case OPC1_32_B_JL:

    case OPC1_32_B_JLA:

        address = MASK_OP_B_DISP24(ctx->opcode);

        gen_compute_branch(ctx, op1, 0, 0, 0, address);

        break;

/* Bit-format */

    case OPCM_32_BIT_ANDACC:

        decode_bit_andacc(env, ctx);

        break;

    case OPCM_32_BIT_LOGICAL_T1:

        decode_bit_logical_t(env, ctx);

        break;

    case OPCM_32_BIT_INSERT:

        decode_bit_insert(env, ctx);

        break;

    case OPCM_32_BIT_LOGICAL_T2:

        decode_bit_logical_t2(env, ctx);

        break;

    case OPCM_32_BIT_ORAND:

        decode_bit_orand(env, ctx);

        break;

    case OPCM_32_BIT_SH_LOGIC1:

        decode_bit_sh_logic1(env, ctx);

        break;

    case OPCM_32_BIT_SH_LOGIC2:

        decode_bit_sh_logic2(env, ctx);

        break;

    /* BO Format */

    case OPCM_32_BO_ADDRMODE_POST_PRE_BASE:

        decode_bo_addrmode_post_pre_base(env, ctx);

        break;

    case OPCM_32_BO_ADDRMODE_BITREVERSE_CIRCULAR:

        decode_bo_addrmode_bitreverse_circular(env, ctx);

        break;

    case OPCM_32_BO_ADDRMODE_LD_POST_PRE_BASE:

        decode_bo_addrmode_ld_post_pre_base(env, ctx);

        break;

    case OPCM_32_BO_ADDRMODE_LD_BITREVERSE_CIRCULAR:

        decode_bo_addrmode_ld_bitreverse_circular(env, ctx);

        break;

    case OPCM_32_BO_ADDRMODE_STCTX_POST_PRE_BASE:

        decode_bo_addrmode_stctx_post_pre_base(env, ctx);

        break;

    case OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR:

        decode_bo_addrmode_ldmst_bitreverse_circular(env, ctx);

        break;

/* BOL-format */

    case OPC1_32_BOL_LD_A_LONGOFF:

    case OPC1_32_BOL_LD_W_LONGOFF:

    case OPC1_32_BOL_LEA_LONGOFF:

    case OPC1_32_BOL_ST_W_LONGOFF:

    case OPC1_32_BOL_ST_A_LONGOFF:

        decode_bol_opc(env, ctx, op1);

        break;

/* BRC Format */

    case OPCM_32_BRC_EQ_NEQ:

    case OPCM_32_BRC_GE:

    case OPCM_32_BRC_JLT:

    case OPCM_32_BRC_JNE:

        const4 = MASK_OP_BRC_CONST4_SEXT(ctx->opcode);

        address = MASK_OP_BRC_DISP15_SEXT(ctx->opcode);

        r1 = MASK_OP_BRC_S1(ctx->opcode);

        gen_compute_branch(ctx, op1, r1, 0, const4, address);

        break;

/* BRN Format */

    case OPCM_32_BRN_JTT:

        address = MASK_OP_BRN_DISP15_SEXT(ctx->opcode);

        r1 = MASK_OP_BRN_S1(ctx->opcode);

        gen_compute_branch(ctx, op1, r1, 0, 0, address);

        break;

/* BRR Format */

    case OPCM_32_BRR_EQ_NEQ:

    case OPCM_32_BRR_ADDR_EQ_NEQ:

    case OPCM_32_BRR_GE:

    case OPCM_32_BRR_JLT:

    case OPCM_32_BRR_JNE:

    case OPCM_32_BRR_JNZ:

    case OPCM_32_BRR_LOOP:

        address = MASK_OP_BRR_DISP15_SEXT(ctx->opcode);

        r2 = MASK_OP_BRR_S2(ctx->opcode);

        r1 = MASK_OP_BRR_S1(ctx->opcode);

        gen_compute_branch(ctx, op1, r1, r2, 0, address);

        break;

/* RC Format */

    case OPCM_32_RC_LOGICAL_SHIFT:

        decode_rc_logical_shift(env, ctx);

        break;

    case OPCM_32_RC_ACCUMULATOR:

        decode_rc_accumulator(env, ctx);

        break;

    case OPCM_32_RC_SERVICEROUTINE:

        decode_rc_serviceroutine(env, ctx);

        break;

    case OPCM_32_RC_MUL:

        decode_rc_mul(env, ctx);

        break;

/* RCPW Format */

    case OPCM_32_RCPW_MASK_INSERT:

        decode_rcpw_insert(env, ctx);

        break;

/* RCRR Format */

    case OPC1_32_RCRR_INSERT:

        r1 = MASK_OP_RCRR_S1(ctx->opcode);

        r2 = MASK_OP_RCRR_S3(ctx->opcode);

        r3 = MASK_OP_RCRR_D(ctx->opcode);

        const16 = MASK_OP_RCRR_CONST4(ctx->opcode);

        temp = tcg_const_i32(const16);

        temp2 = tcg_temp_new(); /* width*/

        temp3 = tcg_temp_new(); /* pos */

        tcg_gen_andi_tl(temp2, cpu_gpr_d[r3+1], 0x1f);

        tcg_gen_andi_tl(temp3, cpu_gpr_d[r3], 0x1f);

        gen_insert(cpu_gpr_d[r2], cpu_gpr_d[r1], temp, temp2, temp3);

        tcg_temp_free(temp);

        tcg_temp_free(temp2);

        tcg_temp_free(temp3);

        break;

/* RCRW Format */

    case OPCM_32_RCRW_MASK_INSERT:

        decode_rcrw_insert(env, ctx);

        break;

/* RCR Format */

    case OPCM_32_RCR_COND_SELECT:

        decode_rcr_cond_select(env, ctx);

        break;

    case OPCM_32_RCR_MADD:

        decode_rcr_madd(env, ctx);

        break;

    case OPCM_32_RCR_MSUB:

        decode_rcr_msub(env, ctx);

        break;

/* RLC Format */

    case OPC1_32_RLC_ADDI:

    case OPC1_32_RLC_ADDIH:

    case OPC1_32_RLC_ADDIH_A:

    case OPC1_32_RLC_MFCR:

    case OPC1_32_RLC_MOV:

    case OPC1_32_RLC_MOV_64:

    case OPC1_32_RLC_MOV_U:

    case OPC1_32_RLC_MOV_H:

    case OPC1_32_RLC_MOVH_A:

    case OPC1_32_RLC_MTCR:

        decode_rlc_opc(env, ctx, op1);

        break;

    }

}


static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,

                       intptr_t arg2)

{

    uint8_t *old_code_ptr = s->code_ptr;

    if (type == TCG_TYPE_I32) {

        tcg_out_op_t(s, INDEX_op_ld_i32);

        tcg_out_r(s, ret);

        tcg_out_r(s, arg1);

        tcg_out32(s, arg2);

    } else {

        assert(type == TCG_TYPE_I64);

#if TCG_TARGET_REG_BITS == 64

        tcg_out_op_t(s, INDEX_op_ld_i64);

        tcg_out_r(s, ret);

        tcg_out_r(s, arg1);

        assert(arg2 == (int32_t)arg2);

        tcg_out32(s, arg2);

#else

        TODO();

#endif

    }

    old_code_ptr[1] = s->code_ptr - old_code_ptr;

}


static bool s390_cpu_has_work(CPUState *cs)

{

    S390CPU *cpu = S390_CPU(cs);

    CPUS390XState *env = &cpu->env;

    return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&

           (env->psw.mask & PSW_MASK_EXT);

}


static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender,

                                       const struct iovec *iov, int iovcnt,

                                       NetPacketSent *sent_cb)

{

    VLANPacket *packet;

    size_t max_len = 0;

    int i;

    max_len = calc_iov_length(iov, iovcnt);

    packet = qemu_malloc(sizeof(VLANPacket) + max_len);

    packet->sender = sender;

    packet->sent_cb = sent_cb;

    packet->size = 0;

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

        size_t len = iov[i].iov_len;

        memcpy(packet->data + packet->size, iov[i].iov_base, len);

        packet->size += len;

    }

    TAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry);

    return packet->size;

}


static void sm501_palette_write(void *opaque,

				target_phys_addr_t addr, uint32_t value)

{

    SM501State * s = (SM501State *)opaque;

    SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",

		  (int)addr, value);

    /* TODO : consider BYTE/WORD access */

    /* TODO : consider endian */

    assert(0 <= addr && addr < 0x400 * 3);

    *(uint32_t*)&s->dc_palette[addr] = value;

}


static int qemu_gluster_open(BlockDriverState *bs,  QDict *options,

                             int bdrv_flags, Error **errp)

{

    BDRVGlusterState *s = bs->opaque;

    int open_flags = O_BINARY;

    int ret = 0;

    GlusterConf *gconf = g_malloc0(sizeof(GlusterConf));

    QemuOpts *opts;

    Error *local_err = NULL;

    const char *filename;

    opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);

    qemu_opts_absorb_qdict(opts, options, &local_err);

    if (local_err) {

        error_propagate(errp, local_err);

        ret = -EINVAL;

        goto out;

    }

    filename = qemu_opt_get(opts, "filename");

    s->glfs = qemu_gluster_init(gconf, filename, errp);

    if (!s->glfs) {

        ret = -errno;

        goto out;

    }

    if (bdrv_flags & BDRV_O_RDWR) {

        open_flags |= O_RDWR;

    } else {

        open_flags |= O_RDONLY;

    }

    if ((bdrv_flags & BDRV_O_NOCACHE)) {

        open_flags |= O_DIRECT;

    }

    s->fd = glfs_open(s->glfs, gconf->image, open_flags);

    if (!s->fd) {

        ret = -errno;

    }

out:

    qemu_opts_del(opts);

    qemu_gluster_gconf_free(gconf);

    if (!ret) {

        return ret;

    }

    if (s->fd) {

        glfs_close(s->fd);

    }

    if (s->glfs) {

        glfs_fini(s->glfs);

    }

    return ret;

}


static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)

{

    AVFilterContext *ctx  = inlink->dst;

    TileContext *tile    = ctx->priv;

    AVFilterLink *outlink = ctx->outputs[0];

    unsigned x0, y0;

    get_current_tile_pos(ctx, &x0, &y0);

    ff_copy_rectangle2(&tile->draw,

                       outlink->out_buf->data, outlink->out_buf->linesize,

                       inlink ->cur_buf->data, inlink ->cur_buf->linesize,

                       x0, y0 + y, 0, y, inlink->cur_buf->video->w, h);

    /* TODO if tile->w == 1 && slice_dir is always 1, we could draw_slice

     * immediately. */

    return 0;

}