static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)

{

    uint32_t insn, imm, shift, offset;

    uint32_t rd, rn, rm, rs;

    TCGv_i32 tmp;

    TCGv_i32 tmp2;

    TCGv_i32 tmp3;

    TCGv_i32 addr;

    TCGv_i64 tmp64;

    int op;

    int shiftop;

    int conds;

    int logic_cc;

    if (!(arm_feature(env, ARM_FEATURE_THUMB2)

          || arm_feature (env, ARM_FEATURE_M))) {

        /* Thumb-1 cores may need to treat bl and blx as a pair of

           16-bit instructions to get correct prefetch abort behavior.  */

        insn = insn_hw1;

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

            ARCH(5);

            /* Second half of blx.  */

            offset = ((insn & 0x7ff) << 1);

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

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

            /* Second half of bl.  */

            offset = ((insn & 0x7ff) << 1) | 1;

            tmp = load_reg(s, 14);

            tcg_gen_addi_i32(tmp, tmp, offset);

            tmp2 = tcg_temp_new_i32();

            tcg_gen_movi_i32(tmp2, s->pc | 1);

            store_reg(s, 14, tmp2);

            gen_bx(s, tmp);

            return 0;

        }

        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {

            /* Instruction spans a page boundary.  Implement it as two

               16-bit instructions in case the second half causes an

               prefetch abort.  */

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

            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);

            return 0;

        }

        /* Fall through to 32-bit decode.  */

    }

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

    s->pc += 2;

    insn |= (uint32_t)insn_hw1 << 16;

    if ((insn & 0xf800e800) != 0xf000e800) {

        ARCH(6T2);

    }

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

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

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

    rm = insn & 0xf;

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

    case 0: case 1: case 2: case 3:

        /* 16-bit instructions.  Should never happen.  */

        abort();

    case 4:

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

            /* Other load/store, table branch.  */

            if (insn & 0x01200000) {

                /* Load/store doubleword.  */

                if (rn == 15) {

                    addr = tcg_temp_new_i32();

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

                } else {

                    addr = load_reg(s, rn);

                }

                offset = (insn & 0xff) * 4;

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

                    offset = -offset;

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

                    tcg_gen_addi_i32(addr, addr, offset);

                    offset = 0;

                }

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

                    /* ldrd */

                    tmp = tcg_temp_new_i32();

                    tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));

                    store_reg(s, rs, tmp);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = tcg_temp_new_i32();

                    tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));

                    store_reg(s, rd, tmp);

                } else {

                    /* strd */

                    tmp = load_reg(s, rs);

                    tcg_gen_qemu_st32(tmp, addr, IS_USER(s));

                    tcg_temp_free_i32(tmp);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp = load_reg(s, rd);

                    tcg_gen_qemu_st32(tmp, addr, IS_USER(s));

                    tcg_temp_free_i32(tmp);

                }

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

                    /* Base writeback.  */

                    if (rn == 15)

                        goto illegal_op;

                    tcg_gen_addi_i32(addr, addr, offset - 4);

                    store_reg(s, rn, addr);

                } else {

                    tcg_temp_free_i32(addr);

                }

            } else if ((insn & (1 << 23)) == 0) {

                /* Load/store exclusive word.  */

                addr = tcg_temp_local_new_i32();

                load_reg_var(s, addr, rn);

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

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

                    gen_load_exclusive(s, rs, 15, addr, 2);

                } else {

                    gen_store_exclusive(s, rd, rs, 15, addr, 2);

                }

                tcg_temp_free_i32(addr);

            } else if ((insn & (7 << 5)) == 0) {

                /* Table Branch.  */

                if (rn == 15) {

                    addr = tcg_temp_new_i32();

                    tcg_gen_movi_i32(addr, s->pc);

                } else {

                    addr = load_reg(s, rn);

                }

                tmp = load_reg(s, rm);

                tcg_gen_add_i32(addr, addr, tmp);

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

                    /* tbh */

                    tcg_gen_add_i32(addr, addr, tmp);

                    tcg_temp_free_i32(tmp);

                    tmp = tcg_temp_new_i32();

                    tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s));

                } else { /* tbb */

                    tcg_temp_free_i32(tmp);

                    tmp = tcg_temp_new_i32();

                    tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s));

                }

                tcg_temp_free_i32(addr);

                tcg_gen_shli_i32(tmp, tmp, 1);

                tcg_gen_addi_i32(tmp, tmp, s->pc);

                store_reg(s, 15, tmp);

            } else {

                int op2 = (insn >> 6) & 0x3;

                op = (insn >> 4) & 0x3;

                switch (op2) {

                case 0:

                    goto illegal_op;

                case 1:

                    /* Load/store exclusive byte/halfword/doubleword */

                    if (op == 2) {

                        goto illegal_op;

                    }

                    ARCH(7);

                    break;

                case 2:

                    /* Load-acquire/store-release */

                    if (op == 3) {

                        goto illegal_op;

                    }

                    /* Fall through */

                case 3:

                    /* Load-acquire/store-release exclusive */

                    ARCH(8);

                    break;

                }

                addr = tcg_temp_local_new_i32();

                load_reg_var(s, addr, rn);

                if (!(op2 & 1)) {

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

                        tmp = tcg_temp_new_i32();

                        switch (op) {

                        case 0: /* ldab */

                            tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s));

                            break;

                        case 1: /* ldah */

                            tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s));

                            break;

                        case 2: /* lda */

                            tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));

                            break;

                        default:

                            abort();

                        }

                        store_reg(s, rs, tmp);

                    } else {

                        tmp = load_reg(s, rs);

                        switch (op) {

                        case 0: /* stlb */

                            tcg_gen_qemu_st8(tmp, addr, IS_USER(s));

                            break;

                        case 1: /* stlh */

                            tcg_gen_qemu_st16(tmp, addr, IS_USER(s));

                            break;

                        case 2: /* stl */

                            tcg_gen_qemu_st32(tmp, addr, IS_USER(s));

                            break;

                        default:

                            abort();

                        }

                        tcg_temp_free_i32(tmp);

                    }

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

                    gen_load_exclusive(s, rs, rd, addr, op);

                } else {

                    gen_store_exclusive(s, rm, rs, rd, addr, op);

                }

                tcg_temp_free_i32(addr);

            }

        } else {

            /* Load/store multiple, RFE, SRS.  */

            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {

                /* RFE, SRS: not available in user mode or on M profile */

                if (IS_USER(s) || IS_M(env)) {

                    goto illegal_op;

                }

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

                    /* rfe */

                    addr = load_reg(s, rn);

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

                        tcg_gen_addi_i32(addr, addr, -8);

                    /* Load PC into tmp and CPSR into tmp2.  */

                    tmp = tcg_temp_new_i32();

                    tcg_gen_qemu_ld32u(tmp, addr, 0);

                    tcg_gen_addi_i32(addr, addr, 4);

                    tmp2 = tcg_temp_new_i32();

                    tcg_gen_qemu_ld32u(tmp2, addr, 0);

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

                        /* Base writeback.  */

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

                            tcg_gen_addi_i32(addr, addr, 4);

                        } else {

                            tcg_gen_addi_i32(addr, addr, -4);

                        }

                        store_reg(s, rn, addr);

                    } else {

                        tcg_temp_free_i32(addr);

                    }

                    gen_rfe(s, tmp, tmp2);

                } else {

                    /* srs */

                    gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,

                            insn & (1 << 21));

                }

            } else {

                int i, loaded_base = 0;

                TCGv_i32 loaded_var;

                /* Load/store multiple.  */

                addr = load_reg(s, rn);

                offset = 0;

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

                    if (insn & (1 << i))

                        offset += 4;

                }

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

                    tcg_gen_addi_i32(addr, addr, -offset);

                }

                TCGV_UNUSED_I32(loaded_var);

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

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

                        continue;

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

                        /* Load.  */

                        tmp = tcg_temp_new_i32();

                        tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));

                        if (i == 15) {

                            gen_bx(s, tmp);

                        } else if (i == rn) {

                            loaded_var = tmp;

                            loaded_base = 1;

                        } else {

                            store_reg(s, i, tmp);

                        }

                    } else {

                        /* Store.  */

                        tmp = load_reg(s, i);

                        tcg_gen_qemu_st32(tmp, addr, IS_USER(s));

                        tcg_temp_free_i32(tmp);

                    }

                    tcg_gen_addi_i32(addr, addr, 4);

                }

                if (loaded_base) {

                    store_reg(s, rn, loaded_var);

                }

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

                    /* Base register writeback.  */

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

                        tcg_gen_addi_i32(addr, addr, -offset);

                    }

                    /* Fault if writeback register is in register list.  */

                    if (insn & (1 << rn))

                        goto illegal_op;

                    store_reg(s, rn, addr);

                } else {

                    tcg_temp_free_i32(addr);

                }

            }

        }

        break;

    case 5:

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

        if (op == 6) {

            /* Halfword pack.  */

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);

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

                /* pkhtb */

                if (shift == 0)

                    shift = 31;

                tcg_gen_sari_i32(tmp2, tmp2, shift);

                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);

                tcg_gen_ext16u_i32(tmp2, tmp2);

            } else {

                /* pkhbt */

                if (shift)

                    tcg_gen_shli_i32(tmp2, tmp2, shift);

                tcg_gen_ext16u_i32(tmp, tmp);

                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);

            }

            tcg_gen_or_i32(tmp, tmp, tmp2);

            tcg_temp_free_i32(tmp2);

            store_reg(s, rd, tmp);

        } else {

            /* Data processing register constant shift.  */

            if (rn == 15) {

                tmp = tcg_temp_new_i32();

                tcg_gen_movi_i32(tmp, 0);

            } else {

                tmp = load_reg(s, rn);

            }

            tmp2 = load_reg(s, rm);

            shiftop = (insn >> 4) & 3;

            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

            conds = (insn & (1 << 20)) != 0;

            logic_cc = (conds && thumb2_logic_op(op));

            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);

            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))

                goto illegal_op;

            tcg_temp_free_i32(tmp2);

            if (rd != 15) {

                store_reg(s, rd, tmp);

            } else {

                tcg_temp_free_i32(tmp);

            }

        }

        break;

    case 13: /* Misc data processing.  */

        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);

        if (op < 4 && (insn & 0xf000) != 0xf000)

            goto illegal_op;

        switch (op) {

        case 0: /* Register controlled shift.  */

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((insn & 0x70) != 0)

                goto illegal_op;

            op = (insn >> 21) & 3;

            logic_cc = (insn & (1 << 20)) != 0;

            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);

            if (logic_cc)

                gen_logic_CC(tmp);

            store_reg_bx(env, s, rd, tmp);

            break;

        case 1: /* Sign/zero extend.  */

            tmp = load_reg(s, rm);

            shift = (insn >> 4) & 3;

            /* ??? In many cases it's not necessary to do a

               rotate, a shift is sufficient.  */

            if (shift != 0)

                tcg_gen_rotri_i32(tmp, tmp, shift * 8);

            op = (insn >> 20) & 7;

            switch (op) {

            case 0: gen_sxth(tmp);   break;

            case 1: gen_uxth(tmp);   break;

            case 2: gen_sxtb16(tmp); break;

            case 3: gen_uxtb16(tmp); break;

            case 4: gen_sxtb(tmp);   break;

            case 5: gen_uxtb(tmp);   break;

            default: goto illegal_op;

            }

            if (rn != 15) {

                tmp2 = load_reg(s, rn);

                if ((op >> 1) == 1) {

                    gen_add16(tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 2: /* SIMD add/subtract.  */

            op = (insn >> 20) & 7;

            shift = (insn >> 4) & 7;

            if ((op & 3) == 3 || (shift & 3) == 3)

                goto illegal_op;

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);

            tcg_temp_free_i32(tmp2);

            store_reg(s, rd, tmp);

            break;

        case 3: /* Other data processing.  */

            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);

            if (op < 4) {

                /* Saturating add/subtract.  */

                tmp = load_reg(s, rn);

                tmp2 = load_reg(s, rm);

                if (op & 1)

                    gen_helper_double_saturate(tmp, cpu_env, tmp);

                if (op & 2)

                    gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);

                else

                    gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

            } else {

                tmp = load_reg(s, rn);

                switch (op) {

                case 0x0a: /* rbit */

                    gen_helper_rbit(tmp, tmp);

                    break;

                case 0x08: /* rev */

                    tcg_gen_bswap32_i32(tmp, tmp);

                    break;

                case 0x09: /* rev16 */

                    gen_rev16(tmp);

                    break;

                case 0x0b: /* revsh */

                    gen_revsh(tmp);

                    break;

                case 0x10: /* sel */

                    tmp2 = load_reg(s, rm);

                    tmp3 = tcg_temp_new_i32();

                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));

                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);

                    tcg_temp_free_i32(tmp3);

                    tcg_temp_free_i32(tmp2);

                    break;

                case 0x18: /* clz */

                    gen_helper_clz(tmp, tmp);

                    break;

                default:

                    goto illegal_op;

                }

            }

            store_reg(s, rd, tmp);

            break;

        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */

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

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

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

            case 0: /* 32 x 32 -> 32 */

                tcg_gen_mul_i32(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    if (op)

                        tcg_gen_sub_i32(tmp, tmp2, tmp);

                    else

                        tcg_gen_add_i32(tmp, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                }

                break;

            case 1: /* 16 x 16 -> 32 */

                gen_mulxy(tmp, tmp2, op & 2, op & 1);

                tcg_temp_free_i32(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                }

                break;

            case 2: /* Dual multiply add.  */

            case 4: /* Dual multiply subtract.  */

                if (op)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

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

                    /* This subtraction cannot overflow. */

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    /* This addition cannot overflow 32 bits;

                     * however it may overflow considered as a signed

                     * operation, in which case we must set the Q flag.

                     */

                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);

                }

                tcg_temp_free_i32(tmp2);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                  }

                break;

            case 3: /* 32 * 16 -> 32msb */

                if (op)

                    tcg_gen_sari_i32(tmp2, tmp2, 16);

                else

                    gen_sxth(tmp2);

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                tcg_gen_shri_i64(tmp64, tmp64, 16);

                tmp = tcg_temp_new_i32();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                if (rs != 15)

                  {

                    tmp2 = load_reg(s, rs);

                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                  }

                break;

            case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */

                tmp64 = gen_muls_i64_i32(tmp, tmp2);

                if (rs != 15) {

                    tmp = load_reg(s, rs);

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

                        tmp64 = gen_addq_msw(tmp64, tmp);

                    } else {

                        tmp64 = gen_subq_msw(tmp64, tmp);

                    }

                }

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

                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);

                }

                tcg_gen_shri_i64(tmp64, tmp64, 32);

                tmp = tcg_temp_new_i32();

                tcg_gen_trunc_i64_i32(tmp, tmp64);

                tcg_temp_free_i64(tmp64);

                break;

            case 7: /* Unsigned sum of absolute differences.  */

                gen_helper_usad8(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                if (rs != 15) {

                    tmp2 = load_reg(s, rs);

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                    tcg_temp_free_i32(tmp2);

                }

                break;

            }

            store_reg(s, rd, tmp);

            break;

        case 6: case 7: /* 64-bit multiply, Divide.  */

            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);

            tmp = load_reg(s, rn);

            tmp2 = load_reg(s, rm);

            if ((op & 0x50) == 0x10) {

                /* sdiv, udiv */

                if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {

                    goto illegal_op;

                }

                if (op & 0x20)

                    gen_helper_udiv(tmp, tmp, tmp2);

                else

                    gen_helper_sdiv(tmp, tmp, tmp2);

                tcg_temp_free_i32(tmp2);

                store_reg(s, rd, tmp);

            } else if ((op & 0xe) == 0xc) {

                /* Dual multiply accumulate long.  */

                if (op & 1)

                    gen_swap_half(tmp2);

                gen_smul_dual(tmp, tmp2);

                if (op & 0x10) {

                    tcg_gen_sub_i32(tmp, tmp, tmp2);

                } else {

                    tcg_gen_add_i32(tmp, tmp, tmp2);

                }

                tcg_temp_free_i32(tmp2);

                /* BUGFIX */

                tmp64 = tcg_temp_new_i64();

                tcg_gen_ext_i32_i64(tmp64, tmp);

                tcg_temp_free_i32(tmp);

                gen_addq(s, tmp64, rs, rd);

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            } else {

                if (op & 0x20) {

                    /* Unsigned 64-bit multiply  */

                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);

                } else {

                    if (op & 8) {

                        /* smlalxy */

                        gen_mulxy(tmp, tmp2, op & 2, op & 1);

                        tcg_temp_free_i32(tmp2);

                        tmp64 = tcg_temp_new_i64();

                        tcg_gen_ext_i32_i64(tmp64, tmp);

                        tcg_temp_free_i32(tmp);

                    } else {

                        /* Signed 64-bit multiply  */

                        tmp64 = gen_muls_i64_i32(tmp, tmp2);

                    }

                }

                if (op & 4) {

                    /* umaal */

                    gen_addq_lo(s, tmp64, rs);

                    gen_addq_lo(s, tmp64, rd);

                } else if (op & 0x40) {

                    /* 64-bit accumulate.  */

                    gen_addq(s, tmp64, rs, rd);

                }

                gen_storeq_reg(s, rs, rd, tmp64);

                tcg_temp_free_i64(tmp64);

            }

            break;

        }

        break;

    case 6: case 7: case 14: case 15:

        /* Coprocessor.  */

        if (((insn >> 24) & 3) == 3) {

            /* Translate into the equivalent ARM encoding.  */

            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);

            if (disas_neon_data_insn(env, s, insn))

                goto illegal_op;

        } else {

            if (insn & (1 << 28))

                goto illegal_op;

            if (disas_coproc_insn (env, s, insn))

                goto illegal_op;

        }

        break;

    case 8: case 9: case 10: case 11:

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

            /* Branches, misc control.  */

            if (insn & 0x5000) {

                /* Unconditional branch.  */

                /* signextend(hw1[10:0]) -> offset[:12].  */

                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;

                /* hw1[10:0] -> offset[11:1].  */

                offset |= (insn & 0x7ff) << 1;

                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]

                   offset[24:22] already have the same value because of the

                   sign extension above.  */

                offset ^= ((~insn) & (1 << 13)) << 10;

                offset ^= ((~insn) & (1 << 11)) << 11;

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

                    /* Branch and link.  */

                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);

                }

                offset += s->pc;

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

                    /* b/bl */

                    gen_jmp(s, offset);

                } else {

                    /* blx */

                    offset &= ~(uint32_t)2;

                    /* thumb2 bx, no need to check */

                    gen_bx_im(s, offset);

                }

            } else if (((insn >> 23) & 7) == 7) {

                /* Misc control */

                if (insn & (1 << 13))

                    goto illegal_op;

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

                    /* Secure monitor call (v6Z) */

                    goto illegal_op; /* not implemented.  */

                } else {

                    op = (insn >> 20) & 7;

                    switch (op) {

                    case 0: /* msr cpsr.  */

                        if (IS_M(env)) {

                            tmp = load_reg(s, rn);

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_msr(cpu_env, addr, tmp);

                            tcg_temp_free_i32(addr);

                            tcg_temp_free_i32(tmp);

                            gen_lookup_tb(s);

                            break;

                        }

                        /* fall through */

                    case 1: /* msr spsr.  */

                        if (IS_M(env))

                            goto illegal_op;

                        tmp = load_reg(s, rn);

                        if (gen_set_psr(s,

                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),

                              op == 1, tmp))

                            goto illegal_op;

                        break;

                    case 2: /* cps, nop-hint.  */

                        if (((insn >> 8) & 7) == 0) {

                            gen_nop_hint(s, insn & 0xff);

                        }

                        /* Implemented as NOP in user mode.  */

                        if (IS_USER(s))

                            break;

                        offset = 0;

                        imm = 0;

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

                            if (insn & (1 << 7))

                                offset |= CPSR_A;

                            if (insn & (1 << 6))

                                offset |= CPSR_I;

                            if (insn & (1 << 5))

                                offset |= CPSR_F;

                            if (insn & (1 << 9))

                                imm = CPSR_A | CPSR_I | CPSR_F;

                        }

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

                            offset |= 0x1f;

                            imm |= (insn & 0x1f);

                        }

                        if (offset) {

                            gen_set_psr_im(s, offset, 0, imm);

                        }

                        break;

                    case 3: /* Special control operations.  */

                        ARCH(7);

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

                        switch (op) {

                        case 2: /* clrex */

                            gen_clrex(s);

                            break;

                        case 4: /* dsb */

                        case 5: /* dmb */

                        case 6: /* isb */

                            /* These execute as NOPs.  */

                            break;

                        default:

                            goto illegal_op;

                        }

                        break;

                    case 4: /* bxj */

                        /* Trivial implementation equivalent to bx.  */

                        tmp = load_reg(s, rn);

                        gen_bx(s, tmp);

                        break;

                    case 5: /* Exception return.  */

                        if (IS_USER(s)) {

                            goto illegal_op;

                        }

                        if (rn != 14 || rd != 15) {

                            goto illegal_op;

                        }

                        tmp = load_reg(s, rn);

                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);

                        gen_exception_return(s, tmp);

                        break;

                    case 6: /* mrs cpsr.  */

                        tmp = tcg_temp_new_i32();

                        if (IS_M(env)) {

                            addr = tcg_const_i32(insn & 0xff);

                            gen_helper_v7m_mrs(tmp, cpu_env, addr);

                            tcg_temp_free_i32(addr);

                        } else {

                            gen_helper_cpsr_read(tmp, cpu_env);

                        }

                        store_reg(s, rd, tmp);

                        break;

                    case 7: /* mrs spsr.  */

                        /* Not accessible in user mode.  */

                        if (IS_USER(s) || IS_M(env))

                            goto illegal_op;

                        tmp = load_cpu_field(spsr);

                        store_reg(s, rd, tmp);

                        break;

                    }

                }

            } else {

                /* Conditional branch.  */

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

                /* Generate a conditional jump to next instruction.  */

                s->condlabel = gen_new_label();

                gen_test_cc(op ^ 1, s->condlabel);

                s->condjmp = 1;

                /* offset[11:1] = insn[10:0] */

                offset = (insn & 0x7ff) << 1;

                /* offset[17:12] = insn[21:16].  */

                offset |= (insn & 0x003f0000) >> 4;

                /* offset[31:20] = insn[26].  */

                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;

                /* offset[18] = insn[13].  */

                offset |= (insn & (1 << 13)) << 5;

                /* offset[19] = insn[11].  */

                offset |= (insn & (1 << 11)) << 8;

                /* jump to the offset */

                gen_jmp(s, s->pc + offset);

            }

        } else {

            /* Data processing immediate.  */

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

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

                    if (insn & (1 << 20))

                        goto illegal_op;

                    /* Bitfield/Saturate.  */

                    op = (insn >> 21) & 7;

                    imm = insn & 0x1f;

                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);

                    if (rn == 15) {

                        tmp = tcg_temp_new_i32();

                        tcg_gen_movi_i32(tmp, 0);

                    } else {

                        tmp = load_reg(s, rn);

                    }

                    switch (op) {

                    case 2: /* Signed bitfield extract.  */

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_sbfx(tmp, shift, imm);

                        break;

                    case 6: /* Unsigned bitfield extract.  */

                        imm++;

                        if (shift + imm > 32)

                            goto illegal_op;

                        if (imm < 32)

                            gen_ubfx(tmp, shift, (1u << imm) - 1);

                        break;

                    case 3: /* Bitfield insert/clear.  */

                        if (imm < shift)

                            goto illegal_op;

                        imm = imm + 1 - shift;

                        if (imm != 32) {

                            tmp2 = load_reg(s, rd);

                            tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);

                            tcg_temp_free_i32(tmp2);

                        }

                        break;

                    case 7:

                        goto illegal_op;

                    default: /* Saturate.  */

                        if (shift) {

                            if (op & 1)

                                tcg_gen_sari_i32(tmp, tmp, shift);

                            else

                                tcg_gen_shli_i32(tmp, tmp, shift);

                        }

                        tmp2 = tcg_const_i32(imm);

                        if (op & 4) {

                            /* Unsigned.  */

                            if ((op & 1) && shift == 0)

                                gen_helper_usat16(tmp, cpu_env, tmp, tmp2);

                            else

                                gen_helper_usat(tmp, cpu_env, tmp, tmp2);

                        } else {

                            /* Signed.  */

                            if ((op & 1) && shift == 0)

                                gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);

                            else

                                gen_helper_ssat(tmp, cpu_env, tmp, tmp2);

                        }

                        tcg_temp_free_i32(tmp2);

                        break;

                    }

                    store_reg(s, rd, tmp);

                } else {

                    imm = ((insn & 0x04000000) >> 15)

                          | ((insn & 0x7000) >> 4) | (insn & 0xff);

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

                        /* 16-bit immediate.  */

                        imm |= (insn >> 4) & 0xf000;

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

                            /* movt */

                            tmp = load_reg(s, rd);

                            tcg_gen_ext16u_i32(tmp, tmp);

                            tcg_gen_ori_i32(tmp, tmp, imm << 16);

                        } else {

                            /* movw */

                            tmp = tcg_temp_new_i32();

                            tcg_gen_movi_i32(tmp, imm);

                        }

                    } else {

                        /* Add/sub 12-bit immediate.  */

                        if (rn == 15) {

                            offset = s->pc & ~(uint32_t)3;

                            if (insn & (1 << 23))

                                offset -= imm;

                            else

                                offset += imm;

                            tmp = tcg_temp_new_i32();

                            tcg_gen_movi_i32(tmp, offset);

                        } else {

                            tmp = load_reg(s, rn);

                            if (insn & (1 << 23))

                                tcg_gen_subi_i32(tmp, tmp, imm);

                            else

                                tcg_gen_addi_i32(tmp, tmp, imm);

                        }

                    }

                    store_reg(s, rd, tmp);

                }

            } else {

                int shifter_out = 0;

                /* modified 12-bit immediate.  */

                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);

                imm = (insn & 0xff);

                switch (shift) {

                case 0: /* XY */

                    /* Nothing to do.  */

                    break;

                case 1: /* 00XY00XY */

                    imm |= imm << 16;

                    break;

                case 2: /* XY00XY00 */

                    imm |= imm << 16;

                    imm <<= 8;

                    break;

                case 3: /* XYXYXYXY */

                    imm |= imm << 16;

                    imm |= imm << 8;

                    break;

                default: /* Rotated constant.  */

                    shift = (shift << 1) | (imm >> 7);

                    imm |= 0x80;

                    imm = imm << (32 - shift);

                    shifter_out = 1;

                    break;

                }

                tmp2 = tcg_temp_new_i32();

                tcg_gen_movi_i32(tmp2, imm);

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

                if (rn == 15) {

                    tmp = tcg_temp_new_i32();

                    tcg_gen_movi_i32(tmp, 0);

                } else {

                    tmp = load_reg(s, rn);

                }

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

                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,

                                       shifter_out, tmp, tmp2))

                    goto illegal_op;

                tcg_temp_free_i32(tmp2);

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

                if (rd != 15) {

                    store_reg(s, rd, tmp);

                } else {

                    tcg_temp_free_i32(tmp);

                }

            }

        }

        break;

    case 12: /* Load/store single data item.  */

        {

        int postinc = 0;

        int writeback = 0;

        int user;

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

            if (disas_neon_ls_insn(env, s, insn))

                goto illegal_op;

            break;

        }

        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);

        if (rs == 15) {

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

                goto illegal_op;

            }

            if (op != 2) {

                /* Byte or halfword load space with dest == r15 : memory hints.

                 * Catch them early so we don't emit pointless addressing code.

                 * This space is a mix of:

                 *  PLD/PLDW/PLI,  which we implement as NOPs (note that unlike

                 *     the ARM encodings, PLDW space doesn't UNDEF for non-v7MP

                 *     cores)

                 *  unallocated hints, which must be treated as NOPs

                 *  UNPREDICTABLE space, which we NOP or UNDEF depending on

                 *     which is easiest for the decoding logic

                 *  Some space which must UNDEF

                 */

                int op1 = (insn >> 23) & 3;

                int op2 = (insn >> 6) & 0x3f;

                if (op & 2) {

                    goto illegal_op;

                }

                if (rn == 15) {

                    /* UNPREDICTABLE, unallocated hint or

                     * PLD/PLDW/PLI (literal)

                     */

                    return 0;

                }

                if (op1 & 1) {

                    return 0; /* PLD/PLDW/PLI or unallocated hint */

                }

                if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {

                    return 0; /* PLD/PLDW/PLI or unallocated hint */

                }

                /* UNDEF space, or an UNPREDICTABLE */

                return 1;

            }

        }

        user = IS_USER(s);

        if (rn == 15) {

            addr = tcg_temp_new_i32();

            /* PC relative.  */

            /* s->pc has already been incremented by 4.  */

            imm = s->pc & 0xfffffffc;

            if (insn & (1 << 23))

                imm += insn & 0xfff;

            else

                imm -= insn & 0xfff;

            tcg_gen_movi_i32(addr, imm);

        } else {

            addr = load_reg(s, rn);

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

                /* Positive offset.  */

                imm = insn & 0xfff;

                tcg_gen_addi_i32(addr, addr, imm);

            } else {

                imm = insn & 0xff;

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

                case 0x0: /* Shifted Register.  */

                    shift = (insn >> 4) & 0xf;

                    if (shift > 3) {

                        tcg_temp_free_i32(addr);

                        goto illegal_op;

                    }

                    tmp = load_reg(s, rm);

                    if (shift)

                        tcg_gen_shli_i32(tmp, tmp, shift);

                    tcg_gen_add_i32(addr, addr, tmp);

                    tcg_temp_free_i32(tmp);

                    break;

                case 0xc: /* Negative offset.  */

                    tcg_gen_addi_i32(addr, addr, -imm);

                    break;

                case 0xe: /* User privilege.  */

                    tcg_gen_addi_i32(addr, addr, imm);

                    user = 1;

                    break;

                case 0x9: /* Post-decrement.  */

                    imm = -imm;

                    /* Fall through.  */

                case 0xb: /* Post-increment.  */

                    postinc = 1;

                    writeback = 1;

                    break;

                case 0xd: /* Pre-decrement.  */

                    imm = -imm;

                    /* Fall through.  */

                case 0xf: /* Pre-increment.  */

                    tcg_gen_addi_i32(addr, addr, imm);

                    writeback = 1;

                    break;

                default:

                    tcg_temp_free_i32(addr);

                    goto illegal_op;

                }

            }

        }

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

            /* Load.  */

            tmp = tcg_temp_new_i32();

            switch (op) {

            case 0:

                tcg_gen_qemu_ld8u(tmp, addr, user);

                break;

            case 4:

                tcg_gen_qemu_ld8s(tmp, addr, user);

                break;

            case 1:

                tcg_gen_qemu_ld16u(tmp, addr, user);

                break;

            case 5:

                tcg_gen_qemu_ld16s(tmp, addr, user);

                break;

            case 2:

                tcg_gen_qemu_ld32u(tmp, addr, user);

                break;

            default:

                tcg_temp_free_i32(tmp);

                tcg_temp_free_i32(addr);

                goto illegal_op;

            }

            if (rs == 15) {

                gen_bx(s, tmp);

            } else {

                store_reg(s, rs, tmp);

            }

        } else {

            /* Store.  */

            tmp = load_reg(s, rs);

            switch (op) {

            case 0:

                tcg_gen_qemu_st8(tmp, addr, user);

                break;

            case 1:

                tcg_gen_qemu_st16(tmp, addr, user);

                break;

            case 2:

                tcg_gen_qemu_st32(tmp, addr, user);

                break;

            default:

                tcg_temp_free_i32(tmp);

                tcg_temp_free_i32(addr);

                goto illegal_op;

            }

            tcg_temp_free_i32(tmp);

        }

        if (postinc)

            tcg_gen_addi_i32(addr, addr, imm);

        if (writeback) {

            store_reg(s, rn, addr);

        } else {

            tcg_temp_free_i32(addr);

        }

        }

        break;

    default:

        goto illegal_op;

    }

    return 0;

