static void *spapr_create_fdt_skel(hwaddr initrd_base,

                                   hwaddr initrd_size,

                                   hwaddr kernel_size,

                                   bool little_endian,

                                   const char *kernel_cmdline,

                                   uint32_t epow_irq)

{

    void *fdt;

    uint32_t start_prop = cpu_to_be32(initrd_base);

    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);

    GString *hypertas = g_string_sized_new(256);

    GString *qemu_hypertas = g_string_sized_new(256);

    uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};

    uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};

    unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};

    char *buf;

    add_str(hypertas, "hcall-pft");

    add_str(hypertas, "hcall-term");

    add_str(hypertas, "hcall-dabr");

    add_str(hypertas, "hcall-interrupt");

    add_str(hypertas, "hcall-tce");

    add_str(hypertas, "hcall-vio");

    add_str(hypertas, "hcall-splpar");

    add_str(hypertas, "hcall-bulk");

    add_str(hypertas, "hcall-set-mode");

    add_str(qemu_hypertas, "hcall-memop1");

    fdt = g_malloc0(FDT_MAX_SIZE);

    _FDT((fdt_create(fdt, FDT_MAX_SIZE)));

    if (kernel_size) {

        _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));

    }

    if (initrd_size) {

        _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size)));

    }

    _FDT((fdt_finish_reservemap(fdt)));

    /* Root node */

    _FDT((fdt_begin_node(fdt, "")));

    _FDT((fdt_property_string(fdt, "device_type", "chrp")));

    _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));

    _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));

    /*

     * Add info to guest to indentify which host is it being run on

     * and what is the uuid of the guest

     */

    if (kvmppc_get_host_model(&buf)) {

        _FDT((fdt_property_string(fdt, "host-model", buf)));

        g_free(buf);

    }

    if (kvmppc_get_host_serial(&buf)) {

        _FDT((fdt_property_string(fdt, "host-serial", buf)));

        g_free(buf);

    }

    buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],

                          qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],

                          qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],

                          qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],

                          qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],

                          qemu_uuid[14], qemu_uuid[15]);

    _FDT((fdt_property_string(fdt, "vm,uuid", buf)));

    if (qemu_uuid_set) {

        _FDT((fdt_property_string(fdt, "system-id", buf)));

    }

    g_free(buf);

    if (qemu_get_vm_name()) {

        _FDT((fdt_property_string(fdt, "ibm,partition-name",

                                  qemu_get_vm_name())));

    }

    _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));

    _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));

    /* /chosen */

    _FDT((fdt_begin_node(fdt, "chosen")));

    /* Set Form1_affinity */

    _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));

    _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));

    _FDT((fdt_property(fdt, "linux,initrd-start",

                       &start_prop, sizeof(start_prop))));

    _FDT((fdt_property(fdt, "linux,initrd-end",

                       &end_prop, sizeof(end_prop))));

    if (kernel_size) {

        uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),

                              cpu_to_be64(kernel_size) };

        _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));

        if (little_endian) {

            _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));

        }

    }

    if (boot_menu) {

        _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));

    }

    _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));

    _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));

    _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));

    _FDT((fdt_end_node(fdt)));

    /* RTAS */

    _FDT((fdt_begin_node(fdt, "rtas")));

    if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {

        add_str(hypertas, "hcall-multi-tce");

    }

    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,

                       hypertas->len)));

    g_string_free(hypertas, TRUE);

    _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,

                       qemu_hypertas->len)));

    g_string_free(qemu_hypertas, TRUE);

    _FDT((fdt_property(fdt, "ibm,associativity-reference-points",

        refpoints, sizeof(refpoints))));

    _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));

    _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",

                            RTAS_EVENT_SCAN_RATE)));

    if (msi_nonbroken) {

        _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));

    }

    /*

     * According to PAPR, rtas ibm,os-term does not guarantee a return

     * back to the guest cpu.

     *

     * While an additional ibm,extended-os-term property indicates that

     * rtas call return will always occur. Set this property.

     */

    _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));

    _FDT((fdt_end_node(fdt)));

    /* interrupt controller */

    _FDT((fdt_begin_node(fdt, "interrupt-controller")));

    _FDT((fdt_property_string(fdt, "device_type",

                              "PowerPC-External-Interrupt-Presentation")));

    _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));

    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));

    _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",

                       interrupt_server_ranges_prop,

                       sizeof(interrupt_server_ranges_prop))));

    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));

    _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));

    _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));

    _FDT((fdt_end_node(fdt)));

    /* vdevice */

    _FDT((fdt_begin_node(fdt, "vdevice")));

    _FDT((fdt_property_string(fdt, "device_type", "vdevice")));

    _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));

    _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));

    _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));

    _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));

    _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));

    _FDT((fdt_end_node(fdt)));

    /* event-sources */

    spapr_events_fdt_skel(fdt, epow_irq);

    /* /hypervisor node */

    if (kvm_enabled()) {

        uint8_t hypercall[16];

        /* indicate KVM hypercall interface */

        _FDT((fdt_begin_node(fdt, "hypervisor")));

        _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));

        if (kvmppc_has_cap_fixup_hcalls()) {

            /*

             * Older KVM versions with older guest kernels were broken with the

             * magic page, don't allow the guest to map it.

             */

            kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,

                                 sizeof(hypercall));

            _FDT((fdt_property(fdt, "hcall-instructions", hypercall,

                              sizeof(hypercall))));

        }

        _FDT((fdt_end_node(fdt)));

    }

    _FDT((fdt_end_node(fdt))); /* close root node */

    _FDT((fdt_finish(fdt)));

    return fdt;

}


static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d,

                                             const struct rgbvec *s)

{

    const struct rgbvec d = {s->r - PREV(s->r), s->g - PREV(s->g), s->b - PREV(s->b)};

    const struct rgbvec c000 = lut3d->lut[PREV(s->r)][PREV(s->g)][PREV(s->b)];

    const struct rgbvec c001 = lut3d->lut[PREV(s->r)][PREV(s->g)][NEXT(s->b)];

    const struct rgbvec c010 = lut3d->lut[PREV(s->r)][NEXT(s->g)][PREV(s->b)];

    const struct rgbvec c011 = lut3d->lut[PREV(s->r)][NEXT(s->g)][NEXT(s->b)];

    const struct rgbvec c100 = lut3d->lut[NEXT(s->r)][PREV(s->g)][PREV(s->b)];

    const struct rgbvec c101 = lut3d->lut[NEXT(s->r)][PREV(s->g)][NEXT(s->b)];

    const struct rgbvec c110 = lut3d->lut[NEXT(s->r)][NEXT(s->g)][PREV(s->b)];

    const struct rgbvec c111 = lut3d->lut[NEXT(s->r)][NEXT(s->g)][NEXT(s->b)];

    const struct rgbvec c00  = lerp(&c000, &c100, d.r);

    const struct rgbvec c10  = lerp(&c010, &c110, d.r);

    const struct rgbvec c01  = lerp(&c001, &c101, d.r);

    const struct rgbvec c11  = lerp(&c011, &c111, d.r);

    const struct rgbvec c0   = lerp(&c00,  &c10,  d.g);

    const struct rgbvec c1   = lerp(&c01,  &c11,  d.g);

    const struct rgbvec c    = lerp(&c0,   &c1,   d.b);

    return c;

}


static void mux_chr_accept_input(CharDriverState *chr)

{

    int m = chr->focus;

    MuxDriver *d = chr->opaque;

    while (d->prod != d->cons &&

           d->chr_can_read[m] &&

           d->chr_can_read[m](d->ext_opaque[m])) {

        d->chr_read[m](d->ext_opaque[m],

                       &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);

    }

}


static int ogg_read_close(AVFormatContext *s)

{

    struct ogg *ogg = s->priv_data;

    int i;

    for (i = 0; i < ogg->nstreams; i++) {

        av_free(ogg->streams[i].buf);

        av_free(ogg->streams[i].private);

    }

    av_free(ogg->streams);

    return 0;

}


static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb)

