void gen_intermediate_code_internal_a64(ARMCPU *cpu,

                                        TranslationBlock *tb,

                                        bool search_pc)

{

    CPUState *cs = CPU(cpu);

    CPUARMState *env = &cpu->env;

    DisasContext dc1, *dc = &dc1;

    CPUBreakpoint *bp;

    int j, lj;

    target_ulong pc_start;

    target_ulong next_page_start;

    int num_insns;

    int max_insns;

    pc_start = tb->pc;

    dc->tb = tb;

    dc->is_jmp = DISAS_NEXT;

    dc->pc = pc_start;

    dc->singlestep_enabled = cs->singlestep_enabled;

    dc->condjmp = 0;

    dc->aarch64 = 1;

    dc->el3_is_aa64 = arm_el_is_aa64(env, 3);

    dc->thumb = 0;

    dc->bswap_code = 0;

    dc->condexec_mask = 0;

    dc->condexec_cond = 0;

    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);

    dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);

#if !defined(CONFIG_USER_ONLY)

    dc->user = (dc->current_el == 0);

#endif

    dc->cpacr_fpen = ARM_TBFLAG_AA64_FPEN(tb->flags);

    dc->vec_len = 0;

    dc->vec_stride = 0;

    dc->cp_regs = cpu->cp_regs;

    dc->features = env->features;

    /* Single step state. The code-generation logic here is:

     *  SS_ACTIVE == 0:

     *   generate code with no special handling for single-stepping (except

     *   that anything that can make us go to SS_ACTIVE == 1 must end the TB;

     *   this happens anyway because those changes are all system register or

     *   PSTATE writes).

     *  SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)

     *   emit code for one insn

     *   emit code to clear PSTATE.SS

     *   emit code to generate software step exception for completed step

     *   end TB (as usual for having generated an exception)

     *  SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)

     *   emit code to generate a software step exception

     *   end the TB

     */

    dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);

    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);

    dc->is_ldex = false;

    dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);

    init_tmp_a64_array(dc);

    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;

    lj = -1;

    num_insns = 0;

    max_insns = tb->cflags & CF_COUNT_MASK;

    if (max_insns == 0) {

        max_insns = CF_COUNT_MASK;

    }

    gen_tb_start(tb);

    tcg_clear_temp_count();

    do {

        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {

            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {

                if (bp->pc == dc->pc) {

                    gen_exception_internal_insn(dc, 0, EXCP_DEBUG);

                    /* Advance PC so that clearing the breakpoint will

                       invalidate this TB.  */

                    dc->pc += 2;

                    goto done_generating;

                }

            }

        }

        if (search_pc) {

            j = tcg_op_buf_count();

            if (lj < j) {

                lj++;

                while (lj < j) {

                    tcg_ctx.gen_opc_instr_start[lj++] = 0;

                }

            }

            tcg_ctx.gen_opc_pc[lj] = dc->pc;

            tcg_ctx.gen_opc_instr_start[lj] = 1;

            tcg_ctx.gen_opc_icount[lj] = num_insns;

        }

        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {

            gen_io_start();

        }

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

            tcg_gen_debug_insn_start(dc->pc);

        }

        if (dc->ss_active && !dc->pstate_ss) {

            /* Singlestep state is Active-pending.

             * If we're in this state at the start of a TB then either

             *  a) we just took an exception to an EL which is being debugged

             *     and this is the first insn in the exception handler

             *  b) debug exceptions were masked and we just unmasked them

             *     without changing EL (eg by clearing PSTATE.D)

             * In either case we're going to take a swstep exception in the

             * "did not step an insn" case, and so the syndrome ISV and EX

             * bits should be zero.

             */

            assert(num_insns == 0);

            gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),

                          default_exception_el(dc));

            dc->is_jmp = DISAS_EXC;

            break;

        }

        disas_a64_insn(env, dc);

        if (tcg_check_temp_count()) {

            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",

                    dc->pc);

        }

        /* Translation stops when a conditional branch is encountered.

         * Otherwise the subsequent code could get translated several times.

         * Also stop translation when a page boundary is reached.  This

         * ensures prefetch aborts occur at the right place.

         */

        num_insns++;

    } while (!dc->is_jmp && !tcg_op_buf_full() &&

             !cs->singlestep_enabled &&

             !singlestep &&

             !dc->ss_active &&

             dc->pc < next_page_start &&

             num_insns < max_insns);

    if (tb->cflags & CF_LAST_IO) {

        gen_io_end();

    }

    if (unlikely(cs->singlestep_enabled || dc->ss_active)

        && dc->is_jmp != DISAS_EXC) {

        /* Note that this means single stepping WFI doesn't halt the CPU.

         * For conditional branch insns this is harmless unreachable code as

         * gen_goto_tb() has already handled emitting the debug exception

         * (and thus a tb-jump is not possible when singlestepping).

         */

        assert(dc->is_jmp != DISAS_TB_JUMP);

        if (dc->is_jmp != DISAS_JUMP) {

            gen_a64_set_pc_im(dc->pc);

        }

        if (cs->singlestep_enabled) {

            gen_exception_internal(EXCP_DEBUG);

        } else {

            gen_step_complete_exception(dc);

        }

    } else {

        switch (dc->is_jmp) {

        case DISAS_NEXT:

            gen_goto_tb(dc, 1, dc->pc);

            break;

        default:

        case DISAS_UPDATE:

            gen_a64_set_pc_im(dc->pc);

            /* fall through */

        case DISAS_JUMP:

            /* indicate that the hash table must be used to find the next TB */

            tcg_gen_exit_tb(0);

            break;

        case DISAS_TB_JUMP:

        case DISAS_EXC:

        case DISAS_SWI:

            break;

        case DISAS_WFE:

            gen_a64_set_pc_im(dc->pc);

            gen_helper_wfe(cpu_env);

            break;

        case DISAS_WFI:

            /* This is a special case because we don't want to just halt the CPU

             * if trying to debug across a WFI.

             */

            gen_a64_set_pc_im(dc->pc);

            gen_helper_wfi(cpu_env);

            break;

        }

    }

done_generating:

    gen_tb_end(tb, num_insns);

#ifdef DEBUG_DISAS

    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {

        qemu_log("----------------\n");

        qemu_log("IN: %s\n", lookup_symbol(pc_start));

        log_target_disas(env, pc_start, dc->pc - pc_start,

                         4 | (dc->bswap_code << 1));

        qemu_log("\n");

    }

#endif

    if (search_pc) {

        j = tcg_op_buf_count();

        lj++;

        while (lj <= j) {

            tcg_ctx.gen_opc_instr_start[lj++] = 0;

        }

    } else {

        tb->size = dc->pc - pc_start;

        tb->icount = num_insns;

    }

}


static void gen_farith (DisasContext *ctx, uint32_t op1, int ft,

                        int fs, int fd, int cc)