illegal_op:

    return 1;

}


static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets *ps,

                                 int is_nalff, int nal_length_size, void *logctx)

{

    int i;

    int ret = 0;

    H2645Packet pkt = { 0 };

    ret = ff_h2645_packet_split(&pkt, buf, buf_size, logctx, is_nalff, nal_length_size, AV_CODEC_ID_HEVC, 1);

    if (ret < 0) {

        goto done;

    }

    for (i = 0; i < pkt.nb_nals; i++) {

        H2645NAL *nal = &pkt.nals[i];

        /* ignore everything except parameter sets and VCL NALUs */

        switch (nal->type) {

        case HEVC_NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, logctx, ps);    break;

        case HEVC_NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, logctx, ps, 1); break;

        case HEVC_NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, logctx, ps);    break;

        default:

            av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in extradata\n", nal->type);

            break;

        }

    }

done:

    ff_h2645_packet_uninit(&pkt);

    return ret;

}


static void test_qemu_strtoll_full_max(void)

{

    const char *str = g_strdup_printf("%lld", LLONG_MAX);

    int64_t res;

    int err;

    err = qemu_strtoll(str, NULL, 0, &res);

    g_assert_cmpint(err, ==, 0);

    g_assert_cmpint(res, ==, LLONG_MAX);

}