{

    Vp3DecodeContext *s = avctx->priv_data;

    int i, n, matrices, inter, plane;

    if (s->theora >= 0x030200) {

        n = get_bits(gb, 3);

        /* loop filter limit values table */

        if (n) {

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

            s->filter_limit_values[i] = get_bits(gb, n);

            if (s->filter_limit_values[i] > 127) {

                av_log(avctx, AV_LOG_ERROR, "filter limit value too large (%i > 127), clamping\n", s->filter_limit_values[i]);

                s->filter_limit_values[i] = 127;

    if (s->theora >= 0x030200)

        n = get_bits(gb, 4) + 1;

    else

        n = 16;

    /* quality threshold table */

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

        s->coded_ac_scale_factor[i] = get_bits(gb, n);

    if (s->theora >= 0x030200)

        n = get_bits(gb, 4) + 1;

    else

        n = 16;

    /* dc scale factor table */

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

        s->coded_dc_scale_factor[i] = get_bits(gb, n);

    if (s->theora >= 0x030200)

        matrices = get_bits(gb, 9) + 1;

    else

        matrices = 3;

    if(matrices > 384){

        av_log(avctx, AV_LOG_ERROR, "invalid number of base matrixes\n");

        return -1;

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

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

            s->base_matrix[n][i]= get_bits(gb, 8);

    for (inter = 0; inter <= 1; inter++) {

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

            int newqr= 1;

            if (inter || plane > 0)

                newqr = get_bits1(gb);

            if (!newqr) {

                int qtj, plj;

                if(inter && get_bits1(gb)){

                    qtj = 0;

                    plj = plane;

                }else{

                    qtj= (3*inter + plane - 1) / 3;

                    plj= (plane + 2) % 3;

                s->qr_count[inter][plane]= s->qr_count[qtj][plj];

                memcpy(s->qr_size[inter][plane], s->qr_size[qtj][plj], sizeof(s->qr_size[0][0]));

                memcpy(s->qr_base[inter][plane], s->qr_base[qtj][plj], sizeof(s->qr_base[0][0]));

            } else {

                int qri= 0;

                int qi = 0;

                for(;;){

                    i= get_bits(gb, av_log2(matrices-1)+1);

                    if(i>= matrices){

                        av_log(avctx, AV_LOG_ERROR, "invalid base matrix index\n");

                        return -1;

                    s->qr_base[inter][plane][qri]= i;

                    if(qi >= 63)

                        break;

                    i = get_bits(gb, av_log2(63-qi)+1) + 1;

                    s->qr_size[inter][plane][qri++]= i;

                    qi += i;

                if (qi > 63) {

                    av_log(avctx, AV_LOG_ERROR, "invalid qi %d > 63\n", qi);

                    return -1;

                s->qr_count[inter][plane]= qri;

    /* Huffman tables */

    for (s->hti = 0; s->hti < 80; s->hti++) {

        s->entries = 0;

        s->huff_code_size = 1;

        if (!get_bits1(gb)) {

            s->hbits = 0;

            if(read_huffman_tree(avctx, gb))

                return -1;

            s->hbits = 1;

            if(read_huffman_tree(avctx, gb))

                return -1;

    s->theora_tables = 1;

    return 0;


int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)

{

    BDRVQcowState *s = bs->opaque;

    int64_t offset;

    size_t free_in_cluster;

    int ret;

    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES);

    assert(size > 0 && size <= s->cluster_size);

    assert(!s->free_byte_offset || offset_into_cluster(s, s->free_byte_offset));

    offset = s->free_byte_offset;

    if (offset) {

        uint64_t refcount;

        ret = qcow2_get_refcount(bs, offset >> s->cluster_bits, &refcount);

        if (ret < 0) {

            return ret;

        }

        if (refcount == s->refcount_max) {

            offset = 0;

        }

    }

    free_in_cluster = s->cluster_size - offset_into_cluster(s, offset);

    if (!offset || free_in_cluster < size) {

        int64_t new_cluster = alloc_clusters_noref(bs, s->cluster_size);

        if (new_cluster < 0) {

            return new_cluster;

        }

        if (!offset || ROUND_UP(offset, s->cluster_size) != new_cluster) {

            offset = new_cluster;

        }

    }

    assert(offset);

    ret = update_refcount(bs, offset, size, 1, false, QCOW2_DISCARD_NEVER);

    if (ret < 0) {

        return ret;

    }

    /* The cluster refcount was incremented; refcount blocks must be flushed

     * before the caller's L2 table updates. */

    qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache);

    s->free_byte_offset = offset + size;

    if (!offset_into_cluster(s, s->free_byte_offset)) {

        s->free_byte_offset = 0;

    }

    return offset;

}


void aio_co_schedule(AioContext *ctx, Coroutine *co)
{
    trace_aio_co_schedule(ctx, co);
    QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
                              co, co_scheduled_next);
    qemu_bh_schedule(ctx->co_schedule_bh);


static void xtensa_sim_init(MachineState *machine)

{

    XtensaCPU *cpu = NULL;

    CPUXtensaState *env = NULL;

    ram_addr_t ram_size = machine->ram_size;

    const char *cpu_model = machine->cpu_model;

    const char *kernel_filename = machine->kernel_filename;

    int n;

    if (!cpu_model) {

        cpu_model = XTENSA_DEFAULT_CPU_MODEL;

    }

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

        cpu = XTENSA_CPU(cpu_generic_init(TYPE_XTENSA_CPU, cpu_model));

        if (cpu == NULL) {

            error_report("unable to find CPU definition '%s'",

                         cpu_model);

            exit(EXIT_FAILURE);

        }

        env = &cpu->env;

        env->sregs[PRID] = n;

        qemu_register_reset(sim_reset, cpu);

        /* Need MMU initialized prior to ELF loading,

         * so that ELF gets loaded into virtual addresses

         */

        sim_reset(cpu);

    }

    if (env) {

        XtensaMemory sysram = env->config->sysram;

        sysram.location[0].size = ram_size;

        xtensa_create_memory_regions(&env->config->instrom, "xtensa.instrom");

        xtensa_create_memory_regions(&env->config->instram, "xtensa.instram");

        xtensa_create_memory_regions(&env->config->datarom, "xtensa.datarom");

        xtensa_create_memory_regions(&env->config->dataram, "xtensa.dataram");

        xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom");

        xtensa_create_memory_regions(&sysram, "xtensa.sysram");

    }

    if (serial_hds[0]) {

        xtensa_sim_open_console(serial_hds[0]);

    }

    if (kernel_filename) {

        uint64_t elf_entry;

        uint64_t elf_lowaddr;

#ifdef TARGET_WORDS_BIGENDIAN

        int success = load_elf(kernel_filename, translate_phys_addr, cpu,

                &elf_entry, &elf_lowaddr, NULL, 1, EM_XTENSA, 0, 0);

#else

        int success = load_elf(kernel_filename, translate_phys_addr, cpu,

                &elf_entry, &elf_lowaddr, NULL, 0, EM_XTENSA, 0, 0);

#endif

        if (success > 0) {

            env->pc = elf_entry;

        }

    }

}


void cpu_physical_memory_write_rom(target_phys_addr_t addr,

                                   const uint8_t *buf, int len)

{

    int l;

    uint8_t *ptr;

    target_phys_addr_t page;

    MemoryRegionSection *section;

    while (len > 0) {

        page = addr & TARGET_PAGE_MASK;

        l = (page + TARGET_PAGE_SIZE) - addr;

        if (l > len)

            l = len;

        section = phys_page_find(page >> TARGET_PAGE_BITS);

        if (!(memory_region_is_ram(section->mr) ||

              memory_region_is_romd(section->mr))) {

            /* do nothing */

        } else {

            unsigned long addr1;

            addr1 = memory_region_get_ram_addr(section->mr)

                + memory_region_section_addr(section, addr);

            /* ROM/RAM case */

            ptr = qemu_get_ram_ptr(addr1);

            memcpy(ptr, buf, l);

            qemu_put_ram_ptr(ptr);

        len -= l;

        buf += l;

        addr += l;


av_cold void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx)

{

    c->clear_block  = clear_block_8_c;

    c->clear_blocks = clear_blocks_8_c;

    c->fill_block_tab[0] = fill_block16_c;

    c->fill_block_tab[1] = fill_block8_c;

    if (ARCH_ARM)

        ff_blockdsp_init_arm(c);

    if (ARCH_PPC)

        ff_blockdsp_init_ppc(c);

    if (ARCH_X86)

#if FF_API_XVMC

        ff_blockdsp_init_x86(c, avctx);

#else

        ff_blockdsp_init_x86(c);

#endif /* FF_API_XVMC */

}


static void estimate_timings_from_bit_rate(AVFormatContext *ic)

{

    int64_t filesize, duration;

    int i;

    AVStream *st;

    /* if bit_rate is already set, we believe it */

    if (ic->bit_rate <= 0) {

        int bit_rate = 0;

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

            st = ic->streams[i];

            if (st->codec->bit_rate > 0) {

                if (INT_MAX - st->codec->bit_rate > bit_rate) {

                    bit_rate = 0;

                    break;

                }

                bit_rate += st->codec->bit_rate;

            }

        }

        ic->bit_rate = bit_rate;

    }

    /* if duration is already set, we believe it */

    if (ic->duration == AV_NOPTS_VALUE &&

        ic->bit_rate != 0) {

        filesize = ic->pb ? avio_size(ic->pb) : 0;

        if (filesize > 0) {

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

                st = ic->streams[i];

                duration= av_rescale(8*filesize, st->time_base.den, ic->bit_rate*(int64_t)st->time_base.num);

                if (st->duration == AV_NOPTS_VALUE)

                    st->duration = duration;

            }

        }

    }

}


AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
{
    AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef));
    if (!ret)
        return NULL;
    *ret = *ref;
    if (ref->type == AVMEDIA_TYPE_VIDEO) {
        ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
        if (!ret->video) {
            av_free(ret);
            return NULL;
        }
        copy_video_props(ret->video, ref->video);
        ret->extended_data = ret->data;
    } else if (ref->type == AVMEDIA_TYPE_AUDIO) {
        ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps));
        if (!ret->audio) {
            av_free(ret);
            return NULL;
        }
        *ret->audio = *ref->audio;
        if (ref->extended_data && ref->extended_data != ref->data) {
            int nb_channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
            if (!(ret->extended_data = av_malloc(sizeof(*ret->extended_data) *
                                                 nb_channels))) {
                av_freep(&ret->audio);
                av_freep(&ret);
                return NULL;
            }
            memcpy(ret->extended_data, ref->extended_data,
                   sizeof(*ret->extended_data) * nb_channels);
        } else
            ret->extended_data = ret->data;
    }
    ret->perms &= pmask;
    ret->buf->refcount ++;
    return ret;
}


static int parse_playlist(AppleHTTPContext *c, const char *url,

                          struct variant *var, AVIOContext *in)

{

    int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;

    enum KeyType key_type = KEY_NONE;

    uint8_t iv[16] = "";

    int has_iv = 0;

    char key[MAX_URL_SIZE];

    char line[1024];

    const char *ptr;

    int close_in = 0;

    if (!in) {

        close_in = 1;

        if ((ret = avio_open2(&in, url, AVIO_FLAG_READ,

                              c->interrupt_callback, NULL)) < 0)

            return ret;

    }

    read_chomp_line(in, line, sizeof(line));

    if (strcmp(line, "#EXTM3U")) {

        ret = AVERROR_INVALIDDATA;

        goto fail;

    }

    if (var) {

        free_segment_list(var);

        var->finished = 0;

    }

    while (!in->eof_reached) {

        read_chomp_line(in, line, sizeof(line));

        if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {

            struct variant_info info = {{0}};

            is_variant = 1;

            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,

                               &info);

            bandwidth = atoi(info.bandwidth);

        } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {

            struct key_info info = {{0}};

            ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,

                               &info);

            key_type = KEY_NONE;

            has_iv = 0;

            if (!strcmp(info.method, "AES-128"))

                key_type = KEY_AES_128;

            if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {

                ff_hex_to_data(iv, info.iv + 2);

                has_iv = 1;

            }

            av_strlcpy(key, info.uri, sizeof(key));

        } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {

            if (!var) {

                var = new_variant(c, 0, url, NULL);

                if (!var) {

                    ret = AVERROR(ENOMEM);

                    goto fail;

                }

            }

            var->target_duration = atoi(ptr);

        } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {

            if (!var) {

                var = new_variant(c, 0, url, NULL);

                if (!var) {

                    ret = AVERROR(ENOMEM);

                    goto fail;

                }

            }

            var->start_seq_no = atoi(ptr);

        } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {

            if (var)

                var->finished = 1;

        } else if (av_strstart(line, "#EXTINF:", &ptr)) {

            is_segment = 1;

            duration   = atoi(ptr);

        } else if (av_strstart(line, "#", NULL)) {

            continue;

        } else if (line[0]) {

            if (is_variant) {

                if (!new_variant(c, bandwidth, line, url)) {

                    ret = AVERROR(ENOMEM);

                    goto fail;

                }

                is_variant = 0;

                bandwidth  = 0;

            }

            if (is_segment) {

                struct segment *seg;

                if (!var) {

                    var = new_variant(c, 0, url, NULL);

                    if (!var) {

                        ret = AVERROR(ENOMEM);

                        goto fail;

                    }

                }

                seg = av_malloc(sizeof(struct segment));

                if (!seg) {

                    ret = AVERROR(ENOMEM);

                    goto fail;

                }

                seg->duration = duration;

                seg->key_type = key_type;

                if (has_iv) {

                    memcpy(seg->iv, iv, sizeof(iv));

                } else {

                    int seq = var->start_seq_no + var->n_segments;

                    memset(seg->iv, 0, sizeof(seg->iv));

                    AV_WB32(seg->iv + 12, seq);

                }

                ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);

                ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);

                dynarray_add(&var->segments, &var->n_segments, seg);

                is_segment = 0;

            }

        }

    }

    if (var)

        var->last_load_time = av_gettime();

fail:

    if (close_in)

        avio_close(in);

    return ret;

}


static int integrate(hdcd_state_t *state, int *flag, const int32_t *samples, int count, int stride)

{

    uint32_t bits = 0;

    int result = FFMIN(state->readahead, count);

    int i;

    *flag = 0;

    for (i = result - 1; i >= 0; i--) {

        bits |= (*samples & 1) << i; /* might be better as a conditional? */

        samples += stride;

    }

    state->window = (state->window << result) | bits;

    state->readahead -= result;

    if (state->readahead > 0)

        return result;

    bits = (state->window ^ state->window >> 5 ^ state->window >> 23);

    if (state->arg) {

        if ((bits & 0xffffffc8) == 0x0fa00500) {

            state->control = (bits & 255) + (bits & 7);

            *flag = 1;

            state->code_counterA++;

        }

        if (((bits ^ (~bits >> 8 & 255)) & 0xffff00ff) == 0xa0060000) {

            state->control = bits >> 8 & 255;

            *flag = 1;

            state->code_counterB++;

        }

        state->arg = 0;

    }

    if (bits == 0x7e0fa005 || bits == 0x7e0fa006) {

        state->readahead = (bits & 3) * 8;

        state->arg = 1;

        state->code_counterC++;

    } else {

        if (bits)

            state->readahead = readaheadtab[bits & ~(-1 << 8)];

        else

            state->readahead = 31; /* ffwd over digisilence */

    }

    return result;

}


static int svq1_decode_block_intra(GetBitContext *bitbuf, uint8_t *pixels,

                                   int pitch)

{

    uint32_t bit_cache;

    uint8_t *list[63];

    uint32_t *dst;

    const uint32_t *codebook;

    int entries[6];

    int i, j, m, n;

    int mean, stages;

    unsigned x, y, width, height, level;

    uint32_t n1, n2, n3, n4;

    /* initialize list for breadth first processing of vectors */

    list[0] = pixels;

    /* recursively process vector */

    for (i = 0, m = 1, n = 1, level = 5; i < n; i++) {

        SVQ1_PROCESS_VECTOR();

        /* destination address and vector size */

        dst    = (uint32_t *)list[i];

        width  = 1 << ((4 + level) / 2);

        height = 1 << ((3 + level) / 2);

        /* get number of stages (-1 skips vector, 0 for mean only) */

        stages = get_vlc2(bitbuf, svq1_intra_multistage[level].table, 3, 3) - 1;

        if (stages == -1) {

            for (y = 0; y < height; y++)

                memset(&dst[y * (pitch / 4)], 0, width);

            continue;   /* skip vector */

        }

        if (stages > 0 && level >= 4) {

            av_dlog(NULL,

                    "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",

                    stages, level);

            return AVERROR_INVALIDDATA;  /* invalid vector */

        }

        mean = get_vlc2(bitbuf, svq1_intra_mean.table, 8, 3);

        if (stages == 0) {

            for (y = 0; y < height; y++)

                memset(&dst[y * (pitch / 4)], mean, width);

        } else {

            SVQ1_CALC_CODEBOOK_ENTRIES(ff_svq1_intra_codebooks);

            for (y = 0; y < height; y++) {

                for (x = 0; x < width / 4; x++, codebook++) {

                    n1 = n4;

                    n2 = n4;

                    SVQ1_ADD_CODEBOOK()

                    /* store result */

                    dst[x] = n1 << 8 | n2;

                }

                dst += pitch / 4;

            }

        }

    }

    return 0;

}


int ff_h264_decode_mb_cavlc(H264Context *h){

    MpegEncContext * const s = &h->s;

    int mb_xy;

    int partition_count;

    unsigned int mb_type, cbp;

    int dct8x8_allowed= h->pps.transform_8x8_mode;

    mb_xy = h->mb_xy = s->mb_x + s->mb_y*s->mb_stride;

    tprintf(s->avctx, "pic:%d mb:%d/%d\n", h->frame_num, s->mb_x, s->mb_y);

    cbp = 0; /* avoid warning. FIXME: find a solution without slowing

                down the code */

    if(h->slice_type_nos != FF_I_TYPE){

        if(s->mb_skip_run==-1)

            s->mb_skip_run= get_ue_golomb(&s->gb);

        if (s->mb_skip_run--) {

            if(FRAME_MBAFF && (s->mb_y&1) == 0){

                if(s->mb_skip_run==0)

                    h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&s->gb);

                else

                    predict_field_decoding_flag(h);

            }

            decode_mb_skip(h);

            return 0;

        }

    }

    if(FRAME_MBAFF){

        if( (s->mb_y&1) == 0 )

            h->mb_mbaff = h->mb_field_decoding_flag = get_bits1(&s->gb);

    }

    h->prev_mb_skipped= 0;

    mb_type= get_ue_golomb(&s->gb);

    if(h->slice_type_nos == FF_B_TYPE){

        if(mb_type < 23){

            partition_count= b_mb_type_info[mb_type].partition_count;

            mb_type=         b_mb_type_info[mb_type].type;

        }else{

            mb_type -= 23;

            goto decode_intra_mb;

        }

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

        if(mb_type < 5){

            partition_count= p_mb_type_info[mb_type].partition_count;

            mb_type=         p_mb_type_info[mb_type].type;

        }else{

            mb_type -= 5;

            goto decode_intra_mb;

        }

    }else{

       assert(h->slice_type_nos == FF_I_TYPE);

        if(h->slice_type == FF_SI_TYPE && mb_type)

            mb_type--;

decode_intra_mb:

        if(mb_type > 25){

            av_log(h->s.avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_pict_type_char(h->slice_type), s->mb_x, s->mb_y);

            return -1;

        }

        partition_count=0;

        cbp= i_mb_type_info[mb_type].cbp;

        h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode;

        mb_type= i_mb_type_info[mb_type].type;

    }

    if(MB_FIELD)

        mb_type |= MB_TYPE_INTERLACED;

    h->slice_table[ mb_xy ]= h->slice_num;

    if(IS_INTRA_PCM(mb_type)){

        unsigned int x;

        // We assume these blocks are very rare so we do not optimize it.

        align_get_bits(&s->gb);

        // The pixels are stored in the same order as levels in h->mb array.

        for(x=0; x < (CHROMA ? 384 : 256); x++){

            ((uint8_t*)h->mb)[x]= get_bits(&s->gb, 8);

        }

        // In deblocking, the quantizer is 0

        s->current_picture.qscale_table[mb_xy]= 0;

        // All coeffs are present

        memset(h->non_zero_count[mb_xy], 16, 16);

        s->current_picture.mb_type[mb_xy]= mb_type;

        return 0;

    }

    if(MB_MBAFF){

        h->ref_count[0] <<= 1;

        h->ref_count[1] <<= 1;

    }

    fill_caches(h, mb_type, 0);

    //mb_pred

    if(IS_INTRA(mb_type)){

        int pred_mode;

//            init_top_left_availability(h);

        if(IS_INTRA4x4(mb_type)){

            int i;

            int di = 1;

            if(dct8x8_allowed && get_bits1(&s->gb)){

                mb_type |= MB_TYPE_8x8DCT;

                di = 4;

            }

//                fill_intra4x4_pred_table(h);

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

                int mode= pred_intra_mode(h, i);

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

                    const int rem_mode= get_bits(&s->gb, 3);

                    mode = rem_mode + (rem_mode >= mode);

                }

                if(di==4)

                    fill_rectangle( &h->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 );

                else

                    h->intra4x4_pred_mode_cache[ scan8[i] ] = mode;

            }

            ff_h264_write_back_intra_pred_mode(h);

            if( ff_h264_check_intra4x4_pred_mode(h) < 0)

                return -1;

        }else{

            h->intra16x16_pred_mode= ff_h264_check_intra_pred_mode(h, h->intra16x16_pred_mode);

            if(h->intra16x16_pred_mode < 0)

                return -1;

        }

        if(CHROMA){

            pred_mode= ff_h264_check_intra_pred_mode(h, get_ue_golomb_31(&s->gb));

            if(pred_mode < 0)

                return -1;

            h->chroma_pred_mode= pred_mode;

        }

    }else if(partition_count==4){

        int i, j, sub_partition_count[4], list, ref[2][4];

        if(h->slice_type_nos == FF_B_TYPE){

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

                h->sub_mb_type[i]= get_ue_golomb_31(&s->gb);

                if(h->sub_mb_type[i] >=13){

                    av_log(h->s.avctx, AV_LOG_ERROR, "B sub_mb_type %u out of range at %d %d\n", h->sub_mb_type[i], s->mb_x, s->mb_y);

                    return -1;

                }

                sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count;

                h->sub_mb_type[i]=      b_sub_mb_type_info[ h->sub_mb_type[i] ].type;

            }

            if(   IS_DIRECT(h->sub_mb_type[0]) || IS_DIRECT(h->sub_mb_type[1])

               || IS_DIRECT(h->sub_mb_type[2]) || IS_DIRECT(h->sub_mb_type[3])) {

                ff_h264_pred_direct_motion(h, &mb_type);

                h->ref_cache[0][scan8[4]] =

                h->ref_cache[1][scan8[4]] =

                h->ref_cache[0][scan8[12]] =

                h->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE;

            }

        }else{

            assert(h->slice_type_nos == FF_P_TYPE); //FIXME SP correct ?

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

                h->sub_mb_type[i]= get_ue_golomb_31(&s->gb);

                if(h->sub_mb_type[i] >=4){

                    av_log(h->s.avctx, AV_LOG_ERROR, "P sub_mb_type %u out of range at %d %d\n", h->sub_mb_type[i], s->mb_x, s->mb_y);

                    return -1;

                }

                sub_partition_count[i]= p_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count;

                h->sub_mb_type[i]=      p_sub_mb_type_info[ h->sub_mb_type[i] ].type;

            }

        }

        for(list=0; list<h->list_count; list++){

            int ref_count= IS_REF0(mb_type) ? 1 : h->ref_count[list];

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

                if(IS_DIRECT(h->sub_mb_type[i])) continue;

                if(IS_DIR(h->sub_mb_type[i], 0, list)){

                    unsigned int tmp;

                    if(ref_count == 1){

                        tmp= 0;

                    }else if(ref_count == 2){

                        tmp= get_bits1(&s->gb)^1;

                    }else{

                        tmp= get_ue_golomb_31(&s->gb);

                        if(tmp>=ref_count){

                            av_log(h->s.avctx, AV_LOG_ERROR, "ref %u overflow\n", tmp);

                            return -1;

                        }

                    }

                    ref[list][i]= tmp;

                }else{

                 //FIXME

                    ref[list][i] = -1;

                }

            }

        }

        if(dct8x8_allowed)

            dct8x8_allowed = get_dct8x8_allowed(h);

        for(list=0; list<h->list_count; list++){

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

                if(IS_DIRECT(h->sub_mb_type[i])) {

                    h->ref_cache[list][ scan8[4*i] ] = h->ref_cache[list][ scan8[4*i]+1 ];

                    continue;

                }

                h->ref_cache[list][ scan8[4*i]   ]=h->ref_cache[list][ scan8[4*i]+1 ]=

                h->ref_cache[list][ scan8[4*i]+8 ]=h->ref_cache[list][ scan8[4*i]+9 ]= ref[list][i];

                if(IS_DIR(h->sub_mb_type[i], 0, list)){

                    const int sub_mb_type= h->sub_mb_type[i];

                    const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1;

                    for(j=0; j<sub_partition_count[i]; j++){

                        int mx, my;

                        const int index= 4*i + block_width*j;

                        int16_t (* mv_cache)[2]= &h->mv_cache[list][ scan8[index] ];

                        pred_motion(h, index, block_width, list, h->ref_cache[list][ scan8[index] ], &mx, &my);

                        mx += get_se_golomb(&s->gb);

                        my += get_se_golomb(&s->gb);

                        tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                        if(IS_SUB_8X8(sub_mb_type)){

                            mv_cache[ 1 ][0]=

                            mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx;

                            mv_cache[ 1 ][1]=

                            mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my;

                        }else if(IS_SUB_8X4(sub_mb_type)){

                            mv_cache[ 1 ][0]= mx;

                            mv_cache[ 1 ][1]= my;

                        }else if(IS_SUB_4X8(sub_mb_type)){

                            mv_cache[ 8 ][0]= mx;

                            mv_cache[ 8 ][1]= my;

                        }

                        mv_cache[ 0 ][0]= mx;

                        mv_cache[ 0 ][1]= my;

                    }

                }else{

                    uint32_t *p= (uint32_t *)&h->mv_cache[list][ scan8[4*i] ][0];

                    p[0] = p[1]=

                    p[8] = p[9]= 0;

                }

            }

        }

    }else if(IS_DIRECT(mb_type)){

        ff_h264_pred_direct_motion(h, &mb_type);

        dct8x8_allowed &= h->sps.direct_8x8_inference_flag;

    }else{

        int list, mx, my, i;

         //FIXME we should set ref_idx_l? to 0 if we use that later ...

        if(IS_16X16(mb_type)){

            for(list=0; list<h->list_count; list++){

                    unsigned int val;

                    if(IS_DIR(mb_type, 0, list)){

                        if(h->ref_count[list]==1){

                            val= 0;

                        }else if(h->ref_count[list]==2){

                            val= get_bits1(&s->gb)^1;

                        }else{

                            val= get_ue_golomb_31(&s->gb);

                            if(val >= h->ref_count[list]){

                                av_log(h->s.avctx, AV_LOG_ERROR, "ref %u overflow\n", val);

                                return -1;

                            }

                        }

                    }else

                        val= LIST_NOT_USED&0xFF;

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

            }

            for(list=0; list<h->list_count; list++){

                unsigned int val;

                if(IS_DIR(mb_type, 0, list)){

                    pred_motion(h, 0, 4, list, h->ref_cache[list][ scan8[0] ], &mx, &my);

                    mx += get_se_golomb(&s->gb);

                    my += get_se_golomb(&s->gb);

                    tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                    val= pack16to32(mx,my);

                }else

                    val=0;

                fill_rectangle(h->mv_cache[list][ scan8[0] ], 4, 4, 8, val, 4);

            }

        }

        else if(IS_16X8(mb_type)){

            for(list=0; list<h->list_count; list++){

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

                        unsigned int val;

                        if(IS_DIR(mb_type, i, list)){

                            if(h->ref_count[list] == 1){

                                val= 0;

                            }else if(h->ref_count[list] == 2){

                                val= get_bits1(&s->gb)^1;

                            }else{

                                val= get_ue_golomb_31(&s->gb);

                                if(val >= h->ref_count[list]){

                                    av_log(h->s.avctx, AV_LOG_ERROR, "ref %u overflow\n", val);

                                    return -1;

                                }

                            }

                        }else

                            val= LIST_NOT_USED&0xFF;

                        fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 1);

                    }

            }

            for(list=0; list<h->list_count; list++){

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

                    unsigned int val;

                    if(IS_DIR(mb_type, i, list)){

                        pred_16x8_motion(h, 8*i, list, h->ref_cache[list][scan8[0] + 16*i], &mx, &my);

                        mx += get_se_golomb(&s->gb);

                        my += get_se_golomb(&s->gb);

                        tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                        val= pack16to32(mx,my);

                    }else

                        val=0;

                    fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 4);

                }

            }

        }else{

            assert(IS_8X16(mb_type));

            for(list=0; list<h->list_count; list++){

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

                        unsigned int val;

                        if(IS_DIR(mb_type, i, list)){ //FIXME optimize

                            if(h->ref_count[list]==1){

                                val= 0;

                            }else if(h->ref_count[list]==2){

                                val= get_bits1(&s->gb)^1;

                            }else{

                                val= get_ue_golomb_31(&s->gb);

                                if(val >= h->ref_count[list]){

                                    av_log(h->s.avctx, AV_LOG_ERROR, "ref %u overflow\n", val);

                                    return -1;

                                }

                            }

                        }else

                            val= LIST_NOT_USED&0xFF;

                        fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 1);

                    }

            }

            for(list=0; list<h->list_count; list++){

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

                    unsigned int val;

                    if(IS_DIR(mb_type, i, list)){

                        pred_8x16_motion(h, i*4, list, h->ref_cache[list][ scan8[0] + 2*i ], &mx, &my);

                        mx += get_se_golomb(&s->gb);

                        my += get_se_golomb(&s->gb);

                        tprintf(s->avctx, "final mv:%d %d\n", mx, my);

                        val= pack16to32(mx,my);

                    }else

                        val=0;

                    fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 4);

                }

            }

        }

    }

    if(IS_INTER(mb_type))

        write_back_motion(h, mb_type);

    if(!IS_INTRA16x16(mb_type)){

        cbp= get_ue_golomb(&s->gb);

        if(cbp > 47){

            av_log(h->s.avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, s->mb_x, s->mb_y);

            return -1;

        }

        if(CHROMA){

            if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp[cbp];

            else                     cbp= golomb_to_inter_cbp   [cbp];

        }else{

            if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp_gray[cbp];

            else                     cbp= golomb_to_inter_cbp_gray[cbp];

        }

    }

    h->cbp = cbp;

    if(dct8x8_allowed && (cbp&15) && !IS_INTRA(mb_type)){

        if(get_bits1(&s->gb)){

            mb_type |= MB_TYPE_8x8DCT;

            h->cbp_table[mb_xy]= cbp;

        }

    }

    s->current_picture.mb_type[mb_xy]= mb_type;

    if(cbp || IS_INTRA16x16(mb_type)){

        int i8x8, i4x4, chroma_idx;

        int dquant;

        GetBitContext *gb= IS_INTRA(mb_type) ? h->intra_gb_ptr : h->inter_gb_ptr;

        const uint8_t *scan, *scan8x8, *dc_scan;

//        fill_non_zero_count_cache(h);

        if(IS_INTERLACED(mb_type)){

            scan8x8= s->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0;

            scan= s->qscale ? h->field_scan : h->field_scan_q0;

            dc_scan= luma_dc_field_scan;

        }else{

            scan8x8= s->qscale ? h->zigzag_scan8x8_cavlc : h->zigzag_scan8x8_cavlc_q0;

            scan= s->qscale ? h->zigzag_scan : h->zigzag_scan_q0;

            dc_scan= luma_dc_zigzag_scan;

        }

        dquant= get_se_golomb(&s->gb);

        if( dquant > 25 || dquant < -26 ){

            av_log(h->s.avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, s->mb_x, s->mb_y);

            return -1;

        }

        s->qscale += dquant;

        if(((unsigned)s->qscale) > 51){

            if(s->qscale<0) s->qscale+= 52;

            else            s->qscale-= 52;

        }

        h->chroma_qp[0]= get_chroma_qp(h, 0, s->qscale);

        h->chroma_qp[1]= get_chroma_qp(h, 1, s->qscale);

        if(IS_INTRA16x16(mb_type)){

            if( decode_residual(h, h->intra_gb_ptr, h->mb, LUMA_DC_BLOCK_INDEX, dc_scan, h->dequant4_coeff[0][s->qscale], 16) < 0){

                return -1; //FIXME continue if partitioned and other return -1 too

            }

            assert((cbp&15) == 0 || (cbp&15) == 15);

            if(cbp&15){

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

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

                        const int index= i4x4 + 4*i8x8;

                        if( decode_residual(h, h->intra_gb_ptr, h->mb + 16*index, index, scan + 1, h->dequant4_coeff[0][s->qscale], 15) < 0 ){

                            return -1;

                        }

                    }

                }

            }else{

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

            }

        }else{

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

                if(cbp & (1<<i8x8)){

                    if(IS_8x8DCT(mb_type)){

                        DCTELEM *buf = &h->mb[64*i8x8];

                        uint8_t *nnz;

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

                            if( decode_residual(h, gb, buf, i4x4+4*i8x8, scan8x8+16*i4x4,

                                                h->dequant8_coeff[IS_INTRA( mb_type ) ? 0:1][s->qscale], 16) <0 )

                                return -1;

                        }

                        nnz= &h->non_zero_count_cache[ scan8[4*i8x8] ];

                        nnz[0] += nnz[1] + nnz[8] + nnz[9];

                    }else{

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

                            const int index= i4x4 + 4*i8x8;

                            if( decode_residual(h, gb, h->mb + 16*index, index, scan, h->dequant4_coeff[IS_INTRA( mb_type ) ? 0:3][s->qscale], 16) <0 ){

                                return -1;

                            }

                        }

                    }

                }else{

                    uint8_t * const nnz= &h->non_zero_count_cache[ scan8[4*i8x8] ];

                    nnz[0] = nnz[1] = nnz[8] = nnz[9] = 0;

                }

            }

        }

        if(cbp&0x30){

            for(chroma_idx=0; chroma_idx<2; chroma_idx++)

                if( decode_residual(h, gb, h->mb + 256 + 16*4*chroma_idx, CHROMA_DC_BLOCK_INDEX, chroma_dc_scan, NULL, 4) < 0){

                    return -1;

                }

        }

        if(cbp&0x20){

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

                const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][h->chroma_qp[chroma_idx]];

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

                    const int index= 16 + 4*chroma_idx + i4x4;

                    if( decode_residual(h, gb, h->mb + 16*index, index, scan + 1, qmul, 15) < 0){

                        return -1;

                    }

                }

            }

        }else{

            uint8_t * const nnz= &h->non_zero_count_cache[0];

            nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =

            nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;

        }

    }else{

        uint8_t * const nnz= &h->non_zero_count_cache[0];

        fill_rectangle(&nnz[scan8[0]], 4, 4, 8, 0, 1);

        nnz[ scan8[16]+0 ] = nnz[ scan8[16]+1 ] =nnz[ scan8[16]+8 ] =nnz[ scan8[16]+9 ] =

        nnz[ scan8[20]+0 ] = nnz[ scan8[20]+1 ] =nnz[ scan8[20]+8 ] =nnz[ scan8[20]+9 ] = 0;

    }

    s->current_picture.qscale_table[mb_xy]= s->qscale;

    write_back_non_zero_count(h);

    if(MB_MBAFF){

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

        h->ref_count[1] >>= 1;

    }

    return 0;

}