{

    const char *opn = "farith";

    const char *condnames[] = {

            "c.f",

            "c.un",

            "c.eq",

            "c.ueq",

            "c.olt",

            "c.ult",

            "c.ole",

            "c.ule",

            "c.sf",

            "c.ngle",

            "c.seq",

            "c.ngl",

            "c.lt",

            "c.nge",

            "c.le",

            "c.ngt",

    };

    const char *condnames_abs[] = {

            "cabs.f",

            "cabs.un",

            "cabs.eq",

            "cabs.ueq",

            "cabs.olt",

            "cabs.ult",

            "cabs.ole",

            "cabs.ule",

            "cabs.sf",

            "cabs.ngle",

            "cabs.seq",

            "cabs.ngl",

            "cabs.lt",

            "cabs.nge",

            "cabs.le",

            "cabs.ngt",

    };

    enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;

    uint32_t func = ctx->opcode & 0x3f;

    switch (ctx->opcode & FOP(0x3f, 0x1f)) {

    case FOP(0, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        gen_op_float_add_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "add.s";

        optype = BINOP;

        break;

    case FOP(1, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        gen_op_float_sub_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "sub.s";

        optype = BINOP;

        break;

    case FOP(2, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        gen_op_float_mul_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "mul.s";

        optype = BINOP;

        break;

    case FOP(3, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        gen_op_float_div_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "div.s";

        optype = BINOP;

        break;

    case FOP(4, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_sqrt_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "sqrt.s";

        break;

    case FOP(5, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_abs_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "abs.s";

        break;

    case FOP(6, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_mov_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "mov.s";

        break;

    case FOP(7, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_chs_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "neg.s";

        break;

    case FOP(8, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_roundl_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "round.l.s";

        break;

    case FOP(9, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_truncl_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "trunc.l.s";

        break;

    case FOP(10, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_ceill_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "ceil.l.s";

        break;

    case FOP(11, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_floorl_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "floor.l.s";

        break;

    case FOP(12, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_roundw_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "round.w.s";

        break;

    case FOP(13, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_truncw_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "trunc.w.s";

        break;

    case FOP(14, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_ceilw_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "ceil.w.s";

        break;

    case FOP(15, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_floorw_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "floor.w.s";

        break;

    case FOP(17, 16):

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        gen_movcf_s(ctx, (ft >> 2) & 0x7, ft & 0x1);

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "movcf.s";

        break;

    case FOP(18, 16):

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        gen_op_float_movz_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "movz.s";

        break;

    case FOP(19, 16):

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        gen_op_float_movn_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "movn.s";

        break;

    case FOP(21, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_recip_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "recip.s";

        break;

    case FOP(22, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_rsqrt_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "rsqrt.s";

        break;

    case FOP(28, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        gen_op_float_recip2_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "recip2.s";

        break;

    case FOP(29, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_recip1_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "recip1.s";

        break;

    case FOP(30, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_rsqrt1_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "rsqrt1.s";

        break;

    case FOP(31, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        gen_op_float_rsqrt2_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "rsqrt2.s";

        break;

    case FOP(33, 16):

        gen_op_cp1_registers(fd);

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_cvtd_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "cvt.d.s";

        break;

    case FOP(36, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_cvtw_s();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.w.s";

        break;

    case FOP(37, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_cvtl_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "cvt.l.s";

        break;

    case FOP(38, 16):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT1, fs);

        GEN_LOAD_FREG_FTN(WT0, ft);

        gen_op_float_cvtps_s();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "cvt.ps.s";

        break;

    case FOP(48, 16):

    case FOP(49, 16):

    case FOP(50, 16):

    case FOP(51, 16):

    case FOP(52, 16):

    case FOP(53, 16):

    case FOP(54, 16):

    case FOP(55, 16):

    case FOP(56, 16):

    case FOP(57, 16):

    case FOP(58, 16):

    case FOP(59, 16):

    case FOP(60, 16):

    case FOP(61, 16):

    case FOP(62, 16):

    case FOP(63, 16):

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        if (ctx->opcode & (1 << 6)) {

            gen_op_cp1_64bitmode();

            gen_cmpabs_s(func-48, cc);

            opn = condnames_abs[func-48];

        } else {

            gen_cmp_s(func-48, cc);

            opn = condnames[func-48];

        }

        break;

    case FOP(0, 17):

        gen_op_cp1_registers(fs | ft | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        gen_op_float_add_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "add.d";

        optype = BINOP;

        break;

    case FOP(1, 17):

        gen_op_cp1_registers(fs | ft | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        gen_op_float_sub_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "sub.d";

        optype = BINOP;

        break;

    case FOP(2, 17):

        gen_op_cp1_registers(fs | ft | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        gen_op_float_mul_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "mul.d";

        optype = BINOP;

        break;

    case FOP(3, 17):

        gen_op_cp1_registers(fs | ft | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        gen_op_float_div_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "div.d";

        optype = BINOP;

        break;

    case FOP(4, 17):

        gen_op_cp1_registers(fs | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_sqrt_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "sqrt.d";

        break;

    case FOP(5, 17):

        gen_op_cp1_registers(fs | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_abs_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "abs.d";

        break;

    case FOP(6, 17):

        gen_op_cp1_registers(fs | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_mov_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "mov.d";

        break;

    case FOP(7, 17):

        gen_op_cp1_registers(fs | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_chs_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "neg.d";

        break;

    case FOP(8, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_roundl_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "round.l.d";

        break;

    case FOP(9, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_truncl_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "trunc.l.d";

        break;

    case FOP(10, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_ceill_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "ceil.l.d";

        break;

    case FOP(11, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_floorl_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "floor.l.d";

        break;

    case FOP(12, 17):

        gen_op_cp1_registers(fs);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_roundw_d();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "round.w.d";

        break;

    case FOP(13, 17):

        gen_op_cp1_registers(fs);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_truncw_d();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "trunc.w.d";

        break;

    case FOP(14, 17):

        gen_op_cp1_registers(fs);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_ceilw_d();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "ceil.w.d";

        break;

    case FOP(15, 17):

        gen_op_cp1_registers(fs);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_floorw_d();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "floor.w.d";

        break;

    case FOP(17, 17):

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT2, fd);

        gen_movcf_d(ctx, (ft >> 2) & 0x7, ft & 0x1);

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "movcf.d";

        break;

    case FOP(18, 17):

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT2, fd);

        gen_op_float_movz_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "movz.d";

        break;

    case FOP(19, 17):

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT2, fd);

        gen_op_float_movn_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "movn.d";

        break;

    case FOP(21, 17):

        gen_op_cp1_registers(fs | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_recip_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "recip.d";

        break;

    case FOP(22, 17):

        gen_op_cp1_registers(fs | fd);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_rsqrt_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "rsqrt.d";

        break;

    case FOP(28, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT2, ft);

        gen_op_float_recip2_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "recip2.d";

        break;

    case FOP(29, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_recip1_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "recip1.d";

        break;

    case FOP(30, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_rsqrt1_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "rsqrt1.d";

        break;

    case FOP(31, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT2, ft);

        gen_op_float_rsqrt2_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "rsqrt2.d";

        break;

    case FOP(48, 17):

    case FOP(49, 17):

    case FOP(50, 17):

    case FOP(51, 17):

    case FOP(52, 17):

    case FOP(53, 17):

    case FOP(54, 17):

    case FOP(55, 17):

    case FOP(56, 17):

    case FOP(57, 17):

    case FOP(58, 17):

    case FOP(59, 17):

    case FOP(60, 17):

    case FOP(61, 17):

    case FOP(62, 17):

    case FOP(63, 17):

        GEN_LOAD_FREG_FTN(DT0, fs);

        GEN_LOAD_FREG_FTN(DT1, ft);

        if (ctx->opcode & (1 << 6)) {

            gen_op_cp1_64bitmode();

            gen_cmpabs_d(func-48, cc);

            opn = condnames_abs[func-48];

        } else {

            gen_op_cp1_registers(fs | ft);

            gen_cmp_d(func-48, cc);

            opn = condnames[func-48];

        }

        break;

    case FOP(32, 17):

        gen_op_cp1_registers(fs);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_cvts_d();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.s.d";

        break;

    case FOP(36, 17):

        gen_op_cp1_registers(fs);

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_cvtw_d();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.w.d";

        break;

    case FOP(37, 17):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_cvtl_d();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "cvt.l.d";

        break;

    case FOP(32, 20):

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_cvts_w();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.s.w";

        break;

    case FOP(33, 20):

        gen_op_cp1_registers(fd);

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_cvtd_w();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "cvt.d.w";

        break;

    case FOP(32, 21):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_cvts_l();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.s.l";

        break;

    case FOP(33, 21):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(DT0, fs);

        gen_op_float_cvtd_l();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "cvt.d.l";

        break;

    case FOP(38, 20):

    case FOP(38, 21):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_cvtps_pw();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "cvt.ps.pw";

        break;

    case FOP(0, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        gen_op_float_add_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "add.ps";

        break;

    case FOP(1, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        gen_op_float_sub_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "sub.ps";

        break;

    case FOP(2, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        gen_op_float_mul_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "mul.ps";

        break;

    case FOP(5, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_abs_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "abs.ps";

        break;

    case FOP(6, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_mov_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "mov.ps";

        break;

    case FOP(7, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_chs_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "neg.ps";

        break;

    case FOP(17, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        GEN_LOAD_FREG_FTN(WTH2, fd);

        gen_movcf_ps(ctx, (ft >> 2) & 0x7, ft & 0x1);

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "movcf.ps";

        break;

    case FOP(18, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        GEN_LOAD_FREG_FTN(WTH2, fd);

        gen_op_float_movz_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "movz.ps";

        break;

    case FOP(19, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_REG_TN(T0, ft);

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        GEN_LOAD_FREG_FTN(WTH2, fd);

        gen_op_float_movn_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "movn.ps";

        break;

    case FOP(24, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, ft);

        GEN_LOAD_FREG_FTN(WTH0, ft);

        GEN_LOAD_FREG_FTN(WT1, fs);

        GEN_LOAD_FREG_FTN(WTH1, fs);

        gen_op_float_addr_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "addr.ps";

        break;

    case FOP(26, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, ft);

        GEN_LOAD_FREG_FTN(WTH0, ft);

        GEN_LOAD_FREG_FTN(WT1, fs);

        GEN_LOAD_FREG_FTN(WTH1, fs);

        gen_op_float_mulr_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "mulr.ps";

        break;

    case FOP(28, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        GEN_LOAD_FREG_FTN(WTH2, fd);

        gen_op_float_recip2_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "recip2.ps";

        break;

    case FOP(29, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_recip1_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "recip1.ps";

        break;

    case FOP(30, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_rsqrt1_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "rsqrt1.ps";

        break;

    case FOP(31, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT2, fd);

        GEN_LOAD_FREG_FTN(WTH2, fd);

        gen_op_float_rsqrt2_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "rsqrt2.ps";

        break;

    case FOP(32, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_cvts_pu();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.s.pu";

        break;

    case FOP(36, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        gen_op_float_cvtpw_ps();

        GEN_STORE_FTN_FREG(fd, WT2);

        GEN_STORE_FTN_FREG(fd, WTH2);

        opn = "cvt.pw.ps";

        break;

    case FOP(40, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        gen_op_float_cvts_pl();

        GEN_STORE_FTN_FREG(fd, WT2);

        opn = "cvt.s.pl";

        break;

    case FOP(44, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        gen_op_float_pll_ps();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "pll.ps";

        break;

    case FOP(45, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        gen_op_float_plu_ps();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "plu.ps";

        break;

    case FOP(46, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        gen_op_float_pul_ps();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "pul.ps";

        break;

    case FOP(47, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        gen_op_float_puu_ps();

        GEN_STORE_FTN_FREG(fd, DT2);

        opn = "puu.ps";

        break;

    case FOP(48, 22):

    case FOP(49, 22):

    case FOP(50, 22):

    case FOP(51, 22):

    case FOP(52, 22):

    case FOP(53, 22):

    case FOP(54, 22):

    case FOP(55, 22):

    case FOP(56, 22):

    case FOP(57, 22):

    case FOP(58, 22):

    case FOP(59, 22):

    case FOP(60, 22):

    case FOP(61, 22):

    case FOP(62, 22):

    case FOP(63, 22):

        gen_op_cp1_64bitmode();

        GEN_LOAD_FREG_FTN(WT0, fs);

        GEN_LOAD_FREG_FTN(WTH0, fs);

        GEN_LOAD_FREG_FTN(WT1, ft);

        GEN_LOAD_FREG_FTN(WTH1, ft);

        if (ctx->opcode & (1 << 6)) {

            gen_cmpabs_ps(func-48, cc);

            opn = condnames_abs[func-48];

        } else {

            gen_cmp_ps(func-48, cc);

            opn = condnames[func-48];

        }

        break;

    default:

        MIPS_INVAL(opn);

        generate_exception (ctx, EXCP_RI);

        return;

    }

    switch (optype) {

    case BINOP:

        MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);

        break;

    case CMPOP:

        MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);

        break;

    default:

        MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);

        break;

    }

}


static int count_contiguous_clusters_unallocated(int nb_clusters,

                                                 uint64_t *l2_table,

                                                 QCow2ClusterType wanted_type)

{

    int i;

    assert(wanted_type == QCOW2_CLUSTER_ZERO ||

           wanted_type == QCOW2_CLUSTER_UNALLOCATED);

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

        uint64_t entry = be64_to_cpu(l2_table[i]);

        QCow2ClusterType type = qcow2_get_cluster_type(entry);

        if (type != wanted_type || entry & L2E_OFFSET_MASK) {

            break;

        }

    }

    return i;

}


static void rv34_idct_dc_add_c(uint8_t *dst, ptrdiff_t stride, int dc)

{

    const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;

    int i, j;

    cm += (13*13*dc + 0x200) >> 10;

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

    {

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

            dst[j] = cm[ dst[j] ];

        dst += stride;

    }

}


qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,

                      const char *kernel_filename, const char *cpu_model)

{

    ARMCPU *cpu;

    CPUARMState *env;

    DeviceState *nvic;

    qemu_irq *pic = g_new(qemu_irq, num_irq);

    int image_size;

    uint64_t entry;

    uint64_t lowaddr;

    int i;

    int big_endian;

    MemoryRegion *hack = g_new(MemoryRegion, 1);

    if (cpu_model == NULL) {

	cpu_model = "cortex-m3";

    }

    cpu = cpu_arm_init(cpu_model);

    if (cpu == NULL) {

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

        exit(1);

    }

    env = &cpu->env;

    armv7m_bitband_init();

    nvic = qdev_create(NULL, "armv7m_nvic");

    qdev_prop_set_uint32(nvic, "num-irq", num_irq);

    env->nvic = nvic;

    qdev_init_nofail(nvic);

    sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,

                       qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));

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

        pic[i] = qdev_get_gpio_in(nvic, i);

    }

#ifdef TARGET_WORDS_BIGENDIAN

    big_endian = 1;

#else

    big_endian = 0;

#endif

    if (!kernel_filename && !qtest_enabled()) {

        fprintf(stderr, "Guest image must be specified (using -kernel)\n");

        exit(1);

    }

    if (kernel_filename) {

        image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,

                              NULL, big_endian, ELF_MACHINE, 1);

        if (image_size < 0) {

            image_size = load_image_targphys(kernel_filename, 0, mem_size);

            lowaddr = 0;

        }

        if (image_size < 0) {

            error_report("Could not load kernel '%s'", kernel_filename);

            exit(1);

        }

    }

    /* Hack to map an additional page of ram at the top of the address

       space.  This stops qemu complaining about executing code outside RAM

       when returning from an exception.  */

    memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000, &error_abort);

    vmstate_register_ram_global(hack);

    memory_region_add_subregion(system_memory, 0xfffff000, hack);

    qemu_register_reset(armv7m_reset, cpu);

    return pic;

}


int qemu_show_nic_models(const char *arg, const char *const *models)

{

    int i;

    if (!arg || strcmp(arg, "?"))

        return 0;

    fprintf(stderr, "qemu: Supported NIC models: ");

    for (i = 0 ; models[i]; i++)

        fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n');

    return 1;

}


void openrisc_cpu_do_interrupt(CPUState *cs)

{

#ifndef CONFIG_USER_ONLY

    OpenRISCCPU *cpu = OPENRISC_CPU(cs);

    CPUOpenRISCState *env = &cpu->env;

    env->epcr = env->pc;

    if (env->flags & D_FLAG) {

        env->flags &= ~D_FLAG;

        env->sr |= SR_DSX;

        env->epcr -= 4;

    if (cs->exception_index == EXCP_SYSCALL) {

        env->epcr += 4;

    /* For machine-state changed between user-mode and supervisor mode,

       we need flush TLB when we enter&exit EXCP.  */

    tlb_flush(cs);

    env->esr = env->sr;

    env->sr &= ~SR_DME;

    env->sr &= ~SR_IME;

    env->sr |= SR_SM;

    env->sr &= ~SR_IEE;

    env->sr &= ~SR_TEE;

    env->tlb->cpu_openrisc_map_address_data = &cpu_openrisc_get_phys_nommu;

    env->tlb->cpu_openrisc_map_address_code = &cpu_openrisc_get_phys_nommu;

    if (cs->exception_index > 0 && cs->exception_index < EXCP_NR) {

        env->pc = (cs->exception_index << 8);

        cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);

#endif

    cs->exception_index = -1;


static char *qemu_rbd_array_opts(QDict *options, const char *prefix, int type,

                                 Error **errp)

{

    int num_entries;

    QemuOpts *opts = NULL;

    QDict *sub_options;

    const char *host;

    const char *port;

    char *str;

    char *rados_str = NULL;

    Error *local_err = NULL;

    int i;

    assert(type == RBD_MON_HOST);

    num_entries = qdict_array_entries(options, prefix);

    if (num_entries < 0) {

        error_setg(errp, "Parse error on RBD QDict array");

        return NULL;

    }

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

        char *strbuf = NULL;

        const char *value;

        char *rados_str_tmp;

        str = g_strdup_printf("%s%d.", prefix, i);

        qdict_extract_subqdict(options, &sub_options, str);

        g_free(str);

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

        qemu_opts_absorb_qdict(opts, sub_options, &local_err);

        QDECREF(sub_options);

        if (local_err) {

            error_propagate(errp, local_err);

            g_free(rados_str);

            rados_str = NULL;

            goto exit;

        }

        if (type == RBD_MON_HOST) {

            host = qemu_opt_get(opts, "host");

            port = qemu_opt_get(opts, "port");

            value = host;

            if (port) {

                /* check for ipv6 */

                if (strchr(host, ':')) {

                    strbuf = g_strdup_printf("[%s]:%s", host, port);

                } else {

                    strbuf = g_strdup_printf("%s:%s", host, port);

                }

                value = strbuf;

            } else if (strchr(host, ':')) {

                strbuf = g_strdup_printf("[%s]", host);

                value = strbuf;

            }

        } else {

            abort();

        }

        /* each iteration in the for loop will build upon the string, and if

         * rados_str is NULL then it is our first pass */

        if (rados_str) {

            /* separate options with ';', as that  is what rados_conf_set()

             * requires */

            rados_str_tmp = rados_str;

            rados_str = g_strdup_printf("%s;%s", rados_str_tmp, value);

            g_free(rados_str_tmp);

        } else {

            rados_str = g_strdup(value);

        }

        g_free(strbuf);

        qemu_opts_del(opts);

        opts = NULL;

    }

exit:

    qemu_opts_del(opts);

    return rados_str;

}


static float *put_vector(vorbis_enc_codebook *book, PutBitContext *pb,

                         float *num)

{

    int i, entry = -1;

    float distance = FLT_MAX;

    assert(book->dimentions);

    for (i = 0; i < book->nentries; i++) {

        float * vec = book->dimentions + i * book->ndimentions, d = book->pow2[i];

        int j;

        if (!book->lens[i])

            continue;

        for (j = 0; j < book->ndimentions; j++)

            d -= vec[j] * num[j];

        if (distance > d) {

            entry    = i;

            distance = d;

        }

    }

    put_codeword(pb, book, entry);

    return &book->dimentions[entry * book->ndimentions];

}


static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
{
        MOVMuxContext *mov = s->priv_data;
        MOVTrack *trk = &mov->tracks[pkt->stream_index];
        AVCodecParameters *par = trk->par;
        int64_t frag_duration = 0;
        int size = pkt->size;
        if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
            int i;
            for (i = 0; i < s->nb_streams; i++)
                mov->tracks[i].frag_discont = 1;
            mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
        }
        if (!pkt->size) {
            if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) {
                trk->start_dts = pkt->dts;
                if (pkt->pts != AV_NOPTS_VALUE)
                    trk->start_cts = pkt->pts - pkt->dts;
                else
                    trk->start_cts = 0;
            }
            if (trk->par->codec_id == AV_CODEC_ID_MP4ALS) {
                int side_size = 0;
                uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
                if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
                    void *newextra = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
                    if (!newextra)
                        return AVERROR(ENOMEM);
                    av_free(par->extradata);
                    par->extradata = newextra;
                    memcpy(par->extradata, side, side_size);
                    par->extradata_size = side_size;
                    mov->need_rewrite_extradata = 1;
                }
            }
            return 0;             /* Discard 0 sized packets */
        }
        if (trk->entry && pkt->stream_index < s->nb_streams)
            frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
                                         s->streams[pkt->stream_index]->time_base,
                                         AV_TIME_BASE_Q);
        if ((mov->max_fragment_duration &&
             frag_duration >= mov->max_fragment_duration) ||
             (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
             (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
              par->codec_type == AVMEDIA_TYPE_VIDEO &&
              trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) {
            if (frag_duration >= mov->min_fragment_duration) {
                // Set the duration of this track to line up with the next
                // sample in this track. This avoids relying on AVPacket
                // duration, but only helps for this particular track, not
                // for the other ones that are flushed at the same time.
                trk->track_duration = pkt->dts - trk->start_dts;
                if (pkt->pts != AV_NOPTS_VALUE)
                    trk->end_pts = pkt->pts;
                else
                    trk->end_pts = pkt->dts;
                trk->end_reliable = 1;
                mov_auto_flush_fragment(s, 0);
            }
        }
        return ff_mov_write_packet(s, pkt);
}


int cpu_exec(CPUArchState *env)

{

    CPUState *cpu = ENV_GET_CPU(env);

#if !(defined(CONFIG_USER_ONLY) && \

      (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))

    CPUClass *cc = CPU_GET_CLASS(cpu);

#endif

#ifdef TARGET_I386

    X86CPU *x86_cpu = X86_CPU(cpu);

#endif

    int ret, interrupt_request;

    TranslationBlock *tb;

    uint8_t *tc_ptr;

    uintptr_t next_tb;

    if (cpu->halted) {

        if (!cpu_has_work(cpu)) {

            return EXCP_HALTED;

        }

        cpu->halted = 0;

    }

    current_cpu = cpu;

    /* As long as current_cpu is null, up to the assignment just above,

     * requests by other threads to exit the execution loop are expected to

     * be issued using the exit_request global. We must make sure that our

     * evaluation of the global value is performed past the current_cpu

     * value transition point, which requires a memory barrier as well as

     * an instruction scheduling constraint on modern architectures.  */

    smp_mb();

    if (unlikely(exit_request)) {

        cpu->exit_request = 1;

    }

#if defined(TARGET_I386)

    /* put eflags in CPU temporary format */

    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);

    env->df = 1 - (2 * ((env->eflags >> 10) & 1));

    CC_OP = CC_OP_EFLAGS;

    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);

#elif defined(TARGET_SPARC)

#elif defined(TARGET_M68K)

    env->cc_op = CC_OP_FLAGS;

    env->cc_dest = env->sr & 0xf;

    env->cc_x = (env->sr >> 4) & 1;

#elif defined(TARGET_ALPHA)

#elif defined(TARGET_ARM)

#elif defined(TARGET_UNICORE32)

#elif defined(TARGET_PPC)

    env->reserve_addr = -1;

#elif defined(TARGET_LM32)

#elif defined(TARGET_MICROBLAZE)

#elif defined(TARGET_MIPS)

#elif defined(TARGET_MOXIE)

#elif defined(TARGET_OPENRISC)

#elif defined(TARGET_SH4)

#elif defined(TARGET_CRIS)

#elif defined(TARGET_S390X)

#elif defined(TARGET_XTENSA)

    /* XXXXX */

#else

#error unsupported target CPU

#endif

    cpu->exception_index = -1;

    /* prepare setjmp context for exception handling */

    for(;;) {

        if (sigsetjmp(cpu->jmp_env, 0) == 0) {

            /* if an exception is pending, we execute it here */

            if (cpu->exception_index >= 0) {

                if (cpu->exception_index >= EXCP_INTERRUPT) {

                    /* exit request from the cpu execution loop */

                    ret = cpu->exception_index;

                    if (ret == EXCP_DEBUG) {

                        cpu_handle_debug_exception(env);

                    }

                    break;

                } else {

#if defined(CONFIG_USER_ONLY)

                    /* if user mode only, we simulate a fake exception

                       which will be handled outside the cpu execution

                       loop */

#if defined(TARGET_I386)

                    cc->do_interrupt(cpu);

#endif

                    ret = cpu->exception_index;

                    break;

#else

                    cc->do_interrupt(cpu);

                    cpu->exception_index = -1;

#endif

                }

            }

            next_tb = 0; /* force lookup of first TB */

            for(;;) {

                interrupt_request = cpu->interrupt_request;

                if (unlikely(interrupt_request)) {

                    if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {

                        /* Mask out external interrupts for this step. */

                        interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;

                    }

                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;

                        cpu->exception_index = EXCP_DEBUG;

                        cpu_loop_exit(cpu);

                    }

#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \

    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \

    defined(TARGET_MICROBLAZE) || defined(TARGET_LM32) || defined(TARGET_UNICORE32)

                    if (interrupt_request & CPU_INTERRUPT_HALT) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;

                        cpu->halted = 1;

                        cpu->exception_index = EXCP_HLT;

                        cpu_loop_exit(cpu);

                    }

#endif

#if defined(TARGET_I386)

#if !defined(CONFIG_USER_ONLY)

                    if (interrupt_request & CPU_INTERRUPT_POLL) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;

                        apic_poll_irq(x86_cpu->apic_state);

                    }

#endif

                    if (interrupt_request & CPU_INTERRUPT_INIT) {

                            cpu_svm_check_intercept_param(env, SVM_EXIT_INIT,

                                                          0);

                            do_cpu_init(x86_cpu);

                            cpu->exception_index = EXCP_HALTED;

                            cpu_loop_exit(cpu);

                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {

                            do_cpu_sipi(x86_cpu);

                    } else if (env->hflags2 & HF2_GIF_MASK) {

                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&

                            !(env->hflags & HF_SMM_MASK)) {

                            cpu_svm_check_intercept_param(env, SVM_EXIT_SMI,

                                                          0);

                            cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;

                            do_smm_enter(x86_cpu);

                            next_tb = 0;

                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&

                                   !(env->hflags2 & HF2_NMI_MASK)) {

                            cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;

                            env->hflags2 |= HF2_NMI_MASK;

                            do_interrupt_x86_hardirq(env, EXCP02_NMI, 1);

                            next_tb = 0;

                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {

                            cpu->interrupt_request &= ~CPU_INTERRUPT_MCE;

                            do_interrupt_x86_hardirq(env, EXCP12_MCHK, 0);

                            next_tb = 0;

                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&

                                   (((env->hflags2 & HF2_VINTR_MASK) &&

                                     (env->hflags2 & HF2_HIF_MASK)) ||

                                    (!(env->hflags2 & HF2_VINTR_MASK) &&

                                     (env->eflags & IF_MASK &&

                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {

                            int intno;

                            cpu_svm_check_intercept_param(env, SVM_EXIT_INTR,

                                                          0);

                            cpu->interrupt_request &= ~(CPU_INTERRUPT_HARD |

                                                        CPU_INTERRUPT_VIRQ);

                            intno = cpu_get_pic_interrupt(env);

                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);

                            do_interrupt_x86_hardirq(env, intno, 1);

                            /* ensure that no TB jump will be modified as

                               the program flow was changed */

                            next_tb = 0;

#if !defined(CONFIG_USER_ONLY)

                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&

                                   (env->eflags & IF_MASK) &&

                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {

                            int intno;

                            /* FIXME: this should respect TPR */

                            cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR,

                                                          0);

                            intno = ldl_phys(cpu->as,

                                             env->vm_vmcb

                                             + offsetof(struct vmcb,

                                                        control.int_vector));

                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);

                            do_interrupt_x86_hardirq(env, intno, 1);

                            cpu->interrupt_request &= ~CPU_INTERRUPT_VIRQ;

                            next_tb = 0;

#endif

                        }

                    }

#elif defined(TARGET_PPC)

                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {

                        cpu_reset(cpu);

                    }

                    if (interrupt_request & CPU_INTERRUPT_HARD) {

                        ppc_hw_interrupt(env);

                        if (env->pending_interrupts == 0) {

                            cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;

                        }

                        next_tb = 0;

                    }

#elif defined(TARGET_LM32)

                    if ((interrupt_request & CPU_INTERRUPT_HARD)

                        && (env->ie & IE_IE)) {

                        cpu->exception_index = EXCP_IRQ;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_MICROBLAZE)

                    if ((interrupt_request & CPU_INTERRUPT_HARD)

                        && (env->sregs[SR_MSR] & MSR_IE)

                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))

                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {

                        cpu->exception_index = EXCP_IRQ;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_MIPS)

                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&

                        cpu_mips_hw_interrupts_pending(env)) {

                        /* Raise it */

                        cpu->exception_index = EXCP_EXT_INTERRUPT;

                        env->error_code = 0;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_OPENRISC)

                    {

                        int idx = -1;

                        if ((interrupt_request & CPU_INTERRUPT_HARD)

                            && (env->sr & SR_IEE)) {

                            idx = EXCP_INT;

                        }

                        if ((interrupt_request & CPU_INTERRUPT_TIMER)

                            && (env->sr & SR_TEE)) {

                            idx = EXCP_TICK;

                        }

                        if (idx >= 0) {

                            cpu->exception_index = idx;

                            cc->do_interrupt(cpu);

                            next_tb = 0;

                        }

                    }

#elif defined(TARGET_SPARC)

                    if (interrupt_request & CPU_INTERRUPT_HARD) {

                        if (cpu_interrupts_enabled(env) &&

                            env->interrupt_index > 0) {

                            int pil = env->interrupt_index & 0xf;

                            int type = env->interrupt_index & 0xf0;

                            if (((type == TT_EXTINT) &&

                                  cpu_pil_allowed(env, pil)) ||

                                  type != TT_EXTINT) {

                                cpu->exception_index = env->interrupt_index;

                                cc->do_interrupt(cpu);

                                next_tb = 0;

                            }

                        }

                    }

#elif defined(TARGET_ARM)

                    if (interrupt_request & CPU_INTERRUPT_FIQ

                        && !(env->daif & PSTATE_F)) {

                        cpu->exception_index = EXCP_FIQ;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

                    /* ARMv7-M interrupt return works by loading a magic value

                       into the PC.  On real hardware the load causes the

                       return to occur.  The qemu implementation performs the

                       jump normally, then does the exception return when the

                       CPU tries to execute code at the magic address.

                       This will cause the magic PC value to be pushed to

                       the stack if an interrupt occurred at the wrong time.

                       We avoid this by disabling interrupts when

                       pc contains a magic address.  */

                    if (interrupt_request & CPU_INTERRUPT_HARD

                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)

                            || !(env->daif & PSTATE_I))) {

                        cpu->exception_index = EXCP_IRQ;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_UNICORE32)

                    if (interrupt_request & CPU_INTERRUPT_HARD

                        && !(env->uncached_asr & ASR_I)) {

                        cpu->exception_index = UC32_EXCP_INTR;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_SH4)

                    if (interrupt_request & CPU_INTERRUPT_HARD) {

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_ALPHA)

                    {

                        int idx = -1;

                        /* ??? This hard-codes the OSF/1 interrupt levels.  */

                        switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {

                        case 0 ... 3:

                            if (interrupt_request & CPU_INTERRUPT_HARD) {

                                idx = EXCP_DEV_INTERRUPT;

                            }

                            /* FALLTHRU */

                        case 4:

                            if (interrupt_request & CPU_INTERRUPT_TIMER) {

                                idx = EXCP_CLK_INTERRUPT;

                            }

                            /* FALLTHRU */

                        case 5:

                            if (interrupt_request & CPU_INTERRUPT_SMP) {

                                idx = EXCP_SMP_INTERRUPT;

                            }

                            /* FALLTHRU */

                        case 6:

                            if (interrupt_request & CPU_INTERRUPT_MCHK) {

                                idx = EXCP_MCHK;

                            }

                        }

                        if (idx >= 0) {

                            cpu->exception_index = idx;

                            env->error_code = 0;

                            cc->do_interrupt(cpu);

                            next_tb = 0;

                        }

                    }

#elif defined(TARGET_CRIS)

                    if (interrupt_request & CPU_INTERRUPT_HARD

                        && (env->pregs[PR_CCS] & I_FLAG)

                        && !env->locked_irq) {

                        cpu->exception_index = EXCP_IRQ;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

                    if (interrupt_request & CPU_INTERRUPT_NMI) {

                        unsigned int m_flag_archval;

                        if (env->pregs[PR_VR] < 32) {

                            m_flag_archval = M_FLAG_V10;

                        } else {

                            m_flag_archval = M_FLAG_V32;

                        }

                        if ((env->pregs[PR_CCS] & m_flag_archval)) {

                            cpu->exception_index = EXCP_NMI;

                            cc->do_interrupt(cpu);

                            next_tb = 0;

                        }

                    }

#elif defined(TARGET_M68K)

                    if (interrupt_request & CPU_INTERRUPT_HARD

                        && ((env->sr & SR_I) >> SR_I_SHIFT)

                            < env->pending_level) {

                        /* Real hardware gets the interrupt vector via an

                           IACK cycle at this point.  Current emulated

                           hardware doesn't rely on this, so we

                           provide/save the vector when the interrupt is

                           first signalled.  */

                        cpu->exception_index = env->pending_vector;

                        do_interrupt_m68k_hardirq(env);

                        next_tb = 0;

                    }

#elif defined(TARGET_S390X) && !defined(CONFIG_USER_ONLY)

                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&

                        (env->psw.mask & PSW_MASK_EXT)) {

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#elif defined(TARGET_XTENSA)

                    if (interrupt_request & CPU_INTERRUPT_HARD) {

                        cpu->exception_index = EXC_IRQ;

                        cc->do_interrupt(cpu);

                        next_tb = 0;

                    }

#endif

                   /* Don't use the cached interrupt_request value,

                      do_interrupt may have updated the EXITTB flag. */

                    if (cpu->interrupt_request & CPU_INTERRUPT_EXITTB) {

                        cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;

                        /* ensure that no TB jump will be modified as

                           the program flow was changed */

                        next_tb = 0;

                    }

                }

                if (unlikely(cpu->exit_request)) {

                    cpu->exit_request = 0;

                    cpu->exception_index = EXCP_INTERRUPT;

                    cpu_loop_exit(cpu);

                }

                spin_lock(&tcg_ctx.tb_ctx.tb_lock);

                have_tb_lock = true;

                tb = tb_find_fast(env);

                /* Note: we do it here to avoid a gcc bug on Mac OS X when

                   doing it in tb_find_slow */

                if (tcg_ctx.tb_ctx.tb_invalidated_flag) {

                    /* as some TB could have been invalidated because

                       of memory exceptions while generating the code, we

                       must recompute the hash index here */

                    next_tb = 0;

                    tcg_ctx.tb_ctx.tb_invalidated_flag = 0;

                }

                if (qemu_loglevel_mask(CPU_LOG_EXEC)) {

                    qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",

                             tb->tc_ptr, tb->pc, lookup_symbol(tb->pc));

                }

                /* see if we can patch the calling TB. When the TB

                   spans two pages, we cannot safely do a direct

                   jump. */

                if (next_tb != 0 && tb->page_addr[1] == -1) {

                    tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),

                                next_tb & TB_EXIT_MASK, tb);

                }

                have_tb_lock = false;

                spin_unlock(&tcg_ctx.tb_ctx.tb_lock);

                /* cpu_interrupt might be called while translating the

                   TB, but before it is linked into a potentially

                   infinite loop and becomes env->current_tb. Avoid

                   starting execution if there is a pending interrupt. */

                cpu->current_tb = tb;

                barrier();

                if (likely(!cpu->exit_request)) {

                    tc_ptr = tb->tc_ptr;

                    /* execute the generated code */

                    next_tb = cpu_tb_exec(cpu, tc_ptr);

                    switch (next_tb & TB_EXIT_MASK) {

                    case TB_EXIT_REQUESTED:

                        /* Something asked us to stop executing

                         * chained TBs; just continue round the main

                         * loop. Whatever requested the exit will also

                         * have set something else (eg exit_request or

                         * interrupt_request) which we will handle

                         * next time around the loop.

                         */

                        tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);

                        next_tb = 0;

                        break;

                    case TB_EXIT_ICOUNT_EXPIRED:

                    {

                        /* Instruction counter expired.  */

                        int insns_left;

                        tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK);

                        insns_left = cpu->icount_decr.u32;

                        if (cpu->icount_extra && insns_left >= 0) {

                            /* Refill decrementer and continue execution.  */

                            cpu->icount_extra += insns_left;

                            if (cpu->icount_extra > 0xffff) {

                                insns_left = 0xffff;

                            } else {

                                insns_left = cpu->icount_extra;

                            }

                            cpu->icount_extra -= insns_left;

                            cpu->icount_decr.u16.low = insns_left;

                        } else {

                            if (insns_left > 0) {

                                /* Execute remaining instructions.  */

                                cpu_exec_nocache(env, insns_left, tb);

                            }

                            cpu->exception_index = EXCP_INTERRUPT;

                            next_tb = 0;

                            cpu_loop_exit(cpu);

                        }

                        break;

                    }

                    default:

                        break;

                    }

                }

                cpu->current_tb = NULL;

                /* reset soft MMU for next block (it can currently

                   only be set by a memory fault) */

            } /* for(;;) */

        } else {

            /* Reload env after longjmp - the compiler may have smashed all

             * local variables as longjmp is marked 'noreturn'. */

            cpu = current_cpu;

            env = cpu->env_ptr;

#if !(defined(CONFIG_USER_ONLY) && \

      (defined(TARGET_M68K) || defined(TARGET_PPC) || defined(TARGET_S390X)))

            cc = CPU_GET_CLASS(cpu);

#endif

#ifdef TARGET_I386

            x86_cpu = X86_CPU(cpu);

#endif

            if (have_tb_lock) {

                spin_unlock(&tcg_ctx.tb_ctx.tb_lock);

                have_tb_lock = false;

            }

        }

    } /* for(;;) */

#if defined(TARGET_I386)

    /* restore flags in standard format */

    env->eflags = env->eflags | cpu_cc_compute_all(env, CC_OP)

        | (env->df & DF_MASK);

#elif defined(TARGET_ARM)

    /* XXX: Save/restore host fpu exception state?.  */

#elif defined(TARGET_UNICORE32)

#elif defined(TARGET_SPARC)

#elif defined(TARGET_PPC)

#elif defined(TARGET_LM32)

#elif defined(TARGET_M68K)

    cpu_m68k_flush_flags(env, env->cc_op);

    env->cc_op = CC_OP_FLAGS;

    env->sr = (env->sr & 0xffe0)

              | env->cc_dest | (env->cc_x << 4);

#elif defined(TARGET_MICROBLAZE)

#elif defined(TARGET_MIPS)

#elif defined(TARGET_MOXIE)

#elif defined(TARGET_OPENRISC)

#elif defined(TARGET_SH4)

#elif defined(TARGET_ALPHA)

#elif defined(TARGET_CRIS)

#elif defined(TARGET_S390X)

#elif defined(TARGET_XTENSA)

    /* XXXXX */

#else

#error unsupported target CPU

#endif

    /* fail safe : never use current_cpu outside cpu_exec() */

    current_cpu = NULL;

    return ret;

}


static int bdrv_can_snapshot(BlockDriverState *bs)

{

    return (bs &&

            !bdrv_is_removable(bs) &&

            !bdrv_is_read_only(bs));

}


int hw_device_init_from_string(const char *arg, HWDevice **dev_out)

{

    // "type=name:device,key=value,key2=value2"

    // "type:device,key=value,key2=value2"

    // -> av_hwdevice_ctx_create()

    // "type=name@name"

    // "type@name"

    // -> av_hwdevice_ctx_create_derived()

    AVDictionary *options = NULL;

    char *type_name = NULL, *name = NULL, *device = NULL;

    enum AVHWDeviceType type;

    HWDevice *dev, *src;

    AVBufferRef *device_ref = NULL;

    int err;

    const char *errmsg, *p, *q;

    size_t k;

    k = strcspn(arg, ":=@");

    p = arg + k;

    type_name = av_strndup(arg, k);

    if (!type_name) {

        err = AVERROR(ENOMEM);

        goto fail;

    }

    type = av_hwdevice_find_type_by_name(type_name);

    if (type == AV_HWDEVICE_TYPE_NONE) {

        errmsg = "unknown device type";

        goto invalid;

    }

    if (*p == '=') {

        k = strcspn(p + 1, ":@");

        name = av_strndup(p + 1, k);

        if (!name) {

            err = AVERROR(ENOMEM);

            goto fail;

        }

        if (hw_device_get_by_name(name)) {

            errmsg = "named device already exists";

            goto invalid;

        }

        p += 1 + k;

    } else {

        // Give the device an automatic name of the form "type%d".

        // We arbitrarily limit at 1000 anonymous devices of the same

        // type - there is probably something else very wrong if you

        // get to this limit.

        size_t index_pos;

        int index, index_limit = 1000;

        index_pos = strlen(type_name);

        name = av_malloc(index_pos + 4);

        if (!name) {

            err = AVERROR(ENOMEM);

            goto fail;

        }

        for (index = 0; index < index_limit; index++) {

            snprintf(name, index_pos + 4, "%s%d", type_name, index);

            if (!hw_device_get_by_name(name))

                break;

        }

        if (index >= index_limit) {

            errmsg = "too many devices";

            goto invalid;

        }

    }

    if (!*p) {

        // New device with no parameters.

        err = av_hwdevice_ctx_create(&device_ref, type,

                                     NULL, NULL, 0);

        if (err < 0)

            goto fail;

    } else if (*p == ':') {

        // New device with some parameters.

        ++p;

        q = strchr(p, ',');

        if (q) {

            device = av_strndup(p, q - p);

            if (!device) {

                err = AVERROR(ENOMEM);

                goto fail;

            }

            err = av_dict_parse_string(&options, q + 1, "=", ",", 0);

            if (err < 0) {

                errmsg = "failed to parse options";

                goto invalid;

            }

        }

        err = av_hwdevice_ctx_create(&device_ref, type,

                                     device ? device : p, options, 0);

        if (err < 0)

            goto fail;

    } else if (*p == '@') {

        // Derive from existing device.

        src = hw_device_get_by_name(p + 1);

        if (!src) {

            errmsg = "invalid source device name";

            goto invalid;

        }

        err = av_hwdevice_ctx_create_derived(&device_ref, type,

                                             src->device_ref, 0);

        if (err < 0)

            goto fail;

    } else {

        errmsg = "parse error";

        goto invalid;

    }

    dev = hw_device_add();

    if (!dev) {

        err = AVERROR(ENOMEM);

        goto fail;

    }

    dev->name = name;

    dev->type = type;

    dev->device_ref = device_ref;

    if (dev_out)

        *dev_out = dev;

    name = NULL;

    err = 0;

done:

    av_freep(&type_name);

    av_freep(&name);

    av_freep(&device);

    av_dict_free(&options);

    return err;

invalid:

    av_log(NULL, AV_LOG_ERROR,

           "Invalid device specification \"%s\": %s\n", arg, errmsg);

    err = AVERROR(EINVAL);

    goto done;

fail:

    av_log(NULL, AV_LOG_ERROR,

           "Device creation failed: %d.\n", err);

    av_buffer_unref(&device_ref);

    goto done;

}


static void vaapi_encode_h264_write_pps(PutBitContext *pbc,

                                        VAAPIEncodeContext *ctx)

{

    VAEncPictureParameterBufferH264   *vpic = ctx->codec_picture_params;

    VAAPIEncodeH264Context            *priv = ctx->priv_data;

    VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;

    vaapi_encode_h264_write_nal_header(pbc, NAL_PPS, 3);

    ue(vpic_var(pic_parameter_set_id));

    ue(vpic_var(seq_parameter_set_id));

    u(1, vpic_field(entropy_coding_mode_flag));

    u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag));

    ue(mseq_var(num_slice_groups_minus1));

    if (mseq->num_slice_groups_minus1 > 0) {

        ue(mseq_var(slice_group_map_type));

        av_assert0(0 && "slice groups not supported");

    }

    ue(vpic_var(num_ref_idx_l0_active_minus1));

    ue(vpic_var(num_ref_idx_l1_active_minus1));

    u(1, vpic_field(weighted_pred_flag));

    u(2, vpic_field(weighted_bipred_idc));

    se(vpic->pic_init_qp - 26, pic_init_qp_minus26);

    se(mseq_var(pic_init_qs_minus26));

    se(vpic_var(chroma_qp_index_offset));

    u(1, vpic_field(deblocking_filter_control_present_flag));

    u(1, vpic_field(constrained_intra_pred_flag));

    u(1, vpic_field(redundant_pic_cnt_present_flag));

    u(1, vpic_field(transform_8x8_mode_flag));

    u(1, vpic_field(pic_scaling_matrix_present_flag));

    if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) {

        av_assert0(0 && "scaling matrices not supported");

    }

    se(vpic_var(second_chroma_qp_index_offset));

    vaapi_encode_h264_write_trailing_rbsp(pbc);

}


static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int rc_rice_param)

{

    int prefix = 0;

    int suffix = 0;

    int last_coeff_abs_level_remaining;

    int i;

    while (prefix < CABAC_MAX_BIN && get_cabac_bypass(&s->HEVClc->cc))

        prefix++;

    if (prefix == CABAC_MAX_BIN) {

        av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix);

        return 0;

    }

    if (prefix < 3) {

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

            suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc);

        last_coeff_abs_level_remaining = (prefix << rc_rice_param) + suffix;

    } else {

        int prefix_minus3 = prefix - 3;

        for (i = 0; i < prefix_minus3 + rc_rice_param; i++)

            suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc);

        last_coeff_abs_level_remaining = (((1 << prefix_minus3) + 3 - 1)

                                              << rc_rice_param) + suffix;

    }

    return last_coeff_abs_level_remaining;

}


static void float_number(void)

{

    int i;

    struct {

        const char *encoded;

        double decoded;

        int skip;

    } test_cases[] = {

        { "32.43", 32.43 },

        { "0.222", 0.222 },

        { "-32.12313", -32.12313 },

        { "-32.20e-10", -32.20e-10, .skip = 1 },

        { },

    };

    for (i = 0; test_cases[i].encoded; i++) {

        QObject *obj;

        QFloat *qfloat;

        obj = qobject_from_json(test_cases[i].encoded, NULL);

        qfloat = qobject_to_qfloat(obj);

        g_assert(qfloat);

        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);

        if (test_cases[i].skip == 0) {

            QString *str;

            str = qobject_to_json(obj);

            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);

            QDECREF(str);

        }

        QDECREF(qfloat);

    }

}


AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)

{

    int i;

    if(!name)

        return NULL;

    for(i = 0; i < graph->filter_count; i ++)

        if(graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))

            return graph->filters[i];

    return NULL;

}


static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,

                          int nb_sectors)

{

    BlockBackend *source = s->common.blk;

    int sectors_per_chunk, nb_chunks;

    int ret = nb_sectors;

    MirrorOp *op;

    sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;

    /* We can only handle as much as buf_size at a time. */

    nb_sectors = MIN(s->buf_size >> BDRV_SECTOR_BITS, nb_sectors);

    assert(nb_sectors);

    if (s->cow_bitmap) {

        ret += mirror_cow_align(s, &sector_num, &nb_sectors);

    }

    assert(nb_sectors << BDRV_SECTOR_BITS <= s->buf_size);

    /* The sector range must meet granularity because:

     * 1) Caller passes in aligned values;

     * 2) mirror_cow_align is used only when target cluster is larger. */

    assert(!(sector_num % sectors_per_chunk));

    nb_chunks = DIV_ROUND_UP(nb_sectors, sectors_per_chunk);

    while (s->buf_free_count < nb_chunks) {

        trace_mirror_yield_in_flight(s, sector_num, s->in_flight);

        mirror_wait_for_io(s);

    }

    /* Allocate a MirrorOp that is used as an AIO callback.  */

    op = g_new(MirrorOp, 1);

    op->s = s;

    op->sector_num = sector_num;

    op->nb_sectors = nb_sectors;

    /* Now make a QEMUIOVector taking enough granularity-sized chunks

     * from s->buf_free.

     */

    qemu_iovec_init(&op->qiov, nb_chunks);

    while (nb_chunks-- > 0) {

        MirrorBuffer *buf = QSIMPLEQ_FIRST(&s->buf_free);

        size_t remaining = nb_sectors * BDRV_SECTOR_SIZE - op->qiov.size;

        QSIMPLEQ_REMOVE_HEAD(&s->buf_free, next);

        s->buf_free_count--;

        qemu_iovec_add(&op->qiov, buf, MIN(s->granularity, remaining));

    }

    /* Copy the dirty cluster.  */

    s->in_flight++;

    s->sectors_in_flight += nb_sectors;

    trace_mirror_one_iteration(s, sector_num, nb_sectors);

    blk_aio_preadv(source, sector_num * BDRV_SECTOR_SIZE, &op->qiov,

                   nb_sectors * BDRV_SECTOR_SIZE,

                   mirror_read_complete, op);

    return ret;

}


static void pred_temp_direct_motion(H264Context * const h, int *mb_type){

    MpegEncContext * const s = &h->s;

    int b8_stride = 2;

    int b4_stride = h->b_stride;

    int mb_xy = h->mb_xy, mb_y = s->mb_y;

    int mb_type_col[2];

    const int16_t (*l1mv0)[2], (*l1mv1)[2];

    const int8_t *l1ref0, *l1ref1;

    const int is_b8x8 = IS_8X8(*mb_type);

    unsigned int sub_mb_type;

    int i8, i4;

    assert(h->ref_list[1][0].f.reference & 3);

    await_reference_mb_row(h, &h->ref_list[1][0], s->mb_y + !!IS_INTERLACED(*mb_type));

    if (IS_INTERLACED(h->ref_list[1][0].f.mb_type[mb_xy])) { // AFL/AFR/FR/FL -> AFL/FL

        if (!IS_INTERLACED(*mb_type)) {                          //     AFR/FR    -> AFL/FL

            mb_y = (s->mb_y&~1) + h->col_parity;

            mb_xy= s->mb_x + ((s->mb_y&~1) + h->col_parity)*s->mb_stride;

            b8_stride = 0;

        }else{

            mb_y  += h->col_fieldoff;

            mb_xy += s->mb_stride*h->col_fieldoff; // non zero for FL -> FL & differ parity

        goto single_col;

    }else{                                               // AFL/AFR/FR/FL -> AFR/FR

        if(IS_INTERLACED(*mb_type)){                     // AFL       /FL -> AFR/FR

            mb_y = s->mb_y&~1;

            mb_xy= s->mb_x + (s->mb_y&~1)*s->mb_stride;

            mb_type_col[0] = h->ref_list[1][0].f.mb_type[mb_xy];

            mb_type_col[1] = h->ref_list[1][0].f.mb_type[mb_xy + s->mb_stride];

            b8_stride = 2+4*s->mb_stride;

            b4_stride *= 6;

            sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */

            if(    (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)

                && (mb_type_col[1] & MB_TYPE_16x16_OR_INTRA)

                && !is_b8x8){

                *mb_type   |= MB_TYPE_16x8 |MB_TYPE_L0L1|MB_TYPE_DIRECT2; /* B_16x8 */

            }else{

                *mb_type   |= MB_TYPE_8x8|MB_TYPE_L0L1;

        }else{                                           //     AFR/FR    -> AFR/FR

single_col:

            mb_type_col[0] =

            mb_type_col[1] = h->ref_list[1][0].f.mb_type[mb_xy];

            sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */

            if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){

                *mb_type   |= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */

            }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){

                *mb_type   |= MB_TYPE_L0L1|MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));

            }else{

                if(!h->sps.direct_8x8_inference_flag){

                    /* FIXME save sub mb types from previous frames (or derive from MVs)

                    * so we know exactly what block size to use */

                    sub_mb_type = MB_TYPE_8x8|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_4x4 */

                *mb_type   |= MB_TYPE_8x8|MB_TYPE_L0L1;

    await_reference_mb_row(h, &h->ref_list[1][0], mb_y);

    l1mv0  = &h->ref_list[1][0].f.motion_val[0][h->mb2b_xy [mb_xy]];

    l1mv1  = &h->ref_list[1][0].f.motion_val[1][h->mb2b_xy [mb_xy]];

    l1ref0 = &h->ref_list[1][0].f.ref_index [0][4 * mb_xy];

    l1ref1 = &h->ref_list[1][0].f.ref_index [1][4 * mb_xy];

    if(!b8_stride){

        if(s->mb_y&1){

            l1ref0 += 2;

            l1ref1 += 2;

            l1mv0  +=  2*b4_stride;

            l1mv1  +=  2*b4_stride;

    {

        const int *map_col_to_list0[2] = {h->map_col_to_list0[0], h->map_col_to_list0[1]};

        const int *dist_scale_factor = h->dist_scale_factor;

        int ref_offset;

        if(FRAME_MBAFF && IS_INTERLACED(*mb_type)){

            map_col_to_list0[0] = h->map_col_to_list0_field[s->mb_y&1][0];

            map_col_to_list0[1] = h->map_col_to_list0_field[s->mb_y&1][1];

            dist_scale_factor   =h->dist_scale_factor_field[s->mb_y&1];

        ref_offset = (h->ref_list[1][0].mbaff<<4) & (mb_type_col[0]>>3); //if(h->ref_list[1][0].mbaff && IS_INTERLACED(mb_type_col[0])) ref_offset=16 else 0

        if(IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])){

            int y_shift  = 2*!IS_INTERLACED(*mb_type);

            assert(h->sps.direct_8x8_inference_flag);

            for(i8=0; i8<4; i8++){

                const int x8 = i8&1;

                const int y8 = i8>>1;

                int ref0, scale;

                const int16_t (*l1mv)[2]= l1mv0;

                if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))

                    continue;

                h->sub_mb_type[i8] = sub_mb_type;

                fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1);

                if(IS_INTRA(mb_type_col[y8])){

                    fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1);

                    fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);

                    fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);

                    continue;

                ref0 = l1ref0[x8 + y8*b8_stride];

                if(ref0 >= 0)

                    ref0 = map_col_to_list0[0][ref0 + ref_offset];

                else{

                    ref0 = map_col_to_list0[1][l1ref1[x8 + y8*b8_stride] + ref_offset];

                    l1mv= l1mv1;

                scale = dist_scale_factor[ref0];

                fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1);

                {

                    const int16_t *mv_col = l1mv[x8*3 + y8*b4_stride];

                    int my_col = (mv_col[1]<<y_shift)/2;

                    int mx = (scale * mv_col[0] + 128) >> 8;

                    int my = (scale * my_col + 128) >> 8;

                    fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4);

                    fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-my_col), 4);

            return;

        /* one-to-one mv scaling */

        if(IS_16X16(*mb_type)){

            int ref, mv0, mv1;

            fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1);

            if(IS_INTRA(mb_type_col[0])){

                ref=mv0=mv1=0;

            }else{

                const int ref0 = l1ref0[0] >= 0 ? map_col_to_list0[0][l1ref0[0] + ref_offset]

                                                : map_col_to_list0[1][l1ref1[0] + ref_offset];

                const int scale = dist_scale_factor[ref0];

                const int16_t *mv_col = l1ref0[0] >= 0 ? l1mv0[0] : l1mv1[0];

                int mv_l0[2];

                mv_l0[0] = (scale * mv_col[0] + 128) >> 8;

                mv_l0[1] = (scale * mv_col[1] + 128) >> 8;

                ref= ref0;

                mv0= pack16to32(mv_l0[0],mv_l0[1]);

                mv1= pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]);

            fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);

            fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4);

            fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4);

        }else{

            for(i8=0; i8<4; i8++){

                const int x8 = i8&1;

                const int y8 = i8>>1;

                int ref0, scale;

                const int16_t (*l1mv)[2]= l1mv0;

                if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))

                    continue;

                h->sub_mb_type[i8] = sub_mb_type;

                fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1);

                if(IS_INTRA(mb_type_col[0])){

                    fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1);

                    fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);

                    fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);

                    continue;

                assert(b8_stride == 2);

                ref0 = l1ref0[i8];

                if(ref0 >= 0)

                    ref0 = map_col_to_list0[0][ref0 + ref_offset];

                else{

                    ref0 = map_col_to_list0[1][l1ref1[i8] + ref_offset];

                    l1mv= l1mv1;

                scale = dist_scale_factor[ref0];

                fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1);

                if(IS_SUB_8X8(sub_mb_type)){

                    const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride];

                    int mx = (scale * mv_col[0] + 128) >> 8;

                    int my = (scale * mv_col[1] + 128) >> 8;

                    fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4);

                    fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-mv_col[1]), 4);

                }else

                for(i4=0; i4<4; i4++){

                    const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride];

                    int16_t *mv_l0 = h->mv_cache[0][scan8[i8*4+i4]];

                    mv_l0[0] = (scale * mv_col[0] + 128) >> 8;

                    mv_l0[1] = (scale * mv_col[1] + 128) >> 8;

                    AV_WN32A(h->mv_cache[1][scan8[i8*4+i4]],

                        pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]));


static inline int cris_abs(int n)

{

	int r;

	asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));

	return r;

}


static int bmdma_prepare_buf(IDEDMA *dma, int is_write)

{

    BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);

    IDEState *s = bmdma_active_if(bm);

    PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev);

    struct {

        uint32_t addr;

        uint32_t size;

    } prd;

    int l, len;

    pci_dma_sglist_init(&s->sg, pci_dev,

                        s->nsector / (BMDMA_PAGE_SIZE / 512) + 1);

    s->io_buffer_size = 0;

    for(;;) {

        if (bm->cur_prd_len == 0) {

            /* end of table (with a fail safe of one page) */

            if (bm->cur_prd_last ||

                (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)

                return s->io_buffer_size != 0;

            pci_dma_read(pci_dev, bm->cur_addr, &prd, 8);

            bm->cur_addr += 8;

            prd.addr = le32_to_cpu(prd.addr);

            prd.size = le32_to_cpu(prd.size);

            len = prd.size & 0xfffe;

            if (len == 0)

                len = 0x10000;

            bm->cur_prd_len = len;

            bm->cur_prd_addr = prd.addr;

            bm->cur_prd_last = (prd.size & 0x80000000);

        }

        l = bm->cur_prd_len;

        if (l > 0) {

            qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);

            bm->cur_prd_addr += l;

            bm->cur_prd_len -= l;

            s->io_buffer_size += l;

        }

    }

    return 1;

}


av_cold int ff_mss12_decode_init(MSS12Context *c, int version,

                                 SliceContext* sc1, SliceContext *sc2)

{

    AVCodecContext *avctx = c->avctx;

    int i;

    if (avctx->extradata_size < 52 + 256 * 3) {

        av_log(avctx, AV_LOG_ERROR, "Insufficient extradata size %d\n",

               avctx->extradata_size);

    if (AV_RB32(avctx->extradata) < avctx->extradata_size) {

        av_log(avctx, AV_LOG_ERROR,

               "Insufficient extradata size: expected %d got %d\n",

               AV_RB32(avctx->extradata),

               avctx->extradata_size);

    avctx->coded_width  = AV_RB32(avctx->extradata + 20);

    avctx->coded_height = AV_RB32(avctx->extradata + 24);

    if (avctx->coded_width > 4096 || avctx->coded_height > 4096) {

        av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too large",

    av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n",

           AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8));

    if (version != AV_RB32(avctx->extradata + 4) > 1) {

        av_log(avctx, AV_LOG_ERROR,

               "Header version doesn't match codec tag\n");

        return -1;

    c->free_colours = AV_RB32(avctx->extradata + 48);

    if ((unsigned)c->free_colours > 256) {

        av_log(avctx, AV_LOG_ERROR,

               "Incorrect number of changeable palette entries: %d\n",

               c->free_colours);

    av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours);

    av_log(avctx, AV_LOG_DEBUG, "Display dimensions %dx%d\n",

           AV_RB32(avctx->extradata + 12), AV_RB32(avctx->extradata + 16));

    av_log(avctx, AV_LOG_DEBUG, "Coded dimensions %dx%d\n",

    av_log(avctx, AV_LOG_DEBUG, "%g frames per second\n",

           av_int2float(AV_RB32(avctx->extradata + 28)));

    av_log(avctx, AV_LOG_DEBUG, "Bitrate %d bps\n",

           AV_RB32(avctx->extradata + 32));

    av_log(avctx, AV_LOG_DEBUG, "Max. lead time %g ms\n",

           av_int2float(AV_RB32(avctx->extradata + 36)));

    av_log(avctx, AV_LOG_DEBUG, "Max. lag time %g ms\n",

           av_int2float(AV_RB32(avctx->extradata + 40)));

    av_log(avctx, AV_LOG_DEBUG, "Max. seek time %g ms\n",

           av_int2float(AV_RB32(avctx->extradata + 44)));

    if (version) {

        if (avctx->extradata_size < 60 + 256 * 3) {

            av_log(avctx, AV_LOG_ERROR,

                   "Insufficient extradata size %d for v2\n",

                   avctx->extradata_size);

        c->slice_split = AV_RB32(avctx->extradata + 52);

        av_log(avctx, AV_LOG_DEBUG, "Slice split %d\n", c->slice_split);

        c->full_model_syms = AV_RB32(avctx->extradata + 56);

        if (c->full_model_syms < 2 || c->full_model_syms > 256) {

            av_log(avctx, AV_LOG_ERROR,

                   "Incorrect number of used colours %d\n",

                   c->full_model_syms);

        av_log(avctx, AV_LOG_DEBUG, "Used colours %d\n",

               c->full_model_syms);

    } else {

        c->slice_split     = 0;

        c->full_model_syms = 256;

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

        c->pal[i] = 0xFFU << 24 | AV_RB24(avctx->extradata + 52 +

                            (version ? 8 : 0) + i * 3);

    c->mask_stride = FFALIGN(avctx->width, 16);

    c->mask        = av_malloc(c->mask_stride * avctx->height);

    if (!c->mask) {

        av_log(avctx, AV_LOG_ERROR, "Cannot allocate mask plane\n");

        return AVERROR(ENOMEM);

    sc1->c = c;

    slicecontext_init(sc1, version, c->full_model_syms);

    if (c->slice_split) {

        sc2->c = c;

        slicecontext_init(sc2, version, c->full_model_syms);

    c->corrupted = 1;

    return 0;


static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code)

{

    AVFormatContext *s = nut->avf;

    AVIOContext *bc    = s->pb;

    int size, stream_id, discard;

    int64_t pts, last_IP_pts;

    StreamContext *stc;

    uint8_t header_idx;

    size = decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code);

    if (size < 0)

        return size;

    stc = &nut->stream[stream_id];

    if (stc->last_flags & FLAG_KEY)

        stc->skip_until_key_frame = 0;

    discard     = s->streams[stream_id]->discard;

    last_IP_pts = s->streams[stream_id]->last_IP_pts;

    if ((discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY)) ||

        (discard >= AVDISCARD_BIDIR  && last_IP_pts != AV_NOPTS_VALUE &&

         last_IP_pts > pts) ||

        discard >= AVDISCARD_ALL ||

        stc->skip_until_key_frame) {

        avio_skip(bc, size);

        return 1;

    }

    if (av_new_packet(pkt, size + nut->header_len[header_idx]) < 0)

        return AVERROR(ENOMEM);

    memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]);

    pkt->pos = avio_tell(bc); // FIXME

    if (stc->last_flags & FLAG_SM_DATA) {

        int sm_size;

        if (read_sm_data(s, bc, pkt, 0, pkt->pos + size) < 0)

            return AVERROR_INVALIDDATA;

        if (read_sm_data(s, bc, pkt, 1, pkt->pos + size) < 0)

            return AVERROR_INVALIDDATA;

        sm_size = avio_tell(bc) - pkt->pos;

        size      -= sm_size;

        pkt->size -= sm_size;

    }

    avio_read(bc, pkt->data + nut->header_len[header_idx], size);

    pkt->stream_index = stream_id;

    if (stc->last_flags & FLAG_KEY)

        pkt->flags |= AV_PKT_FLAG_KEY;

    pkt->pts = pts;

    return 0;

}


static int rm_assemble_video_frame(AVFormatContext *s, ByteIOContext *pb,

                                   RMDemuxContext *rm, RMStream *vst,

                                   AVPacket *pkt, int len, int *pseq)

{

    int hdr, seq, pic_num, len2, pos;

    int type;

    hdr = get_byte(pb); len--;

    type = hdr >> 6;

    if(type != 3){  // not frame as a part of packet

        seq = get_byte(pb); len--;

    }

    if(type != 1){  // not whole frame

        len2 = get_num(pb, &len);

        pos  = get_num(pb, &len);

        pic_num = get_byte(pb); len--;

    }

    if(len<0)

        return -1;

    rm->remaining_len = len;

    if(type&1){     // frame, not slice

        if(type == 3)  // frame as a part of packet

            len= len2;

        if(rm->remaining_len < len)

            return -1;

        rm->remaining_len -= len;

        if(av_new_packet(pkt, len + 9) < 0)

            return AVERROR(EIO);

        pkt->data[0] = 0;

        AV_WL32(pkt->data + 1, 1);

        AV_WL32(pkt->data + 5, 0);

        get_buffer(pb, pkt->data + 9, len);

        return 0;

    }

    //now we have to deal with single slice

    *pseq = seq;

    if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){

        vst->slices = ((hdr & 0x3F) << 1) + 1;

        vst->videobufsize = len2 + 8*vst->slices + 1;

        av_free_packet(&vst->pkt); //FIXME this should be output.

        if(av_new_packet(&vst->pkt, vst->videobufsize) < 0)

            return AVERROR(ENOMEM);

        vst->videobufpos = 8*vst->slices + 1;

        vst->cur_slice = 0;

        vst->curpic_num = pic_num;

        vst->pktpos = url_ftell(pb);

    }

    if(type == 2)

        len = FFMIN(len, pos);

    if(++vst->cur_slice > vst->slices)

        return 1;

    AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1);

    AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1);

    if(vst->videobufpos + len > vst->videobufsize)

        return 1;

    if (get_buffer(pb, vst->pkt.data + vst->videobufpos, len) != len)

        return AVERROR(EIO);

    vst->videobufpos += len;

    rm->remaining_len-= len;

    if(type == 2 || (vst->videobufpos) == vst->videobufsize){

        vst->pkt.data[0] = vst->cur_slice-1;

        *pkt= vst->pkt;

        vst->pkt.data= NULL;

        vst->pkt.size= 0;

        if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin

            memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,

                vst->videobufpos - 1 - 8*vst->slices);

        pkt->size = vst->videobufpos + 8*(vst->cur_slice - vst->slices);

        pkt->pts = AV_NOPTS_VALUE;

        pkt->pos = vst->pktpos;

        return 0;

    }

    return 1;

}


static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)

{

    VideoPicture *vp;

    double frame_delay, pts = pts1;

    /* compute the exact PTS for the picture if it is omitted in the stream

     * pts1 is the dts of the pkt / pts of the frame */

    if (pts != 0) {

        /* update video clock with pts, if present */

        is->video_clock = pts;

    } else {

        pts = is->video_clock;

    /* update video clock for next frame */

    frame_delay = av_q2d(is->video_st->codec->time_base);

    /* for MPEG2, the frame can be repeated, so we update the

       clock accordingly */

    frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);

    is->video_clock += frame_delay;

#if defined(DEBUG_SYNC) && 0

    printf("frame_type=%c clock=%0.3f pts=%0.3f\n",

           av_get_picture_type_char(src_frame->pict_type), pts, pts1);

#endif

    /* wait until we have space to put a new picture */

    SDL_LockMutex(is->pictq_mutex);

    if(is->pictq_size>=VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)

        is->skip_frames= FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0-FRAME_SKIP_FACTOR));

    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&

           !is->videoq.abort_request) {

    SDL_UnlockMutex(is->pictq_mutex);

    if (is->videoq.abort_request)

        return -1;

    vp = &is->pictq[is->pictq_windex];

    vp->duration = frame_delay;

    /* alloc or resize hardware picture buffer */

    if (!vp->bmp ||

#if CONFIG_AVFILTER

        vp->width  != is->out_video_filter->inputs[0]->w ||

        vp->height != is->out_video_filter->inputs[0]->h) {

#else

        vp->width != is->video_st->codec->width ||

        vp->height != is->video_st->codec->height) {

#endif

        SDL_Event event;

        vp->allocated = 0;

        /* the allocation must be done in the main thread to avoid

           locking problems */

        event.type = FF_ALLOC_EVENT;

        event.user.data1 = is;

        SDL_PushEvent(&event);

        /* wait until the picture is allocated */

        SDL_LockMutex(is->pictq_mutex);

        while (!vp->allocated && !is->videoq.abort_request) {

        SDL_UnlockMutex(is->pictq_mutex);

        if (is->videoq.abort_request)

            return -1;

    /* if the frame is not skipped, then display it */

    if (vp->bmp) {

        AVPicture pict;

#if CONFIG_AVFILTER

        if(vp->picref)

            avfilter_unref_buffer(vp->picref);

        vp->picref = src_frame->opaque;

#endif

        /* get a pointer on the bitmap */

        SDL_LockYUVOverlay (vp->bmp);

        memset(&pict,0,sizeof(AVPicture));

        pict.data[0] = vp->bmp->pixels[0];

        pict.data[1] = vp->bmp->pixels[2];

        pict.data[2] = vp->bmp->pixels[1];

        pict.linesize[0] = vp->bmp->pitches[0];

        pict.linesize[1] = vp->bmp->pitches[2];

        pict.linesize[2] = vp->bmp->pitches[1];

#if CONFIG_AVFILTER

        //FIXME use direct rendering

        av_picture_copy(&pict, (AVPicture *)src_frame,

                        vp->pix_fmt, vp->width, vp->height);

#else

        sws_flags = av_get_int(sws_opts, "sws_flags", NULL);

        is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,

            vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,

            PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);

        if (is->img_convert_ctx == NULL) {

            fprintf(stderr, "Cannot initialize the conversion context\n");

            exit(1);

        sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,

                  0, vp->height, pict.data, pict.linesize);

#endif

        /* update the bitmap content */

        SDL_UnlockYUVOverlay(vp->bmp);

        vp->pts = pts;

        vp->pos = pos;

        /* now we can update the picture count */

        if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)

            is->pictq_windex = 0;

        SDL_LockMutex(is->pictq_mutex);

        vp->target_clock= compute_target_time(vp->pts, is);

        is->pictq_size++;

        SDL_UnlockMutex(is->pictq_mutex);

    return 0;