static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,

                     int64_t begin, int64_t length, Error **errp)

{

    CPUState *cpu;

    int nr_cpus;

    Error *err = NULL;

    int ret;

    if (runstate_is_running()) {

        vm_stop(RUN_STATE_SAVE_VM);

        s->resume = true;

    } else {

        s->resume = false;

    }

    /* If we use KVM, we should synchronize the registers before we get dump

     * info or physmap info.

     */

    cpu_synchronize_all_states();

    nr_cpus = 0;

    CPU_FOREACH(cpu) {

        nr_cpus++;

    }

    s->errp = errp;

    s->fd = fd;

    s->has_filter = has_filter;

    s->begin = begin;

    s->length = length;

    guest_phys_blocks_init(&s->guest_phys_blocks);

    guest_phys_blocks_append(&s->guest_phys_blocks);

    s->start = get_start_block(s);

    if (s->start == -1) {

        error_set(errp, QERR_INVALID_PARAMETER, "begin");

        goto cleanup;

    }

    /* get dump info: endian, class and architecture.

     * If the target architecture is not supported, cpu_get_dump_info() will

     * return -1.

     */

    ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks);

    if (ret < 0) {

        error_set(errp, QERR_UNSUPPORTED);

        goto cleanup;

    }

    s->note_size = cpu_get_note_size(s->dump_info.d_class,

                                     s->dump_info.d_machine, nr_cpus);

    if (s->note_size < 0) {

        error_set(errp, QERR_UNSUPPORTED);

        goto cleanup;

    }

    /* get memory mapping */

    memory_mapping_list_init(&s->list);

    if (paging) {

        qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);

        if (err != NULL) {

            error_propagate(errp, err);

            goto cleanup;

        }

    } else {

        qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks);

    }

    s->nr_cpus = nr_cpus;

    s->page_size = TARGET_PAGE_SIZE;

    s->page_shift = ffs(s->page_size) - 1;

    get_max_mapnr(s);

    uint64_t tmp;

    tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size);

    s->len_dump_bitmap = tmp * s->page_size;

    if (s->has_filter) {

        memory_mapping_filter(&s->list, s->begin, s->length);

    }

    /*

     * calculate phdr_num

     *

     * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow

     */

    s->phdr_num = 1; /* PT_NOTE */

    if (s->list.num < UINT16_MAX - 2) {

        s->phdr_num += s->list.num;

        s->have_section = false;

    } else {

        s->have_section = true;

        s->phdr_num = PN_XNUM;

        s->sh_info = 1; /* PT_NOTE */

        /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */

        if (s->list.num <= UINT32_MAX - 1) {

            s->sh_info += s->list.num;

        } else {

            s->sh_info = UINT32_MAX;

        }

    }

    if (s->dump_info.d_class == ELFCLASS64) {

        if (s->have_section) {

            s->memory_offset = sizeof(Elf64_Ehdr) +

                               sizeof(Elf64_Phdr) * s->sh_info +

                               sizeof(Elf64_Shdr) + s->note_size;

        } else {

            s->memory_offset = sizeof(Elf64_Ehdr) +

                               sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;

        }

    } else {

        if (s->have_section) {

            s->memory_offset = sizeof(Elf32_Ehdr) +

                               sizeof(Elf32_Phdr) * s->sh_info +

                               sizeof(Elf32_Shdr) + s->note_size;

        } else {

            s->memory_offset = sizeof(Elf32_Ehdr) +

                               sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;

        }

    }

    return 0;