int av_opt_set(void *obj, const char *name, const char *val, int search_flags)

{

    int ret = 0;

    void *dst, *target_obj;

    const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);

    if (!o || !target_obj)

        return AVERROR_OPTION_NOT_FOUND;

    if (!val && (o->type != AV_OPT_TYPE_STRING &&

                 o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT &&

                 o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE &&

                 o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR &&

                 o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL))

        return AVERROR(EINVAL);

    if (o->flags & AV_OPT_FLAG_READONLY)

        return AVERROR(EINVAL);

    dst = ((uint8_t *)target_obj) + o->offset;

    switch (o->type) {

    case AV_OPT_TYPE_BOOL:

        return set_string_bool(obj, o, val, dst);

    case AV_OPT_TYPE_STRING:

        return set_string(obj, o, val, dst);

    case AV_OPT_TYPE_BINARY:

        return set_string_binary(obj, o, val, dst);

    case AV_OPT_TYPE_FLAGS:

    case AV_OPT_TYPE_INT:

    case AV_OPT_TYPE_INT64:

    case AV_OPT_TYPE_FLOAT:

    case AV_OPT_TYPE_DOUBLE:

    case AV_OPT_TYPE_RATIONAL:

        return set_string_number(obj, target_obj, o, val, dst);

    case AV_OPT_TYPE_IMAGE_SIZE:

        return set_string_image_size(obj, o, val, dst);

    case AV_OPT_TYPE_VIDEO_RATE:

        return set_string_video_rate(obj, o, val, dst);

    case AV_OPT_TYPE_PIXEL_FMT:

        return set_string_pixel_fmt(obj, o, val, dst);

    case AV_OPT_TYPE_SAMPLE_FMT:

        return set_string_sample_fmt(obj, o, val, dst);

    case AV_OPT_TYPE_DURATION:

        if (!val) {

            *(int64_t *)dst = 0;

            return 0;

        } else {

            if ((ret = av_parse_time(dst, val, 1)) < 0)

                av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", val);

            return ret;

        }

        break;

    case AV_OPT_TYPE_COLOR:

        return set_string_color(obj, o, val, dst);

    case AV_OPT_TYPE_CHANNEL_LAYOUT:

        if (!val || !strcmp(val, "none")) {

            *(int64_t *)dst = 0;

        } else {

            int64_t cl = av_get_channel_layout(val);

            if (!cl) {

                av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val);

                ret = AVERROR(EINVAL);

            }

            *(int64_t *)dst = cl;

            return ret;

        }

        break;

    }

    av_log(obj, AV_LOG_ERROR, "Invalid option type.\n");

    return AVERROR(EINVAL);

}