cleanup:

    guest_phys_blocks_free(&s->guest_phys_blocks);

    if (s->resume) {

        vm_start();

    }

    return -1;

}


static void crs_replace_with_free_ranges(GPtrArray *ranges,

                                         uint64_t start, uint64_t end)

{

    GPtrArray *free_ranges = g_ptr_array_new_with_free_func(crs_range_free);

    uint64_t free_base = start;

    int i;

    g_ptr_array_sort(ranges, crs_range_compare);

    for (i = 0; i < ranges->len; i++) {

        CrsRangeEntry *used = g_ptr_array_index(ranges, i);

        if (free_base < used->base) {

            crs_range_insert(free_ranges, free_base, used->base - 1);

        }

        free_base = used->limit + 1;

    }

    if (free_base < end) {

        crs_range_insert(free_ranges, free_base, end);

    }

    g_ptr_array_set_size(ranges, 0);

    for (i = 0; i < free_ranges->len; i++) {

        g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));

    }

    g_ptr_array_free(free_ranges, false);

}


static ssize_t qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,

                                                  Error **errp)

{

    size_t i;

    size_t payload_len;

    uint32_t *payload32;

    if (!ioc->payload_remain) {

        error_setg(errp,

                   "Decoding payload but no bytes of payload remain");

        return -1;

    }

    /* If we aren't at the end of the payload, then drop

     * off the last bytes, so we're always multiple of 4

     * for purpose of unmasking, except at end of payload

     */

    if (ioc->encinput.offset < ioc->payload_remain) {

        payload_len = ioc->encinput.offset - (ioc->encinput.offset % 4);

    } else {

        payload_len = ioc->payload_remain;

    }

    if (payload_len == 0) {

        return QIO_CHANNEL_ERR_BLOCK;

    }

    ioc->payload_remain -= payload_len;

    /* unmask frame */

    /* process 1 frame (32 bit op) */

    payload32 = (uint32_t *)ioc->encinput.buffer;

    for (i = 0; i < payload_len / 4; i++) {

        payload32[i] ^= ioc->mask.u;

    }

    /* process the remaining bytes (if any) */

    for (i *= 4; i < payload_len; i++) {

        ioc->encinput.buffer[i] ^= ioc->mask.c[i % 4];

    }

    buffer_reserve(&ioc->rawinput, payload_len);

    buffer_append(&ioc->rawinput, ioc->encinput.buffer, payload_len);

    buffer_advance(&ioc->encinput, payload_len);

    return payload_len;

}


static int load_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)