static int parse_uint64(DeviceState *dev, Property *prop, const char *str)

{

    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

    char *end;

    /* accept both hex and decimal */

    *ptr = strtoull(str, &end, 0);

    if ((*end != '\0') || (end == str)) {

        return -EINVAL;

    }

    return 0;

}


static void gen_mtsr_64b(DisasContext *ctx)

{

#if defined(CONFIG_USER_ONLY)

    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);

#else

    TCGv t0;

    if (unlikely(ctx->pr)) {

        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);

        return;

    }

    t0 = tcg_const_tl(SR(ctx->opcode));

    gen_helper_store_sr(cpu_env, t0, cpu_gpr[rS(ctx->opcode)]);

    tcg_temp_free(t0);

#endif

}


static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,

                               int64_t timestamp, int flags)

{

    // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)

    const AVDVProfile *sys = av_dv_codec_profile2(c->vst->codec->width, c->vst->codec->height,

                                                 c->vst->codec->pix_fmt, c->vst->codec->time_base);

    int64_t offset;

    int64_t size       = avio_size(s->pb) - s->internal->data_offset;

    int64_t max_offset = ((size - 1) / sys->frame_size) * sys->frame_size;

    offset = sys->frame_size * timestamp;

    if (size >= 0 && offset > max_offset)

        offset = max_offset;

    else if (offset < 0)

        offset = 0;

    return offset + s->internal->data_offset;

}


void msix_write_config(PCIDevice *dev, uint32_t addr,

                       uint32_t val, int len)