{

    struct SOFAlizerContext *s = ctx->priv;

    /* variables associated with content of SOFA file: */

    int ncid, n_dims, n_vars, n_gatts, n_unlim_dim_id, status;

    char data_delay_dim_name[NC_MAX_NAME];

    float *sp_a, *sp_e, *sp_r, *data_ir;

    char *sofa_conventions;

    char dim_name[NC_MAX_NAME];   /* names of netCDF dimensions */

    size_t *dim_length;           /* lengths of netCDF dimensions */

    char *text;

    unsigned int sample_rate;

    int data_delay_dim_id[2];

    int samplingrate_id;

    int data_delay_id;

    int n_samples;

    int m_dim_id = -1;

    int n_dim_id = -1;

    int data_ir_id;

    size_t att_len;

    int m_dim;

    int *data_delay;

    int sp_id;

    int i, ret;

    s->sofa.ncid = 0;

    status = nc_open(filename, NC_NOWRITE, &ncid); /* open SOFA file read-only */

    if (status != NC_NOERR) {

        av_log(ctx, AV_LOG_ERROR, "Can't find SOFA-file '%s'\n", filename);

        return AVERROR(EINVAL);

    }

    /* get number of dimensions, vars, global attributes and Id of unlimited dimensions: */

    nc_inq(ncid, &n_dims, &n_vars, &n_gatts, &n_unlim_dim_id);

    /* -- get number of measurements ("M") and length of one IR ("N") -- */

    dim_length = av_malloc_array(n_dims, sizeof(*dim_length));

    if (!dim_length) {

        nc_close(ncid);

        return AVERROR(ENOMEM);

    }

    for (i = 0; i < n_dims; i++) { /* go through all dimensions of file */

        nc_inq_dim(ncid, i, (char *)&dim_name, &dim_length[i]); /* get dimensions */

        if (!strncmp("M", (const char *)&dim_name, 1)) /* get ID of dimension "M" */

            m_dim_id = i;

        if (!strncmp("N", (const char *)&dim_name, 1)) /* get ID of dimension "N" */

            n_dim_id = i;

    }

    if ((m_dim_id == -1) || (n_dim_id == -1)) { /* dimension "M" or "N" couldn't be found */

        av_log(ctx, AV_LOG_ERROR, "Can't find required dimensions in SOFA file.\n");

        av_freep(&dim_length);

        nc_close(ncid);

        return AVERROR(EINVAL);

    }

    n_samples = dim_length[n_dim_id]; /* get length of one IR */

    m_dim     = dim_length[m_dim_id]; /* get number of measurements */

    av_freep(&dim_length);

    /* -- check file type -- */

    /* get length of attritube "Conventions" */

    status = nc_inq_attlen(ncid, NC_GLOBAL, "Conventions", &att_len);

    if (status != NC_NOERR) {

        av_log(ctx, AV_LOG_ERROR, "Can't get length of attribute \"Conventions\".\n");

        nc_close(ncid);

        return AVERROR_INVALIDDATA;

    }

    /* check whether file is SOFA file */

    text = av_malloc(att_len + 1);

    if (!text) {

        nc_close(ncid);

        return AVERROR(ENOMEM);

    }

    nc_get_att_text(ncid, NC_GLOBAL, "Conventions", text);

    *(text + att_len) = 0;

    if (strncmp("SOFA", text, 4)) {

        av_log(ctx, AV_LOG_ERROR, "Not a SOFA file!\n");

        av_freep(&text);

        nc_close(ncid);

        return AVERROR(EINVAL);

    }

    av_freep(&text);

    status = nc_inq_attlen(ncid, NC_GLOBAL, "License", &att_len);

    if (status == NC_NOERR) {

        text = av_malloc(att_len + 1);

        if (text) {

            nc_get_att_text(ncid, NC_GLOBAL, "License", text);

            *(text + att_len) = 0;

            av_log(ctx, AV_LOG_INFO, "SOFA file License: %s\n", text);

            av_freep(&text);

        }

    }

    status = nc_inq_attlen(ncid, NC_GLOBAL, "SourceDescription", &att_len);

    if (status == NC_NOERR) {

        text = av_malloc(att_len + 1);

        if (text) {

            nc_get_att_text(ncid, NC_GLOBAL, "SourceDescription", text);

            *(text + att_len) = 0;

            av_log(ctx, AV_LOG_INFO, "SOFA file SourceDescription: %s\n", text);

            av_freep(&text);

        }

    }

    status = nc_inq_attlen(ncid, NC_GLOBAL, "Comment", &att_len);

    if (status == NC_NOERR) {

        text = av_malloc(att_len + 1);

        if (text) {

            nc_get_att_text(ncid, NC_GLOBAL, "Comment", text);

            *(text + att_len) = 0;

            av_log(ctx, AV_LOG_INFO, "SOFA file Comment: %s\n", text);

            av_freep(&text);

        }

    }

    status = nc_inq_attlen(ncid, NC_GLOBAL, "SOFAConventions", &att_len);

    if (status != NC_NOERR) {

        av_log(ctx, AV_LOG_ERROR, "Can't get length of attribute \"SOFAConventions\".\n");

        nc_close(ncid);

        return AVERROR_INVALIDDATA;

    }

    sofa_conventions = av_malloc(att_len + 1);

    if (!sofa_conventions) {

        nc_close(ncid);

        return AVERROR(ENOMEM);

    }

    nc_get_att_text(ncid, NC_GLOBAL, "SOFAConventions", sofa_conventions);

    *(sofa_conventions + att_len) = 0;

    if (strncmp("SimpleFreeFieldHRIR", sofa_conventions, att_len)) {

        av_log(ctx, AV_LOG_ERROR, "Not a SimpleFreeFieldHRIR file!\n");

        av_freep(&sofa_conventions);

        nc_close(ncid);

        return AVERROR(EINVAL);

    }

    av_freep(&sofa_conventions);

    /* -- get sampling rate of HRTFs -- */

    /* read ID, then value */

    status  = nc_inq_varid(ncid, "Data.SamplingRate", &samplingrate_id);

    status += nc_get_var_uint(ncid, samplingrate_id, &sample_rate);

    if (status != NC_NOERR) {

        av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.SamplingRate.\n");

        nc_close(ncid);

        return AVERROR(EINVAL);

    }

    *samplingrate = sample_rate; /* remember sampling rate */

    /* -- allocate memory for one value for each measurement position: -- */

    sp_a = s->sofa.sp_a = av_malloc_array(m_dim, sizeof(float));

    sp_e = s->sofa.sp_e = av_malloc_array(m_dim, sizeof(float));

    sp_r = s->sofa.sp_r = av_malloc_array(m_dim, sizeof(float));

    /* delay and IR values required for each ear and measurement position: */

    data_delay = s->sofa.data_delay = av_calloc(m_dim, 2 * sizeof(int));

    data_ir = s->sofa.data_ir = av_malloc_array(m_dim * n_samples, sizeof(float) * 2);

    if (!data_delay || !sp_a || !sp_e || !sp_r || !data_ir) {

        /* if memory could not be allocated */

        close_sofa(&s->sofa);

        return AVERROR(ENOMEM);

    }

    /* get impulse responses (HRTFs): */

    /* get corresponding ID */

    status = nc_inq_varid(ncid, "Data.IR", &data_ir_id);

    status += nc_get_var_float(ncid, data_ir_id, data_ir); /* read and store IRs */

    if (status != NC_NOERR) {

        av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.IR!\n");

        ret = AVERROR(EINVAL);

        goto error;

    }

    /* get source positions of the HRTFs in the SOFA file: */

    status  = nc_inq_varid(ncid, "SourcePosition", &sp_id); /* get corresponding ID */

    status += nc_get_vara_float(ncid, sp_id, (size_t[2]){ 0, 0 } ,

                (size_t[2]){ m_dim, 1}, sp_a); /* read & store azimuth angles */

    status += nc_get_vara_float(ncid, sp_id, (size_t[2]){ 0, 1 } ,

                (size_t[2]){ m_dim, 1}, sp_e); /* read & store elevation angles */

    status += nc_get_vara_float(ncid, sp_id, (size_t[2]){ 0, 2 } ,

                (size_t[2]){ m_dim, 1}, sp_r); /* read & store radii */

    if (status != NC_NOERR) { /* if any source position variable coudn't be read */

        av_log(ctx, AV_LOG_ERROR, "Couldn't read SourcePosition.\n");

        ret = AVERROR(EINVAL);

        goto error;

    }

    /* read Data.Delay, check for errors and fit it to data_delay */

    status  = nc_inq_varid(ncid, "Data.Delay", &data_delay_id);

    status += nc_inq_vardimid(ncid, data_delay_id, &data_delay_dim_id[0]);

    status += nc_inq_dimname(ncid, data_delay_dim_id[0], data_delay_dim_name);

    if (status != NC_NOERR) {

        av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.Delay.\n");

        ret = AVERROR(EINVAL);

        goto error;

    }

    /* Data.Delay dimension check */

    /* dimension of Data.Delay is [I R]: */

    if (!strncmp(data_delay_dim_name, "I", 2)) {

        /* check 2 characters to assure string is 0-terminated after "I" */

        int delay[2]; /* delays get from SOFA file: */

        av_log(ctx, AV_LOG_DEBUG, "Data.Delay has dimension [I R]\n");

        status = nc_get_var_int(ncid, data_delay_id, &delay[0]);

        if (status != NC_NOERR) {

            av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.Delay\n");

            ret = AVERROR(EINVAL);

            goto error;

        }

        int *data_delay_r = data_delay + m_dim;

        for (i = 0; i < m_dim; i++) { /* extend given dimension [I R] to [M R] */

            /* assign constant delay value for all measurements to data_delay fields */

            data_delay[i]   = delay[0];

            data_delay_r[i] = delay[1];

        }

        /* dimension of Data.Delay is [M R] */

    } else if (!strncmp(data_delay_dim_name, "M", 2)) {

        av_log(ctx, AV_LOG_ERROR, "Data.Delay in dimension [M R]\n");

        /* get delays from SOFA file: */

        status = nc_get_var_int(ncid, data_delay_id, data_delay);

        if (status != NC_NOERR) {

            av_log(ctx, AV_LOG_ERROR, "Couldn't read Data.Delay\n");

            ret = AVERROR(EINVAL);

            goto error;

        }

    } else { /* dimension of Data.Delay is neither [I R] nor [M R] */

        av_log(ctx, AV_LOG_ERROR, "Data.Delay does not have the required dimensions [I R] or [M R].\n");

        ret = AVERROR(EINVAL);

        goto error;

    }

    /* save information in SOFA struct: */

    s->sofa.m_dim = m_dim; /* no. measurement positions */

    s->sofa.n_samples = n_samples; /* length on one IR */

    s->sofa.ncid = ncid; /* netCDF ID of SOFA file */

    nc_close(ncid); /* close SOFA file */

    return 0;

error:

    close_sofa(&s->sofa);

    return ret;

}


static void create_flash(const VirtBoardInfo *vbi)

{

    /* Create two flash devices to fill the VIRT_FLASH space in the memmap.

     * Any file passed via -bios goes in the first of these.

     */

    hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2;

    hwaddr flashbase = vbi->memmap[VIRT_FLASH].base;

    char *nodename;

    if (bios_name) {

        char *fn;

        int image_size;

        if (drive_get(IF_PFLASH, 0, 0)) {

            error_report("The contents of the first flash device may be "

                         "specified with -bios or with -drive if=pflash... "

                         "but you cannot use both options at once");

            exit(1);

        }

        fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);

        if (!fn) {

            error_report("Could not find ROM image '%s'", bios_name);

            exit(1);

        }

        image_size = load_image_targphys(fn, flashbase, flashsize);

        g_free(fn);

        if (image_size < 0) {

            error_report("Could not load ROM image '%s'", bios_name);

            exit(1);

        }

        g_free(fn);

    }

    create_one_flash("virt.flash0", flashbase, flashsize);

    create_one_flash("virt.flash1", flashbase + flashsize, flashsize);

    nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);

    qemu_fdt_add_subnode(vbi->fdt, nodename);

    qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash");

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

                                 2, flashbase, 2, flashsize,

                                 2, flashbase + flashsize, 2, flashsize);

    qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4);

    g_free(nodename);

}


void mips_malta_init(QEMUMachineInitArgs *args)
{
    ram_addr_t ram_size = args->ram_size;
    const char *cpu_model = args->cpu_model;
    const char *kernel_filename = args->kernel_filename;
    const char *kernel_cmdline = args->kernel_cmdline;
    const char *initrd_filename = args->initrd_filename;
    char *filename;
    pflash_t *fl;
    MemoryRegion *system_memory = get_system_memory();
    MemoryRegion *ram = g_new(MemoryRegion, 1);
    MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1);
    target_long bios_size = FLASH_SIZE;
    const size_t smbus_eeprom_size = 8 * 256;
    uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
    int64_t kernel_entry;
    PCIBus *pci_bus;
    ISABus *isa_bus;
    MIPSCPU *cpu;
    CPUMIPSState *env;
    qemu_irq *isa_irq;
    qemu_irq *cpu_exit_irq;
    int piix4_devfn;
    i2c_bus *smbus;
    int i;
    DriveInfo *dinfo;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    DriveInfo *fd[MAX_FD];
    int fl_idx = 0;
    int fl_sectors = bios_size >> 16;
    int be;
    DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA);
    MaltaState *s = MIPS_MALTA(dev);
    qdev_init_nofail(dev);
    /* Make sure the first 3 serial ports are associated with a device. */
    for(i = 0; i < 3; i++) {
        if (!serial_hds[i]) {
            char label[32];
            snprintf(label, sizeof(label), "serial%d", i);
            serial_hds[i] = qemu_chr_new(label, "null", NULL);
        }
    }
    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "20Kc";