{

    unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;

    int vector;

    bool was_masked;

    if (!range_covers_byte(addr, len, enable_pos)) {

        return;

    }

    was_masked = dev->msix_function_masked;

    msix_update_function_masked(dev);

    if (!msix_enabled(dev)) {

        return;

    }

    pci_device_deassert_intx(dev);

    if (dev->msix_function_masked == was_masked) {

        return;

    }

    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {

        msix_handle_mask_update(dev, vector);

    }

}


static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,

                            VMStateField *field)

{

    uint32_t *v = pv;

    uint32_t v2;

    qemu_get_be32s(f, &v2);

    if (*v == v2) {

        return 0;

    error_report("%" PRIx32 " != %" PRIx32, *v, v2);

    return -EINVAL;


static int qemu_rdma_accept(RDMAContext *rdma)

{

    RDMACapabilities cap;

    struct rdma_conn_param conn_param = {

                                            .responder_resources = 2,

                                            .private_data = &cap,

                                            .private_data_len = sizeof(cap),

                                         };

    struct rdma_cm_event *cm_event;

    struct ibv_context *verbs;

    int ret = -EINVAL;

    int idx;

    ret = rdma_get_cm_event(rdma->channel, &cm_event);

    if (ret) {

        goto err_rdma_dest_wait;

    }

    if (cm_event->event != RDMA_CM_EVENT_CONNECT_REQUEST) {

        rdma_ack_cm_event(cm_event);

        goto err_rdma_dest_wait;

    }

    memcpy(&cap, cm_event->param.conn.private_data, sizeof(cap));

    network_to_caps(&cap);

    if (cap.version < 1 || cap.version > RDMA_CONTROL_VERSION_CURRENT) {

            fprintf(stderr, "Unknown source RDMA version: %d, bailing...\n",

                            cap.version);

            rdma_ack_cm_event(cm_event);

            goto err_rdma_dest_wait;

    }

    /*

     * Respond with only the capabilities this version of QEMU knows about.

     */

    cap.flags &= known_capabilities;

    /*

     * Enable the ones that we do know about.

     * Add other checks here as new ones are introduced.

     */

    if (cap.flags & RDMA_CAPABILITY_PIN_ALL) {

        rdma->pin_all = true;

    }

    rdma->cm_id = cm_event->id;

    verbs = cm_event->id->verbs;

    rdma_ack_cm_event(cm_event);

    DPRINTF("Memory pin all: %s\n", rdma->pin_all ? "enabled" : "disabled");

    caps_to_network(&cap);

    DPRINTF("verbs context after listen: %p\n", verbs);

    if (!rdma->verbs) {

        rdma->verbs = verbs;

    } else if (rdma->verbs != verbs) {

            fprintf(stderr, "ibv context not matching %p, %p!\n",

                    rdma->verbs, verbs);

            goto err_rdma_dest_wait;

    }

    qemu_rdma_dump_id("dest_init", verbs);

    ret = qemu_rdma_alloc_pd_cq(rdma);

    if (ret) {

        fprintf(stderr, "rdma migration: error allocating pd and cq!\n");

        goto err_rdma_dest_wait;

    }

    ret = qemu_rdma_alloc_qp(rdma);

    if (ret) {

        fprintf(stderr, "rdma migration: error allocating qp!\n");

        goto err_rdma_dest_wait;

    }

    ret = qemu_rdma_init_ram_blocks(rdma);

    if (ret) {

        fprintf(stderr, "rdma migration: error initializing ram blocks!\n");

        goto err_rdma_dest_wait;

    }

    for (idx = 0; idx < RDMA_WRID_MAX; idx++) {

        ret = qemu_rdma_reg_control(rdma, idx);

        if (ret) {

            fprintf(stderr, "rdma: error registering %d control!\n", idx);

            goto err_rdma_dest_wait;

        }

    }

    qemu_set_fd_handler2(rdma->channel->fd, NULL, NULL, NULL, NULL);

    ret = rdma_accept(rdma->cm_id, &conn_param);

    if (ret) {

        fprintf(stderr, "rdma_accept returns %d!\n", ret);

        goto err_rdma_dest_wait;

    }

    ret = rdma_get_cm_event(rdma->channel, &cm_event);

    if (ret) {

        fprintf(stderr, "rdma_accept get_cm_event failed %d!\n", ret);

        goto err_rdma_dest_wait;

    }

    if (cm_event->event != RDMA_CM_EVENT_ESTABLISHED) {

        fprintf(stderr, "rdma_accept not event established!\n");

        rdma_ack_cm_event(cm_event);

        goto err_rdma_dest_wait;

    }

    rdma_ack_cm_event(cm_event);

    rdma->connected = true;

    ret = qemu_rdma_post_recv_control(rdma, RDMA_WRID_READY);

    if (ret) {

        fprintf(stderr, "rdma migration: error posting second control recv!\n");

        goto err_rdma_dest_wait;

    }

    qemu_rdma_dump_gid("dest_connect", rdma->cm_id);

    return 0;

err_rdma_dest_wait:

    rdma->error_state = ret;

    qemu_rdma_cleanup(rdma);

    return ret;

}


int inet_listen(const char *str, char *ostr, int olen,

                int socktype, int port_offset, Error **errp)

{

    QemuOpts *opts;

    char *optstr;

    int sock = -1;

    opts = qemu_opts_create(&dummy_opts, NULL, 0);

    if (inet_parse(opts, str) == 0) {

        sock = inet_listen_opts(opts, port_offset, errp);

        if (sock != -1 && ostr) {

            optstr = strchr(str, ',');

            if (qemu_opt_get_bool(opts, "ipv6", 0)) {

                snprintf(ostr, olen, "[%s]:%s%s",

                         qemu_opt_get(opts, "host"),

                         qemu_opt_get(opts, "port"),

                         optstr ? optstr : "");

            } else {

                snprintf(ostr, olen, "%s:%s%s",

                         qemu_opt_get(opts, "host"),

                         qemu_opt_get(opts, "port"),

                         optstr ? optstr : "");

            }

        }

    } else {

        error_set(errp, QERR_SOCKET_CREATE_FAILED);

    }

    qemu_opts_del(opts);

    return sock;

}


static int ogg_read_page(AVFormatContext *s, int *sid)

{

    AVIOContext *bc = s->pb;

    struct ogg *ogg = s->priv_data;

    struct ogg_stream *os;

    int ret, i = 0;

    int flags, nsegs;

    uint64_t gp;

    uint32_t serial;

    int size, idx;

    uint8_t sync[4];

    int sp = 0;

    ret = avio_read(bc, sync, 4);

    if (ret < 4)

        return ret < 0 ? ret : AVERROR_EOF;

    do {

        int c;

        if (sync[sp & 3] == 'O' &&

            sync[(sp + 1) & 3] == 'g' &&

            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')

            break;

        if(!i && bc->seekable && ogg->page_pos > 0) {

            memset(sync, 0, 4);

            avio_seek(bc, ogg->page_pos+4, SEEK_SET);

            ogg->page_pos = -1;

        }

        c = avio_r8(bc);

        if (avio_feof(bc))

            return AVERROR_EOF;

        sync[sp++ & 3] = c;

    } while (i++ < MAX_PAGE_SIZE);

    if (i >= MAX_PAGE_SIZE) {

        av_log(s, AV_LOG_INFO, "cannot find sync word\n");

        return AVERROR_INVALIDDATA;

    }

    if (avio_r8(bc) != 0) {      /* version */

        av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");

        return AVERROR_INVALIDDATA;

    }

    flags  = avio_r8(bc);

    gp     = avio_rl64(bc);

    serial = avio_rl32(bc);

    avio_skip(bc, 8); /* seq, crc */

    nsegs  = avio_r8(bc);

    idx = ogg_find_stream(ogg, serial);

    if (idx < 0) {

        if (data_packets_seen(ogg))

            idx = ogg_replace_stream(s, serial, nsegs);

        else

            idx = ogg_new_stream(s, serial);

        if (idx < 0) {

            av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");

            return idx;

        }

    }

    os = ogg->streams + idx;

    ogg->page_pos =

    os->page_pos = avio_tell(bc) - 27;

    if (os->psize > 0)

        ogg_new_buf(ogg, idx);

    ret = avio_read(bc, os->segments, nsegs);

    if (ret < nsegs)

        return ret < 0 ? ret : AVERROR_EOF;

    os->nsegs = nsegs;

    os->segp  = 0;

    size = 0;

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

        size += os->segments[i];

    if (!(flags & OGG_FLAG_BOS))

        os->got_data = 1;

    if (flags & OGG_FLAG_CONT || os->incomplete) {

        if (!os->psize) {

            // If this is the very first segment we started

            // playback in the middle of a continuation packet.

            // Discard it since we missed the start of it.

            while (os->segp < os->nsegs) {

                int seg = os->segments[os->segp++];

                os->pstart += seg;

                if (seg < 255)

                    break;

            }

            os->sync_pos = os->page_pos;

        }

    } else {

        os->psize    = 0;

        os->sync_pos = os->page_pos;

    }

    if (os->bufsize - os->bufpos < size) {

        uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);

        if (!nb)

            return AVERROR(ENOMEM);

        memcpy(nb, os->buf, os->bufpos);

        av_free(os->buf);

        os->buf = nb;

    }

    ret = avio_read(bc, os->buf + os->bufpos, size);

    if (ret < size)

        return ret < 0 ? ret : AVERROR_EOF;

    os->bufpos += size;

    os->granule = gp;

    os->flags   = flags;

    memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    if (sid)

        *sid = idx;

    return 0;

}


static inline void RENAME(uyvyToUV)(uint8_t *dstU, uint8_t *dstV, uint8_t *src1, uint8_t *src2, long width)

{

#ifdef HAVE_MMX

	asm volatile(

		"movq "MANGLE(bm01010101)", %%mm4\n\t"

		"mov %0, %%"REG_a"		\n\t"

		"1:				\n\t"

		"movq (%1, %%"REG_a",4), %%mm0	\n\t"

		"movq 8(%1, %%"REG_a",4), %%mm1	\n\t"

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

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

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

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

		"psrlw $8, %%mm0		\n\t"

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

		"packuswb %%mm0, %%mm0		\n\t"

		"packuswb %%mm1, %%mm1		\n\t"

		"movd %%mm0, (%3, %%"REG_a")	\n\t"

		"movd %%mm1, (%2, %%"REG_a")	\n\t"

		"add $4, %%"REG_a"		\n\t"

		" js 1b				\n\t"

		: : "g" (-width), "r" (src1+width*4), "r" (dstU+width), "r" (dstV+width)

		: "%"REG_a

	);

#else

	int i;

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

	{

		dstU[i]= src1[4*i + 0];

		dstV[i]= src1[4*i + 2];

	}

#endif

        assert(src1 == src2);

}


static void r2d_init(MachineState *machine)

{

    const char *cpu_model = machine->cpu_model;

    const char *kernel_filename = machine->kernel_filename;

    const char *kernel_cmdline = machine->kernel_cmdline;

    const char *initrd_filename = machine->initrd_filename;

    SuperHCPU *cpu;

    CPUSH4State *env;

    ResetData *reset_info;

    struct SH7750State *s;

    MemoryRegion *sdram = g_new(MemoryRegion, 1);

    qemu_irq *irq;

    DriveInfo *dinfo;

    int i;

    DeviceState *dev;

    SysBusDevice *busdev;

    MemoryRegion *address_space_mem = get_system_memory();

    PCIBus *pci_bus;

    if (cpu_model == NULL) {

        cpu_model = "SH7751R";

    }

    cpu = cpu_sh4_init(cpu_model);

    if (cpu == NULL) {

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

        exit(1);

    }

    env = &cpu->env;

    reset_info = g_malloc0(sizeof(ResetData));

    reset_info->cpu = cpu;

    reset_info->vector = env->pc;

    qemu_register_reset(main_cpu_reset, reset_info);

    /* Allocate memory space */

    memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE, &error_abort);

    vmstate_register_ram_global(sdram);

    memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);

    /* Register peripherals */

    s = sh7750_init(cpu, address_space_mem);

    irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));

    dev = qdev_create(NULL, "sh_pci");

    busdev = SYS_BUS_DEVICE(dev);

    qdev_init_nofail(dev);

    pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci"));

    sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));

    sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));

    sysbus_connect_irq(busdev, 0, irq[PCI_INTA]);

    sysbus_connect_irq(busdev, 1, irq[PCI_INTB]);

    sysbus_connect_irq(busdev, 2, irq[PCI_INTC]);

    sysbus_connect_irq(busdev, 3, irq[PCI_INTD]);

    sm501_init(address_space_mem, 0x10000000, SM501_VRAM_SIZE,

               irq[SM501], serial_hds[2]);

    /* onboard CF (True IDE mode, Master only). */

    dinfo = drive_get(IF_IDE, 0, 0);

    dev = qdev_create(NULL, "mmio-ide");

    busdev = SYS_BUS_DEVICE(dev);

    sysbus_connect_irq(busdev, 0, irq[CF_IDE]);

    qdev_prop_set_uint32(dev, "shift", 1);

    qdev_init_nofail(dev);

    sysbus_mmio_map(busdev, 0, 0x14001000);

    sysbus_mmio_map(busdev, 1, 0x1400080c);

    mmio_ide_init_drives(dev, dinfo, NULL);

    /* onboard flash memory */

    dinfo = drive_get(IF_PFLASH, 0, 0);

    pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,

                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,

                          (16 * 1024), FLASH_SIZE >> 16,

                          1, 4, 0x0000, 0x0000, 0x0000, 0x0000,

                          0x555, 0x2aa, 0);

    /* NIC: rtl8139 on-board, and 2 slots. */

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

        pci_nic_init_nofail(&nd_table[i], pci_bus,

                            "rtl8139", i==0 ? "2" : NULL);

    /* USB keyboard */

    usb_create_simple(usb_bus_find(-1), "usb-kbd");

    /* Todo: register on board registers */

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

    if (kernel_filename) {

        int kernel_size;

        kernel_size = load_image_targphys(kernel_filename,

                                          SDRAM_BASE + LINUX_LOAD_OFFSET,

                                          INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);

        if (kernel_size < 0) {

          fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);

          exit(1);

        }

        /* initialization which should be done by firmware */

        address_space_stl(&address_space_memory, SH7750_BCR1, 1 << 3,

                          MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 SDRAM */

        address_space_stw(&address_space_memory, SH7750_BCR2, 3 << (3 * 2),

                          MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 32bit */

        reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */

    }

    if (initrd_filename) {

        int initrd_size;

        initrd_size = load_image_targphys(initrd_filename,

                                          SDRAM_BASE + INITRD_LOAD_OFFSET,

                                          SDRAM_SIZE - INITRD_LOAD_OFFSET);

        if (initrd_size < 0) {

          fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);

          exit(1);

        }

        /* initialization which should be done by firmware */

        boot_params.loader_type = tswap32(1);

        boot_params.initrd_start = tswap32(INITRD_LOAD_OFFSET);

        boot_params.initrd_size = tswap32(initrd_size);

    }

    if (kernel_cmdline) {

        /* I see no evidence that this .kernel_cmdline buffer requires

           NUL-termination, so using strncpy should be ok. */

        strncpy(boot_params.kernel_cmdline, kernel_cmdline,

                sizeof(boot_params.kernel_cmdline));

    }

    rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),

                       SDRAM_BASE + BOOT_PARAMS_OFFSET);

}


static void menelaus_rtc_hz(void *opaque)

{

    struct menelaus_s *s = (struct menelaus_s *) opaque;

    s->rtc.next_comp --;

    s->rtc.alm_sec --;

    s->rtc.next += 1000;

    qemu_mod_timer(s->rtc.hz, s->rtc.next);

    if ((s->rtc.ctrl >> 3) & 3) {				/* EVERY */

        menelaus_rtc_update(s);

        if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)

            s->status |= 1 << 8;				/* RTCTMR */

        else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)

            s->status |= 1 << 8;				/* RTCTMR */

        else if (!s->rtc.tm.tm_hour)

            s->status |= 1 << 8;				/* RTCTMR */

    } else

        s->status |= 1 << 8;					/* RTCTMR */

    if ((s->rtc.ctrl >> 1) & 1) {				/* RTC_AL_EN */

        if (s->rtc.alm_sec == 0)

            s->status |= 1 << 9;				/* RTCALM */

        /* TODO: wake-up */

    }

    if (s->rtc.next_comp <= 0) {

        s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000);

        s->rtc.next_comp = 3600;

    }

    menelaus_update(s);

}


static void net_slirp_cleanup(NetClientState *nc)

{

    SlirpState *s = DO_UPCAST(SlirpState, nc, nc);

    slirp_cleanup(s->slirp);

    qemu_remove_exit_notifier(&s->exit_notifier);

    slirp_smb_cleanup(s);

    QTAILQ_REMOVE(&slirp_stacks, s, entry);

}


static void FUNC(intra_pred)(HEVCContext *s, int x0, int y0, int log2_size, int c_idx)

{

#define PU(x) \

    ((x) >> s->sps->log2_min_pu_size)

#define MVF(x, y) \

    (s->ref->tab_mvf[(x) + (y) * pic_width_in_min_pu])

#define MVF_PU(x, y) \

    MVF(PU(x0 + ((x) << hshift)), PU(y0 + ((y) << vshift)))

#define IS_INTRA(x, y) \

    MVF_PU(x, y).is_intra

#define MIN_TB_ADDR_ZS(x, y) \

    s->pps->min_tb_addr_zs[(y) * s->sps->min_tb_width + (x)]

#define EXTEND_LEFT(ptr, start, length) \

        for (i = (start); i > (start) - (length); i--) \

            ptr[i - 1] = ptr[i]

#define EXTEND_RIGHT(ptr, start, length) \

        for (i = (start); i < (start) + (length); i++) \

            ptr[i] = ptr[i - 1]

#define EXTEND_UP(ptr, start, length)   EXTEND_LEFT(ptr, start, length)

#define EXTEND_DOWN(ptr, start, length) EXTEND_RIGHT(ptr, start, length)

#define EXTEND_LEFT_CIP(ptr, start, length) \

        for (i = (start); i > (start) - (length); i--) \

            if (!IS_INTRA(i - 1, -1)) \

                ptr[i - 1] = ptr[i]

#define EXTEND_RIGHT_CIP(ptr, start, length) \

        for (i = (start); i < (start) + (length); i++) \

            if (!IS_INTRA(i, -1)) \

                ptr[i] = ptr[i - 1]

#define EXTEND_UP_CIP(ptr, start, length) \

        for (i = (start); i > (start) - (length); i--) \

            if (!IS_INTRA(-1, i - 1)) \

                ptr[i - 1] = ptr[i]

#define EXTEND_UP_CIP_0(ptr, start, length) \

        for (i = (start); i > (start) - (length); i--) \

            ptr[i - 1] = ptr[i]

#define EXTEND_DOWN_CIP(ptr, start, length) \

        for (i = (start); i < (start) + (length); i++) \

            if (!IS_INTRA(-1, i)) \

                ptr[i] = ptr[i - 1]

    HEVCLocalContext *lc = s->HEVClc;

    int i;

    int hshift = s->sps->hshift[c_idx];

    int vshift = s->sps->vshift[c_idx];

    int size = (1 << log2_size);

    int size_in_luma = size << hshift;

    int size_in_tbs = size_in_luma >> s->sps->log2_min_transform_block_size;

    int x = x0 >> hshift;

    int y = y0 >> vshift;

    int x_tb = x0 >> s->sps->log2_min_transform_block_size;

    int y_tb = y0 >> s->sps->log2_min_transform_block_size;

    int cur_tb_addr = MIN_TB_ADDR_ZS(x_tb, y_tb);

    ptrdiff_t stride = s->frame->linesize[c_idx] / sizeof(pixel);

    pixel *src = (pixel*)s->frame->data[c_idx] + x + y * stride;

    int pic_width_in_min_pu = PU(s->sps->width);

    enum IntraPredMode mode = c_idx ? lc->pu.intra_pred_mode_c :

                              lc->tu.cur_intra_pred_mode;

    pixel left_array[2 * MAX_TB_SIZE + 1];

    pixel filtered_left_array[2 * MAX_TB_SIZE + 1];

    pixel top_array[2 * MAX_TB_SIZE + 1];

    pixel filtered_top_array[2 * MAX_TB_SIZE + 1];

    pixel *left          = left_array + 1;

    pixel *top           = top_array + 1;

    pixel *filtered_left = filtered_left_array + 1;

    pixel *filtered_top  = filtered_top_array + 1;

    int cand_bottom_left = lc->na.cand_bottom_left && cur_tb_addr > MIN_TB_ADDR_ZS(x_tb - 1, y_tb + size_in_tbs);

    int cand_left        = lc->na.cand_left;

    int cand_up_left     = lc->na.cand_up_left;

    int cand_up          = lc->na.cand_up;

    int cand_up_right    = lc->na.cand_up_right && cur_tb_addr > MIN_TB_ADDR_ZS(x_tb + size_in_tbs, y_tb - 1);

    int bottom_left_size = (FFMIN(y0 + 2 * size_in_luma, s->sps->height) -

                            (y0 + size_in_luma)) >> vshift;

    int top_right_size   = (FFMIN(x0 + 2 * size_in_luma, s->sps->width) -

                            (x0 + size_in_luma)) >> hshift;

    if (s->pps->constrained_intra_pred_flag == 1) {

        int size_in_luma_pu = PU(size_in_luma);

        int on_pu_edge_x = !(x0 & ((1 << s->sps->log2_min_pu_size) - 1));

        int on_pu_edge_y = !(y0 & ((1 << s->sps->log2_min_pu_size) - 1));

        if(!size_in_luma_pu)

            size_in_luma_pu++;

        if (cand_bottom_left == 1 && on_pu_edge_x) {

            int x_left_pu   = PU(x0 - 1);

            int y_bottom_pu = PU(y0 + size_in_luma);

            cand_bottom_left = 0;

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

                cand_bottom_left |= MVF(x_left_pu, y_bottom_pu + i).is_intra;

        }

        if (cand_left == 1 && on_pu_edge_x) {

            int x_left_pu   = PU(x0 - 1);

            int y_left_pu   = PU(y0);

            cand_left = 0;

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

                cand_left |= MVF(x_left_pu, y_left_pu + i).is_intra;

        }

        if (cand_up_left == 1) {

            int x_left_pu   = PU(x0 - 1);

            int y_top_pu    = PU(y0 - 1);

            cand_up_left = MVF(x_left_pu, y_top_pu).is_intra;

        }

        if (cand_up == 1 && on_pu_edge_y) {

            int x_top_pu    = PU(x0);

            int y_top_pu    = PU(y0 - 1);

            cand_up = 0;

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

                cand_up |= MVF(x_top_pu + i, y_top_pu).is_intra;

        }

        if (cand_up_right == 1 && on_pu_edge_y) {

            int y_top_pu    = PU(y0 - 1);

            int x_right_pu  = PU(x0 + size_in_luma);

            cand_up_right = 0;

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

                cand_up_right |= MVF(x_right_pu + i, y_top_pu).is_intra;

        }

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

            left[i] = 128;

            top[i]  = 128;

        }

    }

    if (cand_bottom_left) {

        for (i = size + bottom_left_size; i < (size << 1); i++)

            if (IS_INTRA(-1, size + bottom_left_size - 1) || !s->pps->constrained_intra_pred_flag)

                left[i] = POS(-1, size + bottom_left_size - 1);

        for (i = size + bottom_left_size - 1; i >= size; i--)

            if (IS_INTRA(-1, i) || !s->pps->constrained_intra_pred_flag)

                left[i] = POS(-1, i);

    }

    if (cand_left)

        for (i = size - 1; i >= 0; i--)

            if (IS_INTRA(-1, i) || !s->pps->constrained_intra_pred_flag)

                left[i] = POS(-1, i);

    if (cand_up_left)

        if (IS_INTRA(-1, -1) || !s->pps->constrained_intra_pred_flag) {

            left[-1] = POS(-1, -1);

            top[-1]  = left[-1];

        }

    if (cand_up)

        for (i = size - 1; i >= 0; i--)

            if (IS_INTRA(i, -1) || !s->pps->constrained_intra_pred_flag)

                top[i] = POS(i, -1);

    if (cand_up_right) {

        for (i = size + top_right_size; i < (size << 1); i++)

            if (IS_INTRA(size + top_right_size - 1, -1) || !s->pps->constrained_intra_pred_flag)

                top[i] = POS(size + top_right_size - 1, -1);

        for (i = size + top_right_size - 1; i >= size; i--)

            if (IS_INTRA(i, -1) || !s->pps->constrained_intra_pred_flag)

                top[i] = POS(i, -1);

    }

    if (s->pps->constrained_intra_pred_flag == 1) {

        if (cand_bottom_left || cand_left || cand_up_left || cand_up || cand_up_right) {

            int size_max_x = x0 + ((2 * size) << hshift) < s->sps->width ?

                                    2 * size : (s->sps->width - x0) >> hshift;

            int size_max_y = y0 + ((2 * size) << vshift) < s->sps->height ?

                                    2 * size : (s->sps->height - y0) >> vshift;

            int j = size + (cand_bottom_left? bottom_left_size: 0) -1;

            if (!cand_up_right) {

                size_max_x = x0 + ((size) << hshift) < s->sps->width ?

                                                    size : (s->sps->width - x0) >> hshift;

            }

            if (!cand_bottom_left) {

                size_max_y = y0 + (( size) << vshift) < s->sps->height ?

                                                     size : (s->sps->height - y0) >> vshift;

            }

            if (cand_bottom_left || cand_left || cand_up_left) {

                while (j>-1 && !IS_INTRA(-1, j)) j--;

                if (!IS_INTRA(-1, j)) {

                    j = 0;

                    while(j < size_max_x && !IS_INTRA(j, -1)) j++;

                    EXTEND_LEFT_CIP(top, j, j+1);

                    left[-1] = top[-1];

                    j = 0;

                }

            } else {

                j = 0;

                while (j < size_max_x && !IS_INTRA(j, -1)) j++;

                if (j > 0)

                    if (x0 > 0) {

                        EXTEND_LEFT_CIP(top, j, j+1);

                    } else {

                        EXTEND_LEFT_CIP(top, j, j);

                        top[-1] = top[0];

                    }

                left[-1] = top[-1];

                j = 0;

            }

            if (cand_bottom_left || cand_left) {

                EXTEND_DOWN_CIP(left, j, size_max_y-j);

            }

            if (!cand_left) {

                EXTEND_DOWN(left, 0, size);

            }

            if (!cand_bottom_left) {

                EXTEND_DOWN(left, size, size);

            }

            if (x0 != 0 && y0 != 0) {

                EXTEND_UP_CIP(left, size_max_y - 1, size_max_y);

            } else if( x0 == 0) {

                EXTEND_UP_CIP_0(left, size_max_y - 1, size_max_y);

            } else{

                EXTEND_UP_CIP(left, size_max_y - 1, size_max_y-1);

            }

            top[-1] = left[-1];

            if (y0 != 0) {

                EXTEND_RIGHT_CIP(top, 0, size_max_x);

            }

        }

    }

    // Infer the unavailable samples

    if (!cand_bottom_left) {

        if (cand_left) {

            EXTEND_DOWN(left, size, size);

        } else if (cand_up_left) {

            EXTEND_DOWN(left, 0, 2 * size);

            cand_left = 1;

        } else if (cand_up) {

            left[-1] = top[0];

            EXTEND_DOWN(left, 0, 2 * size);

            cand_up_left = 1;

            cand_left = 1;

        } else if (cand_up_right) {

            EXTEND_LEFT(top, size, size);

            left[-1] = top[0];

            EXTEND_DOWN(left ,0 , 2 * size);

            cand_up = 1;

            cand_up_left = 1;

            cand_left = 1;

        } else { // No samples available

            top[0] = left[-1] = (1 << (BIT_DEPTH - 1));

            EXTEND_RIGHT(top, 1, 2 * size - 1);

            EXTEND_DOWN(left, 0, 2 * size);

        }

    }

    if (!cand_left) {

        EXTEND_UP(left, size, size);

    }

    if (!cand_up_left) {

        left[-1] = left[0];

    }

    if (!cand_up) {

        top[0] = left[-1];

        EXTEND_RIGHT(top, 1, size-1);

    }

    if (!cand_up_right) {

        EXTEND_RIGHT(top, size, size);

    }

    top[-1] = left[-1];