#else
        cpu_model = "24Kf";
#endif
    }
    for (i = 0; i < smp_cpus; i++) {
        cpu = cpu_mips_init(cpu_model);
        if (cpu == NULL) {
            fprintf(stderr, "Unable to find CPU definition\n");
            exit(1);
        }
        env = &cpu->env;
        /* Init internal devices */
        cpu_mips_irq_init_cpu(env);
        cpu_mips_clock_init(env);
        qemu_register_reset(main_cpu_reset, cpu);
    }
    cpu = MIPS_CPU(first_cpu);
    env = &cpu->env;
    /* allocate RAM */
    if (ram_size > (256 << 20)) {
        fprintf(stderr,
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
                ((unsigned int)ram_size / (1 << 20)));
        exit(1);
    }
    memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size);
    vmstate_register_ram_global(ram);
    memory_region_add_subregion(system_memory, 0, ram);
    /* generate SPD EEPROM data */
    generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
    generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
#ifdef TARGET_WORDS_BIGENDIAN
    be = 1;
#else
    be = 0;
#endif
    /* FPGA */
    /* The CBUS UART is attached to the MIPS CPU INT2 pin, ie interrupt 4 */
    malta_fpga_init(system_memory, FPGA_ADDRESS, env->irq[4], serial_hds[2]);
    /* Load firmware in flash / BIOS. */
    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
#ifdef DEBUG_BOARD_INIT
    if (dinfo) {
        printf("Register parallel flash %d size " TARGET_FMT_lx " at "
               "addr %08llx '%s' %x\n",
               fl_idx, bios_size, FLASH_ADDRESS,
               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
    }
#endif
    fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
                               65536, fl_sectors,
                               4, 0x0000, 0x0000, 0x0000, 0x0000, be);
    bios = pflash_cfi01_get_memory(fl);
    fl_idx++;
    if (kernel_filename) {
        /* Write a small bootloader to the flash location. */
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        kernel_entry = load_kernel();
        write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
    } else {
        /* Load firmware from flash. */
        if (!dinfo) {
            /* Load a BIOS image. */
            if (bios_name == NULL) {
                bios_name = BIOS_FILENAME;
            }
            filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
            if (filename) {
                bios_size = load_image_targphys(filename, FLASH_ADDRESS,
                                                BIOS_SIZE);
                g_free(filename);
            } else {
                bios_size = -1;
            }
            if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
                !kernel_filename && !qtest_enabled()) {
                error_report("Could not load MIPS bios '%s', and no "
                             "-kernel argument was specified", bios_name);
                exit(1);
            }
        }
        /* In little endian mode the 32bit words in the bios are swapped,
           a neat trick which allows bi-endian firmware. */
#ifndef TARGET_WORDS_BIGENDIAN
        {
            uint32_t *end, *addr = rom_ptr(FLASH_ADDRESS);
            if (!addr) {
                addr = memory_region_get_ram_ptr(bios);
            }
            end = (void *)addr + MIN(bios_size, 0x3e0000);
            while (addr < end) {
                bswap32s(addr);
                addr++;
            }
        }
#endif
    }
    /*
     * Map the BIOS at a 2nd physical location, as on the real board.
     * Copy it so that we can patch in the MIPS revision, which cannot be
     * handled by an overlapping region as the resulting ROM code subpage
     * regions are not executable.
     */
    memory_region_init_ram(bios_copy, NULL, "bios.1fc", BIOS_SIZE);
    if (!rom_copy(memory_region_get_ram_ptr(bios_copy),
                  FLASH_ADDRESS, BIOS_SIZE)) {
        memcpy(memory_region_get_ram_ptr(bios_copy),
               memory_region_get_ram_ptr(bios), BIOS_SIZE);
    }
    memory_region_set_readonly(bios_copy, true);
    memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_copy);
    /* Board ID = 0x420 (Malta Board with CoreLV) */
    stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
    /* Init internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);
    /*
     * We have a circular dependency problem: pci_bus depends on isa_irq,
     * isa_irq is provided by i8259, i8259 depends on ISA, ISA depends
     * on piix4, and piix4 depends on pci_bus.  To stop the cycle we have
     * qemu_irq_proxy() adds an extra bit of indirection, allowing us
     * to resolve the isa_irq -> i8259 dependency after i8259 is initialized.
     */
    isa_irq = qemu_irq_proxy(&s->i8259, 16);
    /* Northbridge */
    pci_bus = gt64120_register(isa_irq);
    /* Southbridge */
    ide_drive_get(hd, MAX_IDE_BUS);
    piix4_devfn = piix4_init(pci_bus, &isa_bus, 80);
    /* Interrupt controller */
    /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
    s->i8259 = i8259_init(isa_bus, env->irq[2]);
    isa_bus_irqs(isa_bus, s->i8259);
    pci_piix4_ide_init(pci_bus, hd, piix4_devfn + 1);
    pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
    smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
                          isa_get_irq(NULL, 9), NULL, 0, NULL);
    smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size);
    g_free(smbus_eeprom_buf);
    pit = pit_init(isa_bus, 0x40, 0, NULL);
    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
    DMA_init(0, cpu_exit_irq);
    /* Super I/O */
    isa_create_simple(isa_bus, "i8042");
    rtc_init(isa_bus, 2000, NULL);
    serial_isa_init(isa_bus, 0, serial_hds[0]);
    serial_isa_init(isa_bus, 1, serial_hds[1]);
    if (parallel_hds[0])
        parallel_init(isa_bus, 0, parallel_hds[0]);
    for(i = 0; i < MAX_FD; i++) {
        fd[i] = drive_get(IF_FLOPPY, 0, i);
    }
    fdctrl_init_isa(isa_bus, fd);
    /* Network card */
    network_init(pci_bus);
    /* Optional PCI video card */
    pci_vga_init(pci_bus);
}


static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr,

                                   qemu_irq **irqs)

{

    QemuOptsList *list;

    qemu_irq *mpic;

    DeviceState *dev = NULL;

    SysBusDevice *s;

    int i;

    mpic = g_new(qemu_irq, 256);

    if (kvm_enabled()) {

        bool irqchip_allowed = true, irqchip_required = false;

        list = qemu_find_opts("machine");

        if (!QTAILQ_EMPTY(&list->head)) {

            irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),

                                                "kernel_irqchip", true);

            irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head),

                                                 "kernel_irqchip", false);

        }

        if (irqchip_allowed) {

            dev = ppce500_init_mpic_kvm(params, irqs);

        }

        if (irqchip_required && !dev) {

            fprintf(stderr, "%s: irqchip requested but unavailable\n",

                    __func__);

            abort();

        }

    }

    if (!dev) {

        dev = ppce500_init_mpic_qemu(params, irqs);

    }

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

        mpic[i] = qdev_get_gpio_in(dev, i);

    }

    s = SYS_BUS_DEVICE(dev);

    memory_region_add_subregion(ccsr, MPC8544_MPIC_REGS_OFFSET,

                                s->mmio[0].memory);

    return mpic;

}


static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,

                                   DeviceState *dev)

{

#define CAST(type, obj, name) \

    ((type *)object_dynamic_cast(OBJECT(obj), (name)))

    SCSIDevice *d = CAST(SCSIDevice,  dev, TYPE_SCSI_DEVICE);

    sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);

    VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON);

    if (d) {

        void *spapr = CAST(void, bus->parent, "spapr-vscsi");

        VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI);

        USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE);

        if (spapr) {

            /*

             * Replace "channel@0/disk@0,0" with "disk@8000000000000000":

             * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun

             * in the top 16 bits of the 64-bit LUN

             */

            unsigned id = 0x8000 | (d->id << 8) | d->lun;

            return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),

                                   (uint64_t)id << 48);

        } else if (virtio) {

            /*

             * We use SRP luns of the form 01000000 | (target << 8) | lun

             * in the top 32 bits of the 64-bit LUN

             * Note: the quote above is from SLOF and it is wrong,

             * the actual binding is:

             * swap 0100 or 10 << or 20 << ( target lun-id -- srplun )

             */

            unsigned id = 0x1000000 | (d->id << 16) | d->lun;

            return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),

                                   (uint64_t)id << 32);

        } else if (usb) {

            /*

             * We use SRP luns of the form 01000000 | (usb-port << 16) | lun

             * in the top 32 bits of the 64-bit LUN

             */

            unsigned usb_port = atoi(usb->port->path);

            unsigned id = 0x1000000 | (usb_port << 16) | d->lun;

            return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),

                                   (uint64_t)id << 32);

    /*

     * SLOF probes the USB devices, and if it recognizes that the device is a

     * storage device, it changes its name to "storage" instead of "usb-host",

     * and additionally adds a child node for the SCSI LUN, so the correct

     * boot path in SLOF is something like .../storage@1/disk@xxx" instead.

     */

    if (strcmp("usb-host", qdev_fw_name(dev)) == 0) {

        USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE);

        if (usb_host_dev_is_scsi_storage(usbdev)) {

            return g_strdup_printf("storage@%s/disk", usbdev->port->path);

    if (phb) {

        /* Replace "pci" with "pci@800000020000000" */

        return g_strdup_printf("pci@%"PRIX64, phb->buid);

    if (vsc) {

        /* Same logic as virtio above */

        unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun;

        return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32);

    if (g_str_equal("pci-bridge", qdev_fw_name(dev))) {

        /* SLOF uses "pci" instead of "pci-bridge" for PCI bridges */

        PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE);

        return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn));

    return NULL;


static int qemu_rdma_alloc_qp(RDMAContext *rdma)

{

    struct ibv_qp_init_attr attr = { 0 };

    int ret;

    attr.cap.max_send_wr = RDMA_SIGNALED_SEND_MAX;

    attr.cap.max_recv_wr = 3;

    attr.cap.max_send_sge = 1;

    attr.cap.max_recv_sge = 1;

    attr.send_cq = rdma->cq;

    attr.recv_cq = rdma->cq;

    attr.qp_type = IBV_QPT_RC;

    ret = rdma_create_qp(rdma->cm_id, rdma->pd, &attr);

    if (ret) {

        return -1;

    }

    rdma->qp = rdma->cm_id->qp;

    return 0;

}