#undef EXTEND_LEFT_CIP

#undef EXTEND_RIGHT_CIP

#undef EXTEND_UP_CIP

#undef EXTEND_DOWN_CIP

#undef IS_INTRA

#undef MVF_PU

#undef MVF

#undef PU

#undef EXTEND_LEFT

#undef EXTEND_RIGHT

#undef EXTEND_UP

#undef EXTEND_DOWN

#undef MIN_TB_ADDR_ZS

    // Filtering process

    if (c_idx == 0 && mode != INTRA_DC && size != 4) {

        int intra_hor_ver_dist_thresh[] = { 7, 1, 0 };

        int min_dist_vert_hor           = FFMIN(FFABS((int)mode - 26),

                                                FFABS((int)mode - 10));

        if (min_dist_vert_hor > intra_hor_ver_dist_thresh[log2_size - 3]) {

            int threshold = 1 << (BIT_DEPTH - 5);

            if (s->sps->sps_strong_intra_smoothing_enable_flag &&

                log2_size == 5 &&

                FFABS(top[-1] + top[63] - 2 * top[31]) < threshold &&

                FFABS(left[-1] + left[63] - 2 * left[31]) < threshold) {

                // We can't just overwrite values in top because it could be

                // a pointer into src

                filtered_top[-1] = top[-1];

                filtered_top[63] = top[63];

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

                    filtered_top[i] = ((64 - (i + 1)) * top[-1] +

                                             (i + 1)  * top[63] + 32) >> 6;

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

                    left[i] = ((64 - (i + 1)) * left[-1] +

                                     (i + 1)  * left[63] + 32) >> 6;

                top = filtered_top;

            } else {

                filtered_left[2 * size - 1] = left[2 * size - 1];

                filtered_top[2 * size - 1]  = top[2 * size - 1];

                for (i = 2 * size - 2; i >= 0; i--)

                    filtered_left[i] = (left[i + 1] + 2 * left[i] +

                                        left[i - 1] + 2) >> 2;

                filtered_top[-1] =

                filtered_left[-1] = (left[0] + 2 * left[-1] +

                                     top[0]  + 2) >> 2;

                for (i = 2 * size - 2; i >= 0; i--)

                    filtered_top[i] = (top[i + 1] + 2 * top[i] +

                                       top[i - 1] + 2) >> 2;

                left = filtered_left;

                top  = filtered_top;

            }

        }

    }

    switch (mode) {

    case INTRA_PLANAR:

        s->hpc.pred_planar[log2_size - 2]((uint8_t*)src, (uint8_t*)top,

                                          (uint8_t*)left, stride);

        break;

    case INTRA_DC:

        s->hpc.pred_dc((uint8_t*)src, (uint8_t*)top,

                       (uint8_t*)left, stride, log2_size, c_idx);

        break;

    default:

        s->hpc.pred_angular[log2_size - 2]((uint8_t*)src, (uint8_t*)top,

                                           (uint8_t*)left, stride, c_idx, mode);

        break;

    }

}


TranslationBlock *tb_gen_code(CPUState *cpu,

                              target_ulong pc, target_ulong cs_base,

                              int flags, int cflags)

{

    CPUArchState *env = cpu->env_ptr;

    TranslationBlock *tb;

    tb_page_addr_t phys_pc, phys_page2;

    target_ulong virt_page2;

    tcg_insn_unit *gen_code_buf;

    int gen_code_size, search_size;

#ifdef CONFIG_PROFILER

    int64_t ti;

#endif

    phys_pc = get_page_addr_code(env, pc);

    if (use_icount) {

        cflags |= CF_USE_ICOUNT;

    }

    tb = tb_alloc(pc);

    if (!tb) {

        /* flush must be done */

        tb_flush(cpu);

        /* cannot fail at this point */

        tb = tb_alloc(pc);

        /* Don't forget to invalidate previous TB info.  */

        tcg_ctx.tb_ctx.tb_invalidated_flag = 1;

    }

    gen_code_buf = tcg_ctx.code_gen_ptr;

    tb->tc_ptr = gen_code_buf;

    tb->cs_base = cs_base;

    tb->flags = flags;

    tb->cflags = cflags;

#ifdef CONFIG_PROFILER

    tcg_ctx.tb_count1++; /* includes aborted translations because of

                       exceptions */

    ti = profile_getclock();

#endif

    tcg_func_start(&tcg_ctx);

    gen_intermediate_code(env, tb);

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

    /* generate machine code */

    tb->tb_next_offset[0] = 0xffff;

    tb->tb_next_offset[1] = 0xffff;

    tcg_ctx.tb_next_offset = tb->tb_next_offset;

#ifdef USE_DIRECT_JUMP

    tcg_ctx.tb_jmp_offset = tb->tb_jmp_offset;

    tcg_ctx.tb_next = NULL;

#else

    tcg_ctx.tb_jmp_offset = NULL;

    tcg_ctx.tb_next = tb->tb_next;

#endif

#ifdef CONFIG_PROFILER

    tcg_ctx.tb_count++;

    tcg_ctx.interm_time += profile_getclock() - ti;

    tcg_ctx.code_time -= profile_getclock();

#endif

    gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf);

    search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);

#ifdef CONFIG_PROFILER

    tcg_ctx.code_time += profile_getclock();

    tcg_ctx.code_in_len += tb->size;

    tcg_ctx.code_out_len += gen_code_size;

    tcg_ctx.search_out_len += search_size;

#endif

#ifdef DEBUG_DISAS

    if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {

        qemu_log("OUT: [size=%d]\n", gen_code_size);

        log_disas(tb->tc_ptr, gen_code_size);

        qemu_log("\n");

        qemu_log_flush();

    }

#endif

    tcg_ctx.code_gen_ptr = (void *)

        ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,

                 CODE_GEN_ALIGN);

    /* check next page if needed */

    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;

    phys_page2 = -1;

    if ((pc & TARGET_PAGE_MASK) != virt_page2) {

        phys_page2 = get_page_addr_code(env, virt_page2);

    }

    tb_link_page(tb, phys_pc, phys_page2);

    return tb;

}