static void qio_channel_websock_handshake_process(QIOChannelWebsock *ioc,

                                                  char *buffer,

                                                  Error **errp)

{

    QIOChannelWebsockHTTPHeader hdrs[32];

    size_t nhdrs = G_N_ELEMENTS(hdrs);

    const char *protocols = NULL, *version = NULL, *key = NULL,

        *host = NULL, *connection = NULL, *upgrade = NULL;

    nhdrs = qio_channel_websock_extract_headers(ioc, buffer, hdrs, nhdrs, errp);

    if (!nhdrs) {

        return;

    }

    protocols = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL);

    if (!protocols) {

        error_setg(errp, "Missing websocket protocol header data");

        goto bad_request;

    }

    version = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_VERSION);

    if (!version) {

        error_setg(errp, "Missing websocket version header data");

        goto bad_request;

    }

    key = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_KEY);

    if (!key) {

        error_setg(errp, "Missing websocket key header data");

        goto bad_request;

    }

    host = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_HOST);

    if (!host) {

        error_setg(errp, "Missing websocket host header data");

        goto bad_request;

    }

    connection = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION);

    if (!connection) {

        error_setg(errp, "Missing websocket connection header data");

        goto bad_request;

    }

    upgrade = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE);

    if (!upgrade) {

        error_setg(errp, "Missing websocket upgrade header data");

        goto bad_request;

    }

    if (!g_strrstr(protocols, QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY)) {

        error_setg(errp, "No '%s' protocol is supported by client '%s'",

                   QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY, protocols);

        goto bad_request;

    }

    if (!g_str_equal(version, QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION)) {

        error_setg(errp, "Version '%s' is not supported by client '%s'",

                   QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION, version);

        goto bad_request;

    }

    if (strlen(key) != QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN) {

        error_setg(errp, "Key length '%zu' was not as expected '%d'",

                   strlen(key), QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN);

        goto bad_request;

    }

    if (strcasecmp(connection, QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE) != 0) {

        error_setg(errp, "No connection upgrade requested '%s'", connection);

        goto bad_request;

    }

    if (strcasecmp(upgrade, QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET) != 0) {

        error_setg(errp, "Incorrect upgrade method '%s'", upgrade);

        goto bad_request;

    }

    qio_channel_websock_handshake_send_res_ok(ioc, key, errp);

    return;

 bad_request:

    qio_channel_websock_handshake_send_res_err(

        ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST);

}


static int rv40_h_loop_filter_strength(uint8_t *src, int stride,

                                       int beta, int beta2, int edge,

                                       int *p1, int *q1)

{

    return rv40_loop_filter_strength(src, stride, 1, beta, beta2, edge, p1, q1);

}


static int decode_pic(AVSContext *h) {

    MpegEncContext *s = &h->s;

    int skip_count;

    enum cavs_mb mb_type;

    if (!s->context_initialized) {

        s->avctx->idct_algo = FF_IDCT_CAVS;

        if (MPV_common_init(s) < 0)

            return -1;

        ff_init_scantable(s->dsp.idct_permutation,&h->scantable,ff_zigzag_direct);

    }

    skip_bits(&s->gb,16);//bbv_dwlay

    if(h->stc == PIC_PB_START_CODE) {

        h->pic_type = get_bits(&s->gb,2) + FF_I_TYPE;

        if(h->pic_type > FF_B_TYPE) {

            av_log(s->avctx, AV_LOG_ERROR, "illegal picture type\n");

            return -1;

        }

        /* make sure we have the reference frames we need */

        if(!h->DPB[0].data[0] ||

          (!h->DPB[1].data[0] && h->pic_type == FF_B_TYPE))

            return -1;

    } else {

        h->pic_type = FF_I_TYPE;

        if(get_bits1(&s->gb))

            skip_bits(&s->gb,24);//time_code

    }

    /* release last B frame */

    if(h->picture.data[0])

        s->avctx->release_buffer(s->avctx, (AVFrame *)&h->picture);

    s->avctx->get_buffer(s->avctx, (AVFrame *)&h->picture);

    ff_cavs_init_pic(h);

    h->picture.poc = get_bits(&s->gb,8)*2;

    /* get temporal distances and MV scaling factors */

    if(h->pic_type != FF_B_TYPE) {

        h->dist[0] = (h->picture.poc - h->DPB[0].poc  + 512) % 512;

    } else {

        h->dist[0] = (h->DPB[0].poc  - h->picture.poc + 512) % 512;

    }

    h->dist[1] = (h->picture.poc - h->DPB[1].poc  + 512) % 512;

    h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0;

    h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0;

    if(h->pic_type == FF_B_TYPE) {

        h->sym_factor = h->dist[0]*h->scale_den[1];

    } else {

        h->direct_den[0] = h->dist[0] ? 16384/h->dist[0] : 0;

        h->direct_den[1] = h->dist[1] ? 16384/h->dist[1] : 0;

    }

    if(s->low_delay)

        get_ue_golomb(&s->gb); //bbv_check_times

    h->progressive             = get_bits1(&s->gb);

    h->pic_structure = 1;

    if(!h->progressive)

        h->pic_structure = get_bits1(&s->gb);

    if(!h->pic_structure && h->stc == PIC_PB_START_CODE)

        skip_bits1(&s->gb);     //advanced_pred_mode_disable

    skip_bits1(&s->gb);        //top_field_first

    skip_bits1(&s->gb);        //repeat_first_field

    h->qp_fixed                = get_bits1(&s->gb);

    h->qp                      = get_bits(&s->gb,6);

    if(h->pic_type == FF_I_TYPE) {

        if(!h->progressive && !h->pic_structure)

            skip_bits1(&s->gb);//what is this?

        skip_bits(&s->gb,4);   //reserved bits

    } else {

        if(!(h->pic_type == FF_B_TYPE && h->pic_structure == 1))

            h->ref_flag        = get_bits1(&s->gb);

        skip_bits(&s->gb,4);   //reserved bits

        h->skip_mode_flag      = get_bits1(&s->gb);

    }

    h->loop_filter_disable     = get_bits1(&s->gb);

    if(!h->loop_filter_disable && get_bits1(&s->gb)) {

        h->alpha_offset        = get_se_golomb(&s->gb);

        h->beta_offset         = get_se_golomb(&s->gb);

    } else {

        h->alpha_offset = h->beta_offset  = 0;

    }

    if(h->pic_type == FF_I_TYPE) {

        do {

            check_for_slice(h);

            decode_mb_i(h, 0);

        } while(ff_cavs_next_mb(h));

    } else if(h->pic_type == FF_P_TYPE) {

        do {

            check_for_slice(h);

            if(h->skip_mode_flag) {

                skip_count = get_ue_golomb(&s->gb);

                while(skip_count--) {

                    decode_mb_p(h,P_SKIP);

                    if(!ff_cavs_next_mb(h))

                        goto done;

                }

                check_for_slice(h);

                mb_type = get_ue_golomb(&s->gb) + P_16X16;

            } else

                mb_type = get_ue_golomb(&s->gb) + P_SKIP;

            if(mb_type > P_8X8) {

                decode_mb_i(h, mb_type - P_8X8 - 1);

            } else

                decode_mb_p(h,mb_type);

        } while(ff_cavs_next_mb(h));

    } else { /* FF_B_TYPE */

        do {

            check_for_slice(h);

            if(h->skip_mode_flag) {

                skip_count = get_ue_golomb(&s->gb);

                while(skip_count--) {

                    decode_mb_b(h,B_SKIP);

                    if(!ff_cavs_next_mb(h))

                        goto done;

                }

                check_for_slice(h);

                mb_type = get_ue_golomb(&s->gb) + B_DIRECT;

            } else

                mb_type = get_ue_golomb(&s->gb) + B_SKIP;

            if(mb_type > B_8X8) {

                decode_mb_i(h, mb_type - B_8X8 - 1);

            } else

                decode_mb_b(h,mb_type);

        } while(ff_cavs_next_mb(h));

    }

 done:

    if(h->pic_type != FF_B_TYPE) {

        if(h->DPB[1].data[0])

            s->avctx->release_buffer(s->avctx, (AVFrame *)&h->DPB[1]);

        h->DPB[1] = h->DPB[0];

        h->DPB[0] = h->picture;

        memset(&h->picture,0,sizeof(Picture));

    }

    return 0;

}


static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)

{

    GXFContext *gxf = s->priv_data;

    AVPacket new_pkt;

    int i;

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

        if (s->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {

            GXFStreamContext *sc = &gxf->streams[i];

            if (pkt && pkt->stream_index == i) {

                av_fifo_write(&sc->audio_buffer, pkt->data, pkt->size);

                pkt = NULL;

            }

            if (flush || av_fifo_size(&sc->audio_buffer) >= GXF_AUDIO_PACKET_SIZE) {

                if (!pkt && gxf_new_audio_packet(gxf, sc, &new_pkt, flush) > 0) {

                    pkt = &new_pkt;

                    break; /* add pkt right now into list */

                }

            }

        }

    }

    return av_interleave_packet_per_dts(s, out, pkt, flush);

}


int ff_nvdec_decode_init(AVCodecContext *avctx)

{

    NVDECContext *ctx = avctx->internal->hwaccel_priv_data;

    NVDECFramePool      *pool;

    AVHWFramesContext   *frames_ctx;

    const AVPixFmtDescriptor *sw_desc;

    CUVIDDECODECREATEINFO params = { 0 };

    int cuvid_codec_type, cuvid_chroma_format;

    int ret = 0;

    sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt);

    if (!sw_desc)

        return AVERROR_BUG;

    cuvid_codec_type = map_avcodec_id(avctx->codec_id);

    if (cuvid_codec_type < 0) {

        av_log(avctx, AV_LOG_ERROR, "Unsupported codec ID\n");

        return AVERROR_BUG;

    }

    cuvid_chroma_format = map_chroma_format(avctx->sw_pix_fmt);

    if (cuvid_chroma_format < 0) {

        av_log(avctx, AV_LOG_ERROR, "Unsupported chroma format\n");

        return AVERROR(ENOSYS);

    }

    if (!avctx->hw_frames_ctx) {

        ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_CUDA);

        if (ret < 0)

            return ret;

    }

    frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;

    params.ulWidth             = avctx->coded_width;

    params.ulHeight            = avctx->coded_height;

    params.ulTargetWidth       = avctx->coded_width;

    params.ulTargetHeight      = avctx->coded_height;

    params.bitDepthMinus8      = sw_desc->comp[0].depth - 8;

    params.OutputFormat        = params.bitDepthMinus8 ?

                                 cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12;

    params.CodecType           = cuvid_codec_type;

    params.ChromaFormat        = cuvid_chroma_format;

    params.ulNumDecodeSurfaces = frames_ctx->initial_pool_size;

    params.ulNumOutputSurfaces = 1;

    ret = nvdec_decoder_create(&ctx->decoder_ref, frames_ctx->device_ref, &params, avctx);

    if (ret < 0)

        return ret;

    pool = av_mallocz(sizeof(*pool));

    if (!pool) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    pool->dpb_size = frames_ctx->initial_pool_size;

    ctx->decoder_pool = av_buffer_pool_init2(sizeof(int), pool,

                                             nvdec_decoder_frame_alloc, av_free);

    if (!ctx->decoder_pool) {

        ret = AVERROR(ENOMEM);

        goto fail;

    }

    return 0;