static inline void vc1_pred_b_mv(VC1Context *v, int dmv_x[2], int dmv_y[2],
                                 int direct, int mvtype)
{
    MpegEncContext *s = &v->s;
    int xy, wrap, off = 0;
    int16_t *A, *B, *C;
    int px, py;
    int sum;
    int r_x, r_y;
    const uint8_t *is_intra = v->mb_type[0];
    r_x = v->range_x;
    r_y = v->range_y;
    /* scale MV difference to be quad-pel */
    dmv_x[0] <<= 1 - s->quarter_sample;
    dmv_y[0] <<= 1 - s->quarter_sample;
    dmv_x[1] <<= 1 - s->quarter_sample;
    dmv_y[1] <<= 1 - s->quarter_sample;
    wrap = s->b8_stride;
    xy = s->block_index[0];
    if (s->mb_intra) {
        s->current_picture.motion_val[0][xy + v->blocks_off][0] =
        s->current_picture.motion_val[0][xy + v->blocks_off][1] =
        s->current_picture.motion_val[1][xy + v->blocks_off][0] =
        s->current_picture.motion_val[1][xy + v->blocks_off][1] = 0;
        return;
    }
    if (!v->field_mode) {
        s->mv[0][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 0, s->quarter_sample);
        s->mv[0][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 0, s->quarter_sample);
        s->mv[1][0][0] = scale_mv(s->next_picture.motion_val[1][xy][0], v->bfraction, 1, s->quarter_sample);
        s->mv[1][0][1] = scale_mv(s->next_picture.motion_val[1][xy][1], v->bfraction, 1, s->quarter_sample);
        /* Pullback predicted motion vectors as specified in 8.4.5.4 */
        s->mv[0][0][0] = av_clip(s->mv[0][0][0], -60 - (s->mb_x << 6), (s->mb_width  << 6) - 4 - (s->mb_x << 6));
        s->mv[0][0][1] = av_clip(s->mv[0][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6));
        s->mv[1][0][0] = av_clip(s->mv[1][0][0], -60 - (s->mb_x << 6), (s->mb_width  << 6) - 4 - (s->mb_x << 6));
        s->mv[1][0][1] = av_clip(s->mv[1][0][1], -60 - (s->mb_y << 6), (s->mb_height << 6) - 4 - (s->mb_y << 6));
    }
    if (direct) {
        s->current_picture.motion_val[0][xy + v->blocks_off][0] = s->mv[0][0][0];
        s->current_picture.motion_val[0][xy + v->blocks_off][1] = s->mv[0][0][1];
        s->current_picture.motion_val[1][xy + v->blocks_off][0] = s->mv[1][0][0];
        s->current_picture.motion_val[1][xy + v->blocks_off][1] = s->mv[1][0][1];
        return;
    }
    if ((mvtype == BMV_TYPE_FORWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
        C   = s->current_picture.motion_val[0][xy - 2];
        A   = s->current_picture.motion_val[0][xy - wrap * 2];
        off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
        B   = s->current_picture.motion_val[0][xy - wrap * 2 + off];
        if (!s->mb_x) C[0] = C[1] = 0;
        if (!s->first_slice_line) { // predictor A is not out of bounds
            if (s->mb_width == 1) {
                px = A[0];
                py = A[1];
            } else {
                px = mid_pred(A[0], B[0], C[0]);
                py = mid_pred(A[1], B[1], C[1]);
            }
        } else if (s->mb_x) { // predictor C is not out of bounds
            px = C[0];
            py = C[1];
        } else {
            px = py = 0;
        }
        /* Pullback MV as specified in 8.3.5.3.4 */
        {
            int qx, qy, X, Y;
            if (v->profile < PROFILE_ADVANCED) {
                qx = (s->mb_x << 5);
                qy = (s->mb_y << 5);
                X  = (s->mb_width  << 5) - 4;
                Y  = (s->mb_height << 5) - 4;
                if (qx + px < -28) px = -28 - qx;
                if (qy + py < -28) py = -28 - qy;
                if (qx + px > X) px = X - qx;
                if (qy + py > Y) py = Y - qy;
            } else {
                qx = (s->mb_x << 6);
                qy = (s->mb_y << 6);
                X  = (s->mb_width  << 6) - 4;
                Y  = (s->mb_height << 6) - 4;
                if (qx + px < -60) px = -60 - qx;
                if (qy + py < -60) py = -60 - qy;
                if (qx + px > X) px = X - qx;
                if (qy + py > Y) py = Y - qy;
            }
        }
        /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
        if (0 && !s->first_slice_line && s->mb_x) {
            if (is_intra[xy - wrap])
                sum = FFABS(px) + FFABS(py);
            else
                sum = FFABS(px - A[0]) + FFABS(py - A[1]);
            if (sum > 32) {
                if (get_bits1(&s->gb)) {
                    px = A[0];
                    py = A[1];
                } else {
                    px = C[0];
                    py = C[1];
                }
            } else {
                if (is_intra[xy - 2])
                    sum = FFABS(px) + FFABS(py);
                else
                    sum = FFABS(px - C[0]) + FFABS(py - C[1]);
                if (sum > 32) {
                    if (get_bits1(&s->gb)) {
                        px = A[0];
                        py = A[1];
                    } else {
                        px = C[0];
                        py = C[1];
                    }
                }
            }
        }
        /* store MV using signed modulus of MV range defined in 4.11 */
        s->mv[0][0][0] = ((px + dmv_x[0] + r_x) & ((r_x << 1) - 1)) - r_x;
        s->mv[0][0][1] = ((py + dmv_y[0] + r_y) & ((r_y << 1) - 1)) - r_y;
    }
    if ((mvtype == BMV_TYPE_BACKWARD) || (mvtype == BMV_TYPE_INTERPOLATED)) {
        C   = s->current_picture.motion_val[1][xy - 2];
        A   = s->current_picture.motion_val[1][xy - wrap * 2];
        off = (s->mb_x == (s->mb_width - 1)) ? -2 : 2;
        B   = s->current_picture.motion_val[1][xy - wrap * 2 + off];
        if (!s->mb_x)
            C[0] = C[1] = 0;
        if (!s->first_slice_line) { // predictor A is not out of bounds
            if (s->mb_width == 1) {
                px = A[0];
                py = A[1];
            } else {
                px = mid_pred(A[0], B[0], C[0]);
                py = mid_pred(A[1], B[1], C[1]);
            }
        } else if (s->mb_x) { // predictor C is not out of bounds
            px = C[0];
            py = C[1];
        } else {
            px = py = 0;
        }
        /* Pullback MV as specified in 8.3.5.3.4 */
        {
            int qx, qy, X, Y;
            if (v->profile < PROFILE_ADVANCED) {
                qx = (s->mb_x << 5);
                qy = (s->mb_y << 5);
                X  = (s->mb_width  << 5) - 4;
                Y  = (s->mb_height << 5) - 4;
                if (qx + px < -28) px = -28 - qx;
                if (qy + py < -28) py = -28 - qy;
                if (qx + px > X) px = X - qx;
                if (qy + py > Y) py = Y - qy;
            } else {
                qx = (s->mb_x << 6);
                qy = (s->mb_y << 6);
                X  = (s->mb_width  << 6) - 4;
                Y  = (s->mb_height << 6) - 4;
                if (qx + px < -60) px = -60 - qx;
                if (qy + py < -60) py = -60 - qy;
                if (qx + px > X) px = X - qx;
                if (qy + py > Y) py = Y - qy;
            }
        }
        /* Calculate hybrid prediction as specified in 8.3.5.3.5 */
        if (0 && !s->first_slice_line && s->mb_x) {
            if (is_intra[xy - wrap])
                sum = FFABS(px) + FFABS(py);
            else
                sum = FFABS(px - A[0]) + FFABS(py - A[1]);
            if (sum > 32) {
                if (get_bits1(&s->gb)) {
                    px = A[0];
                    py = A[1];
                } else {
                    px = C[0];
                    py = C[1];
                }
            } else {
                if (is_intra[xy - 2])
                    sum = FFABS(px) + FFABS(py);
                else
                    sum = FFABS(px - C[0]) + FFABS(py - C[1]);
                if (sum > 32) {
                    if (get_bits1(&s->gb)) {
                        px = A[0];
                        py = A[1];
                    } else {
                        px = C[0];
                        py = C[1];
                    }
                }
            }
        }
        /* store MV using signed modulus of MV range defined in 4.11 */
        s->mv[1][0][0] = ((px + dmv_x[1] + r_x) & ((r_x << 1) - 1)) - r_x;
        s->mv[1][0][1] = ((py + dmv_y[1] + r_y) & ((r_y << 1) - 1)) - r_y;
    }
    s->current_picture.motion_val[0][xy][0] = s->mv[0][0][0];
    s->current_picture.motion_val[0][xy][1] = s->mv[0][0][1];
    s->current_picture.motion_val[1][xy][0] = s->mv[1][0][0];
    s->current_picture.motion_val[1][xy][1] = s->mv[1][0][1];
}


static void test_ide_drive_user(const char *dev, bool trans)

{

    char *argv[256], *opts;

    int argc;

    int secs = img_secs[backend_small];

    const CHST expected_chst = { secs / (4 * 32) , 4, 32, trans };

    argc = setup_common(argv, ARRAY_SIZE(argv));

    opts = g_strdup_printf("%s,%s%scyls=%d,heads=%d,secs=%d",

                           dev ?: "",

                           trans && dev ? "bios-chs-" : "",

                           trans ? "trans=lba," : "",

                           expected_chst.cyls, expected_chst.heads,

                           expected_chst.secs);

    cur_ide[0] = &expected_chst;

    argc = setup_ide(argc, argv, ARRAY_SIZE(argv),

                     0, dev ? opts : NULL, backend_small, mbr_chs,

                     dev ? "" : opts);

    g_free(opts);

    qtest_start(g_strjoinv(" ", argv));

    test_cmos();

    qtest_end();

}


static int read_rle_sgi(const SGIInfo *sgi_info,

        AVPicture *pict, ByteIOContext *f)

{

    uint8_t *dest_row, *rle_data = NULL;

    unsigned long *start_table, *length_table;

    int y, z, xsize, ysize, zsize, tablen;

    long start_offset, run_length;

    int ret = 0;

    xsize = sgi_info->xsize;

    ysize = sgi_info->ysize;

    zsize = sgi_info->zsize;

    rle_data = av_malloc(xsize);

    /* skip header */

    url_fseek(f, SGI_HEADER_SIZE, SEEK_SET);

    /* size of rle offset and length tables */

    tablen = ysize * zsize * sizeof(long);

    start_table = (unsigned long *)av_malloc(tablen);

    length_table = (unsigned long *)av_malloc(tablen);

    if (!get_buffer(f, (uint8_t *)start_table, tablen)) {

        ret = -1;

        goto fail;

    }

    if (!get_buffer(f, (uint8_t *)length_table, tablen)) {

        ret = -1;

        goto fail;

    }

    for (z = 0; z < zsize; z++) {

        for (y = 0; y < ysize; y++) {

            dest_row = pict->data[0] + (ysize - 1 - y) * (xsize * zsize);

            start_offset = BE_32(&start_table[y + z * ysize]);

            run_length = BE_32(&length_table[y + z * ysize]);

            /* don't seek if already in the correct spot */

            if (url_ftell(f) != start_offset) {

                url_fseek(f, start_offset, SEEK_SET);

            }

            get_buffer(f, rle_data, run_length);

            expand_rle_row(dest_row, rle_data, z, zsize);

        }

    }

fail:

    av_free(start_table);

    av_free(length_table);

    av_free(rle_data);

    return ret;

}


static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,

                                 target_ulong eaddr, int rw)

{

    int in_plb, ret;

    ctx->raddr = eaddr;

    ctx->prot = PAGE_READ | PAGE_EXEC;

    ret = 0;

    switch (env->mmu_model) {

    case POWERPC_MMU_32B:

    case POWERPC_MMU_601:

    case POWERPC_MMU_SOFT_6xx:

    case POWERPC_MMU_SOFT_74xx:

    case POWERPC_MMU_SOFT_4xx:

    case POWERPC_MMU_REAL:

    case POWERPC_MMU_BOOKE:

        ctx->prot |= PAGE_WRITE;

        break;

#if defined(TARGET_PPC64)

    case POWERPC_MMU_620:

    case POWERPC_MMU_64B:

    case POWERPC_MMU_2_06:

        /* Real address are 60 bits long */

        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;

        ctx->prot |= PAGE_WRITE;

        break;

#endif

    case POWERPC_MMU_SOFT_4xx_Z:

        if (unlikely(msr_pe != 0)) {

            /* 403 family add some particular protections,

             * using PBL/PBU registers for accesses with no translation.

             */

            in_plb =

                /* Check PLB validity */

                (env->pb[0] < env->pb[1] &&

                 /* and address in plb area */

                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||

                (env->pb[2] < env->pb[3] &&

                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;

            if (in_plb ^ msr_px) {

                /* Access in protected area */

                if (rw == 1) {

                    /* Access is not allowed */

                    ret = -2;

                }

            } else {

                /* Read-write access is allowed */

                ctx->prot |= PAGE_WRITE;

            }

        }

        break;

    case POWERPC_MMU_MPC8xx:

        /* XXX: TODO */

        cpu_abort(env, "MPC8xx MMU model is not implemented\n");

        break;

    case POWERPC_MMU_BOOKE206:

        cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");

        break;

    default:

        cpu_abort(env, "Unknown or invalid MMU model\n");

        return -1;

    }

    return ret;

}