fail:

    ff_nvdec_decode_uninit(avctx);

    return ret;

}


static void versatile_init(ram_addr_t ram_size,

                     const char *boot_device,

                     const char *kernel_filename, const char *kernel_cmdline,

                     const char *initrd_filename, const char *cpu_model,

                     int board_id)

{

    CPUState *env;

    ram_addr_t ram_offset;

    qemu_irq *cpu_pic;

    qemu_irq pic[32];

    qemu_irq sic[32];

    DeviceState *dev;

    PCIBus *pci_bus;

    NICInfo *nd;

    int n;

    int done_smc = 0;

    if (!cpu_model)

        cpu_model = "arm926";

    env = cpu_init(cpu_model);

    if (!env) {

        fprintf(stderr, "Unable to find CPU definition\n");

        exit(1);

    }

    ram_offset = qemu_ram_alloc(NULL, "versatile.ram", ram_size);

    /* ??? RAM should repeat to fill physical memory space.  */

    /* SDRAM at address zero.  */

    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);

    arm_sysctl_init(0x10000000, 0x41007004, 0x02000000);

    cpu_pic = arm_pic_init_cpu(env);

    dev = sysbus_create_varargs("pl190", 0x10140000,

                                cpu_pic[0], cpu_pic[1], NULL);

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

        pic[n] = qdev_get_gpio_in(dev, n);

    }

    dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);

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

        sysbus_connect_irq(sysbus_from_qdev(dev), n, pic[n]);

        sic[n] = qdev_get_gpio_in(dev, n);

    }

    sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);

    sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);

    dev = sysbus_create_varargs("versatile_pci", 0x40000000,

                                sic[27], sic[28], sic[29], sic[30], NULL);

    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");

    /* The Versatile PCI bridge does not provide access to PCI IO space,

       so many of the qemu PCI devices are not useable.  */

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

        nd = &nd_table[n];

        if ((!nd->model && !done_smc) || strcmp(nd->model, "smc91c111") == 0) {

            smc91c111_init(nd, 0x10010000, sic[25]);

            done_smc = 1;

        } else {

            pci_nic_init_nofail(nd, "rtl8139", NULL);

        }

    }

    if (usb_enabled) {

        usb_ohci_init_pci(pci_bus, -1);

    }

    n = drive_get_max_bus(IF_SCSI);

    while (n >= 0) {

        pci_create_simple(pci_bus, -1, "lsi53c895a");

        n--;

    }

    sysbus_create_simple("pl011", 0x101f1000, pic[12]);

    sysbus_create_simple("pl011", 0x101f2000, pic[13]);

    sysbus_create_simple("pl011", 0x101f3000, pic[14]);

    sysbus_create_simple("pl011", 0x10009000, sic[6]);

    sysbus_create_simple("pl080", 0x10130000, pic[17]);

    sysbus_create_simple("sp804", 0x101e2000, pic[4]);

    sysbus_create_simple("sp804", 0x101e3000, pic[5]);

    /* The versatile/PB actually has a modified Color LCD controller

       that includes hardware cursor support from the PL111.  */

    sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);

    sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);

    sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);

    /* Add PL031 Real Time Clock. */

    sysbus_create_simple("pl031", 0x101e8000, pic[10]);

    /* Memory map for Versatile/PB:  */

    /* 0x10000000 System registers.  */

    /* 0x10001000 PCI controller config registers.  */

    /* 0x10002000 Serial bus interface.  */

    /*  0x10003000 Secondary interrupt controller.  */

    /* 0x10004000 AACI (audio).  */

    /*  0x10005000 MMCI0.  */

    /*  0x10006000 KMI0 (keyboard).  */

    /*  0x10007000 KMI1 (mouse).  */

    /* 0x10008000 Character LCD Interface.  */

    /*  0x10009000 UART3.  */

    /* 0x1000a000 Smart card 1.  */

    /*  0x1000b000 MMCI1.  */

    /*  0x10010000 Ethernet.  */

    /* 0x10020000 USB.  */

    /* 0x10100000 SSMC.  */

    /* 0x10110000 MPMC.  */

    /*  0x10120000 CLCD Controller.  */

    /*  0x10130000 DMA Controller.  */

    /*  0x10140000 Vectored interrupt controller.  */

    /* 0x101d0000 AHB Monitor Interface.  */

    /* 0x101e0000 System Controller.  */

    /* 0x101e1000 Watchdog Interface.  */

    /* 0x101e2000 Timer 0/1.  */

    /* 0x101e3000 Timer 2/3.  */

    /* 0x101e4000 GPIO port 0.  */

    /* 0x101e5000 GPIO port 1.  */

    /* 0x101e6000 GPIO port 2.  */

    /* 0x101e7000 GPIO port 3.  */

    /* 0x101e8000 RTC.  */

    /* 0x101f0000 Smart card 0.  */

    /*  0x101f1000 UART0.  */

    /*  0x101f2000 UART1.  */

    /*  0x101f3000 UART2.  */

    /* 0x101f4000 SSPI.  */

    versatile_binfo.ram_size = ram_size;

    versatile_binfo.kernel_filename = kernel_filename;

    versatile_binfo.kernel_cmdline = kernel_cmdline;

    versatile_binfo.initrd_filename = initrd_filename;

    versatile_binfo.board_id = board_id;

    arm_load_kernel(env, &versatile_binfo);

}


static void kvm_mem_ioeventfd_add(MemoryListener *listener,

                                  MemoryRegionSection *section,

                                  bool match_data, uint64_t data,

                                  EventNotifier *e)

{

    int fd = event_notifier_get_fd(e);

    int r;

    r = kvm_set_ioeventfd_mmio(fd, section->offset_within_address_space,

                               data, true, int128_get64(section->size),

                               match_data);

    if (r < 0) {

        abort();

    }

}


static void vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr)

{

    PCIDevice *pdev = &vdev->pdev;

    VFIOQuirk *quirk;

    if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_REALTEK ||

        pci_get_word(pdev->config + PCI_DEVICE_ID) != 0x8168 || nr != 2) {

        return;

    }

    quirk = g_malloc0(sizeof(*quirk));

    quirk->vdev = vdev;

    quirk->data.bar = nr;

    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_rtl8168_window_quirk,

                          quirk, "vfio-rtl8168-window-quirk", 8);

    memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,

                                        0x70, &quirk->mem, 1);

    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);

    trace_vfio_probe_rtl8168_bar2_window_quirk(vdev->vbasedev.name);

}


tcp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,

           u_int lport, int flags)

{

	struct sockaddr_in addr;

	struct socket *so;

	int s, opt = 1;

	socklen_t addrlen = sizeof(addr);

	DEBUG_CALL("tcp_listen");

	DEBUG_ARG("haddr = %x", haddr);

	DEBUG_ARG("hport = %d", hport);

	DEBUG_ARG("laddr = %x", laddr);

	DEBUG_ARG("lport = %d", lport);

	DEBUG_ARG("flags = %x", flags);

	so = socreate(slirp);

	if (!so) {

	  return NULL;

	}

	/* Don't tcp_attach... we don't need so_snd nor so_rcv */

	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {

		free(so);

		return NULL;

	}

	insque(so, &slirp->tcb);

	/*

	 * SS_FACCEPTONCE sockets must time out.

	 */

	if (flags & SS_FACCEPTONCE)

	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;

	so->so_state &= SS_PERSISTENT_MASK;

	so->so_state |= (SS_FACCEPTCONN | flags);

	so->so_lport = lport; /* Kept in network format */

	so->so_laddr.s_addr = laddr; /* Ditto */

	addr.sin_family = AF_INET;

	addr.sin_addr.s_addr = haddr;

	addr.sin_port = hport;

	if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||

	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||

	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||

	    (listen(s,1) < 0)) {

		int tmperrno = errno; /* Don't clobber the real reason we failed */

		close(s);

		sofree(so);

		/* Restore the real errno */

#ifdef _WIN32

		WSASetLastError(tmperrno);

#else

		errno = tmperrno;

#endif

		return NULL;

	}

	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));

	getsockname(s,(struct sockaddr *)&addr,&addrlen);

	so->so_fport = addr.sin_port;

	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)

	   so->so_faddr = slirp->vhost_addr;

	else

	   so->so_faddr = addr.sin_addr;

	so->s = s;

	return so;

}


static void test_dummy_createcmdl(void)
{
    QemuOpts *opts;
    DummyObject *dobj;
    Error *err = NULL;
    const char *params = TYPE_DUMMY \
                         ",id=dev0," \
                         "bv=yes,sv=Hiss hiss hiss,av=platypus";
    qemu_add_opts(&qemu_object_opts);
    opts = qemu_opts_parse(&qemu_object_opts, params, true, &err);
    g_assert(err == NULL);
    g_assert(opts);
    dobj = DUMMY_OBJECT(user_creatable_add_opts(opts, &err));
    g_assert(err == NULL);
    g_assert(dobj);
    g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
    g_assert(dobj->bv == true);
    g_assert(dobj->av == DUMMY_PLATYPUS);
    user_creatable_del("dev0", &err);
    g_assert(err == NULL);
    error_free(err);
    /*
     * cmdline-parsing via qemu_opts_parse() results in a QemuOpts entry
     * corresponding to the Object's ID to be added to the QemuOptsList
     * for objects. To avoid having this entry conflict with future
     * Objects using the same ID (which can happen in cases where
     * qemu_opts_parse() is used to parse the object params, such as
     * with hmp_object_add() at the time of this comment), we need to
     * check for this in user_creatable_del() and remove the QemuOpts if
     * it is present.
     *
     * The below check ensures this works as expected.
     */
    g_assert_null(qemu_opts_find(&qemu_object_opts, "dev0"));
}