void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)

{

    if (!error_is_set(errp)) {

        if (v->type_int64) {

            v->type_int64(v, obj, name, errp);

        } else {

            v->type_int(v, obj, name, errp);

        }

    }

}


static inline void idct4col_add(uint8_t *dest, int line_size, const DCTELEM *col)

{

    int c0, c1, c2, c3, a0, a1, a2, a3;

    const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;

    a0 = col[8*0];

    a1 = col[8*1];

    a2 = col[8*2];

    a3 = col[8*3];

    c0 = (a0 + a2)*C3 + (1 << (C_SHIFT - 1));

    c2 = (a0 - a2)*C3 + (1 << (C_SHIFT - 1));

    c1 = a1 * C1 + a3 * C2;

    c3 = a1 * C2 - a3 * C1;

    dest[0] = cm[dest[0] + ((c0 + c1) >> C_SHIFT)];

    dest += line_size;

    dest[0] = cm[dest[0] + ((c2 + c3) >> C_SHIFT)];

    dest += line_size;

    dest[0] = cm[dest[0] + ((c2 - c3) >> C_SHIFT)];

    dest += line_size;

    dest[0] = cm[dest[0] + ((c0 - c1) >> C_SHIFT)];

}


void bdrv_detach_aio_context(BlockDriverState *bs)

{

    BdrvAioNotifier *baf;

    BdrvChild *child;

    if (!bs->drv) {

        return;

    }

    QLIST_FOREACH(baf, &bs->aio_notifiers, list) {

        baf->detach_aio_context(baf->opaque);

    }

    if (bs->drv->bdrv_detach_aio_context) {

        bs->drv->bdrv_detach_aio_context(bs);

    }

    QLIST_FOREACH(child, &bs->children, next) {

        bdrv_detach_aio_context(child->bs);

    }

    bs->aio_context = NULL;

}


void cpu_ppc_reset (void *opaque)

{

    CPUPPCState *env;

    target_ulong msr;

    env = opaque;

    msr = (target_ulong)0;

    if (0) {

        /* XXX: find a suitable condition to enable the hypervisor mode */

        msr |= (target_ulong)MSR_HVB;

    }

    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */

    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */

    msr |= (target_ulong)1 << MSR_EP;

#if defined (DO_SINGLE_STEP) && 0

    /* Single step trace mode */

    msr |= (target_ulong)1 << MSR_SE;

    msr |= (target_ulong)1 << MSR_BE;

#endif

#if defined(CONFIG_USER_ONLY)

    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */

    msr |= (target_ulong)1 << MSR_PR;

#else

    env->nip = env->hreset_vector | env->excp_prefix;

    if (env->mmu_model != POWERPC_MMU_REAL)

        ppc_tlb_invalidate_all(env);

#endif

    env->msr = msr;

    hreg_compute_hflags(env);

    env->reserve = (target_ulong)-1ULL;

    /* Be sure no exception or interrupt is pending */

    env->pending_interrupts = 0;

    env->exception_index = POWERPC_EXCP_NONE;

    env->error_code = 0;

    /* Flush all TLBs */

    tlb_flush(env, 1);

}


static void omap_sti_write(void *opaque, target_phys_addr_t addr,

                           uint64_t value, unsigned size)

{

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

    if (size != 4) {

        return omap_badwidth_write32(opaque, addr, value);

    }

    switch (addr) {

    case 0x00:	/* STI_REVISION */

    case 0x14:	/* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */

        OMAP_RO_REG(addr);

        return;

    case 0x10:	/* STI_SYSCONFIG */

        if (value & (1 << 1))				/* SOFTRESET */

            omap_sti_reset(s);

        s->sysconfig = value & 0xfe;

        break;

    case 0x18:	/* STI_IRQSTATUS */

        s->irqst &= ~value;

        omap_sti_interrupt_update(s);

        break;

    case 0x1c:	/* STI_IRQSETEN / STI_IRQCLREN */

        s->irqen = value & 0xffff;

        omap_sti_interrupt_update(s);

        break;

    case 0x2c:	/* STI_CLK_CTRL / XTI_SCLKCRTL */

        s->clkcontrol = value & 0xff;

        break;

    case 0x30:	/* STI_SERIAL_CFG / XTI_SCONFIG */

        s->serial_config = value & 0xff;

        break;

    case 0x24:	/* STI_ER / STI_DR / XTI_TRACESELECT */

    case 0x28:	/* STI_RX_DR / XTI_RXDATA */

        /* TODO */

        return;

    default:

        OMAP_BAD_REG(addr);

        return;

    }

}


static void gdb_chr_event(void *opaque, int event)

{

    switch (event) {

    case CHR_EVENT_RESET:

        vm_stop(EXCP_INTERRUPT);

        gdb_syscall_state = opaque;

        gdb_has_xml = 0;

        break;

    default:

        break;

    }

}


static void release_keys(void *opaque)

{

    int keycode;

    while (nb_pending_keycodes > 0) {

        nb_pending_keycodes--;

        keycode = keycodes[nb_pending_keycodes];

        if (keycode & 0x80)

            kbd_put_keycode(0xe0);

        kbd_put_keycode(keycode | 0x80);

    }

}


static int virtio_scsi_parse_req(VirtIOSCSIReq *req,

                                 unsigned req_size, unsigned resp_size)

{

    VirtIODevice *vdev = (VirtIODevice *) req->dev;

    size_t in_size, out_size;

    if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,

                   &req->req, req_size) < req_size) {

        return -EINVAL;

    }

    if (qemu_iovec_concat_iov(&req->resp_iov,

                              req->elem.in_sg, req->elem.in_num, 0,

                              resp_size) < resp_size) {

        return -EINVAL;

    }

    req->resp_size = resp_size;

    /* Old BIOSes left some padding by mistake after the req_size/resp_size.

     * As a workaround, always consider the first buffer as the virtio-scsi

     * request/response, making the payload start at the second element

     * of the iovec.

     *

     * The actual length of the response header, stored in req->resp_size,

     * does not change.

     *

     * TODO: always disable this workaround for virtio 1.0 devices.

     */

    if ((vdev->guest_features & (1 << VIRTIO_F_ANY_LAYOUT)) == 0) {

        req_size = req->elem.out_sg[0].iov_len;

        resp_size = req->elem.in_sg[0].iov_len;

    }

    out_size = qemu_sgl_concat(req, req->elem.out_sg,

                               &req->elem.out_addr[0], req->elem.out_num,

                               req_size);

    in_size = qemu_sgl_concat(req, req->elem.in_sg,

                              &req->elem.in_addr[0], req->elem.in_num,

                              resp_size);

    if (out_size && in_size) {

        return -ENOTSUP;

    }

    if (out_size) {

        req->mode = SCSI_XFER_TO_DEV;

    } else if (in_size) {

        req->mode = SCSI_XFER_FROM_DEV;

    }

    return 0;

}


void pc_dimm_memory_unplug(DeviceState *dev, MemoryHotplugState *hpms,

                           MemoryRegion *mr)

{

    PCDIMMDevice *dimm = PC_DIMM(dev);

    numa_unset_mem_node_id(dimm->addr, memory_region_size(mr), dimm->node);

    memory_region_del_subregion(&hpms->mr, mr);

    vmstate_unregister_ram(mr, dev);

}


static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)

{

    if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {

        int i;

        fprintf(stderr, "KVM internal error. Suberror: %d\n",

                run->internal.suberror);

        for (i = 0; i < run->internal.ndata; ++i) {

            fprintf(stderr, "extra data[%d]: %"PRIx64"\n",

                    i, (uint64_t)run->internal.data[i]);

        }

    }

    cpu_dump_state(env, stderr, fprintf, 0);

    if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {

        fprintf(stderr, "emulation failure\n");

        if (!kvm_arch_stop_on_emulation_error(env)) {

            return;

        }

    }

    /* FIXME: Should trigger a qmp message to let management know

     * something went wrong.

     */

    vm_stop(0);

}


void ff_slice_buffer_init(slice_buffer *buf, int line_count,

                          int max_allocated_lines, int line_width,

                          IDWTELEM *base_buffer)

{

    int i;

    buf->base_buffer = base_buffer;

    buf->line_count  = line_count;

    buf->line_width  = line_width;

    buf->data_count  = max_allocated_lines;

    buf->line        = av_mallocz(sizeof(IDWTELEM *) * line_count);

    buf->data_stack  = av_malloc(sizeof(IDWTELEM *) * max_allocated_lines);

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

        buf->data_stack[i] = av_malloc(sizeof(IDWTELEM) * line_width);

    buf->data_stack_top = max_allocated_lines - 1;

}


static void xenfb_mouse_event(DeviceState *dev, QemuConsole *src,

                              InputEvent *evt)

{

    struct XenInput *xenfb = (struct XenInput *)dev;

    InputBtnEvent *btn;

    InputMoveEvent *move;

    QemuConsole *con;

    DisplaySurface *surface;

    int scale;

    switch (evt->type) {

    case INPUT_EVENT_KIND_BTN:

        btn = evt->u.btn.data;

        switch (btn->button) {

        case INPUT_BUTTON_LEFT:

            xenfb_send_key(xenfb, btn->down, BTN_LEFT);

            break;

        case INPUT_BUTTON_RIGHT:

            xenfb_send_key(xenfb, btn->down, BTN_LEFT + 1);

            break;

        case INPUT_BUTTON_MIDDLE:

            xenfb_send_key(xenfb, btn->down, BTN_LEFT + 2);

            break;

        case INPUT_BUTTON_WHEEL_UP:

            if (btn->down) {

                xenfb->wheel--;

            }

            break;

        case INPUT_BUTTON_WHEEL_DOWN:

            if (btn->down) {

                xenfb->wheel++;

            }

            break;

        default:

            break;

        }

        break;

    case INPUT_EVENT_KIND_ABS:

        move = evt->u.abs.data;

        con = qemu_console_lookup_by_index(0);

        if (!con) {

            xen_pv_printf(&xenfb->c.xendev, 0, "No QEMU console available");

            return;

        }

        surface = qemu_console_surface(con);

        switch (move->axis) {

        case INPUT_AXIS_X:

            scale = surface_width(surface) - 1;

            break;

        case INPUT_AXIS_Y:

            scale = surface_height(surface) - 1;

            break;

        default:

            scale = 0x8000;

            break;

        }

        xenfb->axis[move->axis] = move->value * scale / 0x7fff;

        break;

    case INPUT_EVENT_KIND_REL:

        move = evt->u.rel.data;

        xenfb->axis[move->axis] += move->value;

        break;

    default:

        break;

    }

}


static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,

                                                bool is_listen, bool is_telnet,

                                                bool is_waitconnect,

                                                Error **errp)

{

    CharDriverState *chr = NULL;

    TCPCharDriver *s = NULL;

    char host[NI_MAXHOST], serv[NI_MAXSERV];

    const char *left = "", *right = "";

    struct sockaddr_storage ss;

    socklen_t ss_len = sizeof(ss);

    memset(&ss, 0, ss_len);

    if (getsockname(fd, (struct sockaddr *) &ss, &ss_len) != 0) {

        error_setg_errno(errp, errno, "getsockname");

        return NULL;

    }

    chr = g_malloc0(sizeof(CharDriverState));

    s = g_malloc0(sizeof(TCPCharDriver));

    s->connected = 0;

    s->fd = -1;

    s->listen_fd = -1;

    s->read_msgfds = 0;

    s->read_msgfds_num = 0;

    s->write_msgfds = 0;

    s->write_msgfds_num = 0;

    chr->filename = g_malloc(256);

    switch (ss.ss_family) {

#ifndef _WIN32

    case AF_UNIX:

        s->is_unix = 1;

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

                 ((struct sockaddr_un *)(&ss))->sun_path,

                 is_listen ? ",server" : "");

        break;

#endif

    case AF_INET6:

        left  = "[";

        right = "]";

        /* fall through */

    case AF_INET:

        s->do_nodelay = do_nodelay;

        getnameinfo((struct sockaddr *) &ss, ss_len, host, sizeof(host),

                    serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV);

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

                 is_telnet ? "telnet" : "tcp",

                 left, host, right, serv,

                 is_listen ? ",server" : "");

        break;

    }

    chr->opaque = s;

    chr->chr_write = tcp_chr_write;

    chr->chr_sync_read = tcp_chr_sync_read;

    chr->chr_close = tcp_chr_close;

    chr->get_msgfds = tcp_get_msgfds;

    chr->set_msgfds = tcp_set_msgfds;

    chr->chr_add_client = tcp_chr_add_client;

    chr->chr_add_watch = tcp_chr_add_watch;

    chr->chr_update_read_handler = tcp_chr_update_read_handler;

    /* be isn't opened until we get a connection */

    chr->explicit_be_open = true;

    if (is_listen) {

        s->listen_fd = fd;

        s->listen_chan = io_channel_from_socket(s->listen_fd);

        s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr);

        if (is_telnet) {

            s->do_telnetopt = 1;

        }

    } else {

        s->connected = 1;

        s->fd = fd;

        socket_set_nodelay(fd);

        s->chan = io_channel_from_socket(s->fd);

        tcp_chr_connect(chr);

    }

    if (is_listen && is_waitconnect) {

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

                chr->filename);

        tcp_chr_accept(s->listen_chan, G_IO_IN, chr);

        qemu_set_nonblock(s->listen_fd);

    }

    return chr;

}


static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,

                        const struct in_addr **preq_addr)

{

    const uint8_t *p, *p_end;

    int len, tag;

    *pmsg_type = 0;

    *preq_addr = NULL;

    p = bp->bp_vend;

    p_end = p + DHCP_OPT_LEN;

    if (memcmp(p, rfc1533_cookie, 4) != 0)

        return;

    p += 4;

    while (p < p_end) {

        tag = p[0];

        if (tag == RFC1533_PAD) {

            p++;

        } else if (tag == RFC1533_END) {

            break;

        } else {

            p++;

            if (p >= p_end)

                break;

            len = *p++;

            DPRINTF("dhcp: tag=%d len=%d\n", tag, len);

            switch(tag) {

            case RFC2132_MSG_TYPE:

                if (len >= 1)

                    *pmsg_type = p[0];

                break;

            case RFC2132_REQ_ADDR:

                if (len >= 4)

                    *preq_addr = (struct in_addr *)p;

                break;

            default:

                break;

            }

            p += len;

        }

    }

    if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) {

        *preq_addr = &bp->bp_ciaddr;

    }

}


static void virtio_setup(uint64_t dev_info)

{

    struct schib schib;

    int i;

    int r;

    bool found = false;

    bool check_devno = false;

    uint16_t dev_no = -1;

    blk_schid.one = 1;

    if (dev_info != -1) {

        check_devno = true;

        dev_no = dev_info & 0xffff;

        debug_print_int("device no. ", dev_no);

        blk_schid.ssid = (dev_info >> 16) & 0x3;

        if (blk_schid.ssid != 0) {

            debug_print_int("ssid ", blk_schid.ssid);

            if (enable_mss_facility() != 0) {

                virtio_panic("Failed to enable mss facility\n");

            }

        }

    }

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

        blk_schid.sch_no = i;

        r = stsch_err(blk_schid, &schib);

        if (r == 3) {

            break;

        }

        if (schib.pmcw.dnv) {

            if (!check_devno || (schib.pmcw.dev == dev_no)) {

                if (virtio_is_blk(blk_schid)) {

                    found = true;

                    break;

                }

            }

        }

    }

    if (!found) {

        virtio_panic("No virtio-blk device found!\n");

    }

    virtio_setup_block(blk_schid);

}


void memory_region_init_ram(MemoryRegion *mr,

                            const char *name,

                            uint64_t size)

{

    memory_region_init(mr, name, size);

    mr->ram = true;

    mr->terminates = true;

    mr->destructor = memory_region_destructor_ram;

    mr->ram_addr = qemu_ram_alloc(size, mr);

    mr->backend_registered = true;

}


static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)

{

    TyphoonState *s = opaque;

    uint64_t ret = 0;

    if (addr & 4) {

        return s->latch_tmp;

    }

    switch (addr) {

    case 0x0000:

        /* WSBA0: Window Space Base Address Register.  */

        ret = s->pchip.win[0].base_addr;

        break;

    case 0x0040:

        /* WSBA1 */

        ret = s->pchip.win[1].base_addr;

        break;

    case 0x0080:

        /* WSBA2 */

        ret = s->pchip.win[2].base_addr;

        break;

    case 0x00c0:

        /* WSBA3 */

        ret = s->pchip.win[3].base_addr;

        break;

    case 0x0100:

        /* WSM0: Window Space Mask Register.  */

        ret = s->pchip.win[0].mask;

        break;

    case 0x0140:

        /* WSM1 */

        ret = s->pchip.win[1].mask;

        break;

    case 0x0180:

        /* WSM2 */

        ret = s->pchip.win[2].mask;

        break;

    case 0x01c0:

        /* WSM3 */

        ret = s->pchip.win[3].mask;

        break;

    case 0x0200:

        /* TBA0: Translated Base Address Register.  */

        ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;

        break;

    case 0x0240:

        /* TBA1 */

        ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;

        break;

    case 0x0280:

        /* TBA2 */

        ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;

        break;

    case 0x02c0:

        /* TBA3 */

        ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;

        break;

    case 0x0300:

        /* PCTL: Pchip Control Register.  */

        ret = s->pchip.ctl;

        break;

    case 0x0340:

        /* PLAT: Pchip Master Latency Register.  */

        break;

    case 0x03c0:

        /* PERROR: Pchip Error Register.  */

        break;

    case 0x0400:

        /* PERRMASK: Pchip Error Mask Register.  */

        break;

    case 0x0440:

        /* PERRSET: Pchip Error Set Register.  */

        break;

    case 0x0480:

        /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */

        break;

    case 0x04c0:

        /* TLBIA: Translation Buffer Invalidate All Register (WO).  */

        break;

    case 0x0500: /* PMONCTL */

    case 0x0540: /* PMONCNT */

    case 0x0800: /* SPRST */

        break;

    default:

        cpu_unassigned_access(current_cpu, addr, false, false, 0, size);

        return -1;

    }

    s->latch_tmp = ret >> 32;

    return ret;

}


void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7)

{

    int i;

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

        hw_breakpoint_remove(env, i);

    }

    env->dr[7] = new_dr7;

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

        hw_breakpoint_insert(env, i);

    }

}


int ffurl_get_file_handle(URLContext *h)

{

    if (!h->prot->url_get_file_handle)

        return -1;

    return h->prot->url_get_file_handle(h);

}


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

{

    int format, msf, start_track, len;

    uint64_t total_sectors = s->nb_sectors >> 2;

    int max_len;

    if (total_sectors == 0) {

        ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);

        return;

    }

    max_len = ube16_to_cpu(buf + 7);

    format = buf[9] >> 6;

    msf = (buf[1] >> 1) & 1;

    start_track = buf[6];

    switch(format) {

    case 0:

        len = cdrom_read_toc(total_sectors, buf, msf, start_track);

        if (len < 0)

            goto error_cmd;

        ide_atapi_cmd_reply(s, len, max_len);

        break;

    case 1:

        /* multi session : only a single session defined */

        memset(buf, 0, 12);

        buf[1] = 0x0a;

        buf[2] = 0x01;

        buf[3] = 0x01;

        ide_atapi_cmd_reply(s, 12, max_len);

        break;

    case 2:

        len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);

        if (len < 0)

            goto error_cmd;

        ide_atapi_cmd_reply(s, len, max_len);

        break;

    default:

    error_cmd:

        ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,

                            ASC_INV_FIELD_IN_CMD_PACKET);

    }

}


av_cold void ff_rv40dsp_init(RV34DSPContext *c, DSPContext* dsp) {

    ff_rv34dsp_init(c, dsp);

    c->put_pixels_tab[0][ 0] = dsp->put_h264_qpel_pixels_tab[0][0];

    c->put_pixels_tab[0][ 1] = put_rv40_qpel16_mc10_c;

    c->put_pixels_tab[0][ 2] = dsp->put_h264_qpel_pixels_tab[0][2];

    c->put_pixels_tab[0][ 3] = put_rv40_qpel16_mc30_c;

    c->put_pixels_tab[0][ 4] = put_rv40_qpel16_mc01_c;

    c->put_pixels_tab[0][ 5] = put_rv40_qpel16_mc11_c;

    c->put_pixels_tab[0][ 6] = put_rv40_qpel16_mc21_c;

    c->put_pixels_tab[0][ 7] = put_rv40_qpel16_mc31_c;

    c->put_pixels_tab[0][ 8] = dsp->put_h264_qpel_pixels_tab[0][8];

    c->put_pixels_tab[0][ 9] = put_rv40_qpel16_mc12_c;

    c->put_pixels_tab[0][10] = put_rv40_qpel16_mc22_c;

    c->put_pixels_tab[0][11] = put_rv40_qpel16_mc32_c;

    c->put_pixels_tab[0][12] = put_rv40_qpel16_mc03_c;

    c->put_pixels_tab[0][13] = put_rv40_qpel16_mc13_c;

    c->put_pixels_tab[0][14] = put_rv40_qpel16_mc23_c;

    c->put_pixels_tab[0][15] = ff_put_rv40_qpel16_mc33_c;

    c->avg_pixels_tab[0][ 0] = dsp->avg_h264_qpel_pixels_tab[0][0];

    c->avg_pixels_tab[0][ 1] = avg_rv40_qpel16_mc10_c;

    c->avg_pixels_tab[0][ 2] = dsp->avg_h264_qpel_pixels_tab[0][2];

    c->avg_pixels_tab[0][ 3] = avg_rv40_qpel16_mc30_c;

    c->avg_pixels_tab[0][ 4] = avg_rv40_qpel16_mc01_c;

    c->avg_pixels_tab[0][ 5] = avg_rv40_qpel16_mc11_c;

    c->avg_pixels_tab[0][ 6] = avg_rv40_qpel16_mc21_c;

    c->avg_pixels_tab[0][ 7] = avg_rv40_qpel16_mc31_c;

    c->avg_pixels_tab[0][ 8] = dsp->avg_h264_qpel_pixels_tab[0][8];

    c->avg_pixels_tab[0][ 9] = avg_rv40_qpel16_mc12_c;

    c->avg_pixels_tab[0][10] = avg_rv40_qpel16_mc22_c;

    c->avg_pixels_tab[0][11] = avg_rv40_qpel16_mc32_c;

    c->avg_pixels_tab[0][12] = avg_rv40_qpel16_mc03_c;

    c->avg_pixels_tab[0][13] = avg_rv40_qpel16_mc13_c;

    c->avg_pixels_tab[0][14] = avg_rv40_qpel16_mc23_c;

    c->avg_pixels_tab[0][15] = ff_avg_rv40_qpel16_mc33_c;

    c->put_pixels_tab[1][ 0] = dsp->put_h264_qpel_pixels_tab[1][0];

    c->put_pixels_tab[1][ 1] = put_rv40_qpel8_mc10_c;

    c->put_pixels_tab[1][ 2] = dsp->put_h264_qpel_pixels_tab[1][2];

    c->put_pixels_tab[1][ 3] = put_rv40_qpel8_mc30_c;

    c->put_pixels_tab[1][ 4] = put_rv40_qpel8_mc01_c;

    c->put_pixels_tab[1][ 5] = put_rv40_qpel8_mc11_c;

    c->put_pixels_tab[1][ 6] = put_rv40_qpel8_mc21_c;

    c->put_pixels_tab[1][ 7] = put_rv40_qpel8_mc31_c;

    c->put_pixels_tab[1][ 8] = dsp->put_h264_qpel_pixels_tab[1][8];

    c->put_pixels_tab[1][ 9] = put_rv40_qpel8_mc12_c;

    c->put_pixels_tab[1][10] = put_rv40_qpel8_mc22_c;

    c->put_pixels_tab[1][11] = put_rv40_qpel8_mc32_c;

    c->put_pixels_tab[1][12] = put_rv40_qpel8_mc03_c;

    c->put_pixels_tab[1][13] = put_rv40_qpel8_mc13_c;

    c->put_pixels_tab[1][14] = put_rv40_qpel8_mc23_c;

    c->put_pixels_tab[1][15] = ff_put_rv40_qpel8_mc33_c;

    c->avg_pixels_tab[1][ 0] = dsp->avg_h264_qpel_pixels_tab[1][0];

    c->avg_pixels_tab[1][ 1] = avg_rv40_qpel8_mc10_c;

    c->avg_pixels_tab[1][ 2] = dsp->avg_h264_qpel_pixels_tab[1][2];

    c->avg_pixels_tab[1][ 3] = avg_rv40_qpel8_mc30_c;

    c->avg_pixels_tab[1][ 4] = avg_rv40_qpel8_mc01_c;

    c->avg_pixels_tab[1][ 5] = avg_rv40_qpel8_mc11_c;

    c->avg_pixels_tab[1][ 6] = avg_rv40_qpel8_mc21_c;

    c->avg_pixels_tab[1][ 7] = avg_rv40_qpel8_mc31_c;

    c->avg_pixels_tab[1][ 8] = dsp->avg_h264_qpel_pixels_tab[1][8];

    c->avg_pixels_tab[1][ 9] = avg_rv40_qpel8_mc12_c;

    c->avg_pixels_tab[1][10] = avg_rv40_qpel8_mc22_c;

    c->avg_pixels_tab[1][11] = avg_rv40_qpel8_mc32_c;

    c->avg_pixels_tab[1][12] = avg_rv40_qpel8_mc03_c;

    c->avg_pixels_tab[1][13] = avg_rv40_qpel8_mc13_c;

    c->avg_pixels_tab[1][14] = avg_rv40_qpel8_mc23_c;

    c->avg_pixels_tab[1][15] = ff_avg_rv40_qpel8_mc33_c;

    c->put_chroma_pixels_tab[0] = put_rv40_chroma_mc8_c;

    c->put_chroma_pixels_tab[1] = put_rv40_chroma_mc4_c;

    c->avg_chroma_pixels_tab[0] = avg_rv40_chroma_mc8_c;

    c->avg_chroma_pixels_tab[1] = avg_rv40_chroma_mc4_c;

    c->rv40_weight_pixels_tab[0][0] = rv40_weight_func_rnd_16;

    c->rv40_weight_pixels_tab[0][1] = rv40_weight_func_rnd_8;

    c->rv40_weight_pixels_tab[1][0] = rv40_weight_func_nornd_16;

    c->rv40_weight_pixels_tab[1][1] = rv40_weight_func_nornd_8;

    c->rv40_weak_loop_filter[0]     = rv40_h_weak_loop_filter;

    c->rv40_weak_loop_filter[1]     = rv40_v_weak_loop_filter;

    c->rv40_strong_loop_filter[0]   = rv40_h_strong_loop_filter;

    c->rv40_strong_loop_filter[1]   = rv40_v_strong_loop_filter;

    c->rv40_loop_filter_strength[0] = rv40_h_loop_filter_strength;

    c->rv40_loop_filter_strength[1] = rv40_v_loop_filter_strength;

    if (ARCH_X86)

        ff_rv40dsp_init_x86(c, dsp);

    if (HAVE_NEON)

        ff_rv40dsp_init_neon(c, dsp);

}


static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)

{

    int i, consumed, ret = 0;

    s->ref = NULL;

    s->eos = 0;

    /* split the input packet into NAL units, so we know the upper bound on the

     * number of slices in the frame */

    s->nb_nals = 0;

    while (length >= 4) {

        HEVCNAL *nal;

        int extract_length = 0;

        if (s->is_nalff) {

            int i;

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

                extract_length = (extract_length << 8) | buf[i];

            buf    += s->nal_length_size;

            length -= s->nal_length_size;

            if (extract_length > length) {

                av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n");

                ret = AVERROR_INVALIDDATA;

                goto fail;

            }

        } else {

            if (buf[2] == 0) {

                length--;

                buf++;

                continue;

            }

            if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) {

                ret = AVERROR_INVALIDDATA;

                goto fail;

            }

            buf    += 3;

            length -= 3;

        }

        if (!s->is_nalff)

            extract_length = length;

        if (s->nals_allocated < s->nb_nals + 1) {

            int new_size = s->nals_allocated + 1;

            HEVCNAL *tmp = av_realloc_array(s->nals, new_size, sizeof(*tmp));

            if (!tmp) {

                ret = AVERROR(ENOMEM);

                goto fail;

            }

            s->nals = tmp;

            memset(s->nals + s->nals_allocated, 0, (new_size - s->nals_allocated) * sizeof(*tmp));

            av_reallocp_array(&s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal));

            av_reallocp_array(&s->skipped_bytes_pos_size_nal, new_size, sizeof(*s->skipped_bytes_pos_size_nal));

            av_reallocp_array(&s->skipped_bytes_pos_nal, new_size, sizeof(*s->skipped_bytes_pos_nal));

            s->skipped_bytes_pos_size_nal[s->nals_allocated] = 1024; // initial buffer size

            s->skipped_bytes_pos_nal[s->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[s->nals_allocated], sizeof(*s->skipped_bytes_pos));

            s->nals_allocated = new_size;

        }

        s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[s->nb_nals];

        s->skipped_bytes_pos = s->skipped_bytes_pos_nal[s->nb_nals];

        nal = &s->nals[s->nb_nals];

        consumed = extract_rbsp(s, buf, extract_length, nal);

        s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes;

        s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size;

        s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos;

        if (consumed < 0) {

            ret = consumed;

            goto fail;

        }

        ret = init_get_bits8(&s->HEVClc->gb, nal->data, nal->size);

        if (ret < 0)

            goto fail;

        hls_nal_unit(s);

        if (s->nal_unit_type == NAL_EOS_NUT || s->nal_unit_type == NAL_EOB_NUT)

            s->eos = 1;

        buf    += consumed;

        length -= consumed;

    }

    /* parse the NAL units */

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

        int ret;

        s->skipped_bytes = s->skipped_bytes_nal[i];

        s->skipped_bytes_pos = s->skipped_bytes_pos_nal[i];

        ret = decode_nal_unit(s, s->nals[i].data, s->nals[i].size);

        if (ret < 0) {

            av_log(s->avctx, AV_LOG_WARNING, "Error parsing NAL unit #%d.\n", i);

            if (s->avctx->err_recognition & AV_EF_EXPLODE)

                goto fail;

        }

    }

fail:

    if (s->ref && s->threads_type == FF_THREAD_FRAME)

        ff_thread_report_progress(&s->ref->tf, INT_MAX, 0);

    return ret;

}


static always_inline void gen_intermediate_code_internal (CPUState *env,

                                                          TranslationBlock *tb,

                                                          int search_pc)

{

    DisasContext ctx, *ctxp = &ctx;

    opc_handler_t **table, *handler;

    target_ulong pc_start;

    uint16_t *gen_opc_end;

    CPUBreakpoint *bp;

    int j, lj = -1;

    int num_insns;

    int max_insns;

    pc_start = tb->pc;

    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;

    ctx.nip = pc_start;

    ctx.tb = tb;

    ctx.exception = POWERPC_EXCP_NONE;

    ctx.spr_cb = env->spr_cb;

    ctx.mem_idx = env->mmu_idx;

    ctx.access_type = -1;

    ctx.le_mode = env->hflags & (1 << MSR_LE) ? 1 : 0;

#if defined(TARGET_PPC64)

    ctx.sf_mode = msr_sf;

#endif

    ctx.fpu_enabled = msr_fp;

    if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)

        ctx.spe_enabled = msr_spe;

    else

        ctx.spe_enabled = 0;

    if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)

        ctx.altivec_enabled = msr_vr;

    else

        ctx.altivec_enabled = 0;

    if ((env->flags & POWERPC_FLAG_SE) && msr_se)

        ctx.singlestep_enabled = CPU_SINGLE_STEP;

    else

        ctx.singlestep_enabled = 0;

    if ((env->flags & POWERPC_FLAG_BE) && msr_be)

        ctx.singlestep_enabled |= CPU_BRANCH_STEP;

    if (unlikely(env->singlestep_enabled))

        ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;

#if defined (DO_SINGLE_STEP) && 0

    /* Single step trace mode */

    msr_se = 1;

#endif

    num_insns = 0;

    max_insns = tb->cflags & CF_COUNT_MASK;

    if (max_insns == 0)

        max_insns = CF_COUNT_MASK;

    gen_icount_start();

    /* Set env in case of segfault during code fetch */

    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {

        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {

            TAILQ_FOREACH(bp, &env->breakpoints, entry) {

                if (bp->pc == ctx.nip) {

                    gen_debug_exception(ctxp);

                    break;

                }

            }

        }

        if (unlikely(search_pc)) {

            j = gen_opc_ptr - gen_opc_buf;

            if (lj < j) {

                lj++;

                while (lj < j)

                    gen_opc_instr_start[lj++] = 0;

                gen_opc_pc[lj] = ctx.nip;

                gen_opc_instr_start[lj] = 1;

                gen_opc_icount[lj] = num_insns;

            }

        }

        LOG_DISAS("----------------\n");

        LOG_DISAS("nip=" ADDRX " super=%d ir=%d\n",

                  ctx.nip, ctx.mem_idx, (int)msr_ir);

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

            gen_io_start();

        if (unlikely(ctx.le_mode)) {

            ctx.opcode = bswap32(ldl_code(ctx.nip));

        } else {

            ctx.opcode = ldl_code(ctx.nip);

        }

        LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",

                    ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),

                    opc3(ctx.opcode), little_endian ? "little" : "big");

        ctx.nip += 4;

        table = env->opcodes;

        num_insns++;

        handler = table[opc1(ctx.opcode)];

        if (is_indirect_opcode(handler)) {

            table = ind_table(handler);

            handler = table[opc2(ctx.opcode)];

            if (is_indirect_opcode(handler)) {

                table = ind_table(handler);

                handler = table[opc3(ctx.opcode)];

            }

        }

        /* Is opcode *REALLY* valid ? */

        if (unlikely(handler->handler == &gen_invalid)) {

            if (qemu_log_enabled()) {

                qemu_log("invalid/unsupported opcode: "

                          "%02x - %02x - %02x (%08x) " ADDRX " %d\n",

                          opc1(ctx.opcode), opc2(ctx.opcode),

                          opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);

            } else {

                printf("invalid/unsupported opcode: "

                       "%02x - %02x - %02x (%08x) " ADDRX " %d\n",

                       opc1(ctx.opcode), opc2(ctx.opcode),

                       opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);

            }

        } else {

            if (unlikely((ctx.opcode & handler->inval) != 0)) {

                if (qemu_log_enabled()) {

                    qemu_log("invalid bits: %08x for opcode: "

                              "%02x - %02x - %02x (%08x) " ADDRX "\n",

                              ctx.opcode & handler->inval, opc1(ctx.opcode),

                              opc2(ctx.opcode), opc3(ctx.opcode),

                              ctx.opcode, ctx.nip - 4);

                } else {

                    printf("invalid bits: %08x for opcode: "

                           "%02x - %02x - %02x (%08x) " ADDRX "\n",

                           ctx.opcode & handler->inval, opc1(ctx.opcode),

                           opc2(ctx.opcode), opc3(ctx.opcode),

                           ctx.opcode, ctx.nip - 4);

                }

                gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);

                break;

            }

        }

        (*(handler->handler))(&ctx);

#if defined(DO_PPC_STATISTICS)

        handler->count++;

#endif

        /* Check trace mode exceptions */

        if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&

                     (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&

                     ctx.exception != POWERPC_SYSCALL &&

                     ctx.exception != POWERPC_EXCP_TRAP &&

                     ctx.exception != POWERPC_EXCP_BRANCH)) {

            gen_exception(ctxp, POWERPC_EXCP_TRACE);

        } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||

                            (env->singlestep_enabled) ||

                            num_insns >= max_insns)) {

            /* if we reach a page boundary or are single stepping, stop

             * generation

             */

            break;

        }

#if defined (DO_SINGLE_STEP)

        break;

#endif

    }

    if (tb->cflags & CF_LAST_IO)

        gen_io_end();

    if (ctx.exception == POWERPC_EXCP_NONE) {

        gen_goto_tb(&ctx, 0, ctx.nip);

    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {

        if (unlikely(env->singlestep_enabled)) {

            gen_debug_exception(ctxp);

        }

        /* Generate the return instruction */

        tcg_gen_exit_tb(0);

    }

    gen_icount_end(tb, num_insns);

    *gen_opc_ptr = INDEX_op_end;

    if (unlikely(search_pc)) {

        j = gen_opc_ptr - gen_opc_buf;

        lj++;

        while (lj <= j)

            gen_opc_instr_start[lj++] = 0;

    } else {

        tb->size = ctx.nip - pc_start;

        tb->icount = num_insns;

    }

#if defined(DEBUG_DISAS)

    qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);

    log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);

    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {

        int flags;

        flags = env->bfd_mach;

        flags |= ctx.le_mode << 16;

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

        log_target_disas(pc_start, ctx.nip - pc_start, flags);

        qemu_log("\n");

    }

#endif

}


static int slb_lookup (CPUPPCState *env, target_ulong eaddr,

                       target_ulong *vsid, target_ulong *page_mask, int *attr)

{

    target_phys_addr_t sr_base;

    target_ulong mask;

    uint64_t tmp64;

    uint32_t tmp;

    int n, ret;

    int slb_nr;

    ret = -5;

    sr_base = env->spr[SPR_ASR];

#if defined(DEBUG_SLB)

    if (loglevel != 0) {

        fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",

                __func__, eaddr, sr_base);

    }

#endif

    mask = 0x0000000000000000ULL; /* Avoid gcc warning */

    slb_nr = env->slb_nr;

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

        tmp64 = ldq_phys(sr_base);

        tmp = ldl_phys(sr_base + 8);

#if defined(DEBUG_SLB)

        if (loglevel != 0) {

            fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"

                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);

        }

#endif

        if (tmp64 & 0x0000000008000000ULL) {

            /* SLB entry is valid */

            switch (tmp64 & 0x0000000006000000ULL) {

            case 0x0000000000000000ULL:

                /* 256 MB segment */

                mask = 0xFFFFFFFFF0000000ULL;

                break;

            case 0x0000000002000000ULL:

                /* 1 TB segment */

                mask = 0xFFFF000000000000ULL;

                break;

            case 0x0000000004000000ULL:

            case 0x0000000006000000ULL:

                /* Reserved => segment is invalid */

                continue;

            }

            if ((eaddr & mask) == (tmp64 & mask)) {

                /* SLB match */

                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;

                *page_mask = ~mask;

                *attr = tmp & 0xFF;

                ret = 0;

                break;

            }

        }

        sr_base += 12;

    }

    return ret;

}


static const mon_cmd_t *monitor_parse_command(Monitor *mon,

                                              const char *cmdline,

                                              QDict *qdict)

{

    const char *p, *typestr;

    int c;

    const mon_cmd_t *cmd;

    char cmdname[256];

    char buf[1024];

    char *key;

#ifdef DEBUG

    monitor_printf(mon, "command='%s'\n", cmdline);

#endif

    /* extract the command name */

    p = get_command_name(cmdline, cmdname, sizeof(cmdname));

    if (!p)

        return NULL;

    /* find the command */

    for(cmd = mon_cmds; cmd->name != NULL; cmd++) {

        if (compare_cmd(cmdname, cmd->name))

            break;

    }

    if (cmd->name == NULL) {

        monitor_printf(mon, "unknown command: '%s'\n", cmdname);

        return NULL;

    }

    /* parse the parameters */

    typestr = cmd->args_type;

    for(;;) {

        typestr = key_get_info(typestr, &key);

        if (!typestr)

            break;

        c = *typestr;

        typestr++;

        switch(c) {

        case 'F':

        case 'B':

        case 's':

            {

                int ret;

                while (qemu_isspace(*p))

                    p++;

                if (*typestr == '?') {

                    typestr++;

                    if (*p == '\0') {

                        /* no optional string: NULL argument */

                        break;

                    }

                }

                ret = get_str(buf, sizeof(buf), &p);

                if (ret < 0) {

                    switch(c) {

                    case 'F':

                        monitor_printf(mon, "%s: filename expected\n",

                                       cmdname);

                        break;

                    case 'B':

                        monitor_printf(mon, "%s: block device name expected\n",

                                       cmdname);

                        break;

                    default:

                        monitor_printf(mon, "%s: string expected\n", cmdname);

                        break;

                    }

                    goto fail;

                }

                qdict_put(qdict, key, qstring_from_str(buf));

            }

            break;

        case '/':

            {

                int count, format, size;

                while (qemu_isspace(*p))

                    p++;

                if (*p == '/') {

                    /* format found */

                    p++;

                    count = 1;

                    if (qemu_isdigit(*p)) {

                        count = 0;

                        while (qemu_isdigit(*p)) {

                            count = count * 10 + (*p - '0');

                            p++;

                        }

                    }

                    size = -1;

                    format = -1;

                    for(;;) {

                        switch(*p) {

                        case 'o':

                        case 'd':

                        case 'u':

                        case 'x':

                        case 'i':

                        case 'c':

                            format = *p++;

                            break;

                        case 'b':

                            size = 1;

                            p++;

                            break;

                        case 'h':

                            size = 2;

                            p++;

                            break;

                        case 'w':

                            size = 4;

                            p++;

                            break;

                        case 'g':

                        case 'L':

                            size = 8;

                            p++;

                            break;

                        default:

                            goto next;

                        }

                    }

                next:

                    if (*p != '\0' && !qemu_isspace(*p)) {

                        monitor_printf(mon, "invalid char in format: '%c'\n",

                                       *p);

                        goto fail;

                    }

                    if (format < 0)

                        format = default_fmt_format;

                    if (format != 'i') {

                        /* for 'i', not specifying a size gives -1 as size */

                        if (size < 0)

                            size = default_fmt_size;

                        default_fmt_size = size;

                    }

                    default_fmt_format = format;

                } else {

                    count = 1;

                    format = default_fmt_format;

                    if (format != 'i') {

                        size = default_fmt_size;

                    } else {

                        size = -1;

                    }

                }

                qdict_put(qdict, "count", qint_from_int(count));

                qdict_put(qdict, "format", qint_from_int(format));

                qdict_put(qdict, "size", qint_from_int(size));

            }

            break;

        case 'i':

        case 'l':

            {

                int64_t val;

                while (qemu_isspace(*p))

                    p++;

                if (*typestr == '?' || *typestr == '.') {

                    if (*typestr == '?') {

                        if (*p == '\0') {

                            typestr++;

                            break;

                        }

                    } else {

                        if (*p == '.') {

                            p++;

                            while (qemu_isspace(*p))

                                p++;

                        } else {

                            typestr++;

                            break;

                        }

                    }

                    typestr++;

                }

                if (get_expr(mon, &val, &p))

                    goto fail;

                /* Check if 'i' is greater than 32-bit */

                if ((c == 'i') && ((val >> 32) & 0xffffffff)) {

                    monitor_printf(mon, "\'%s\' has failed: ", cmdname);

                    monitor_printf(mon, "integer is for 32-bit values\n");

                    goto fail;

                }

                qdict_put(qdict, key, qint_from_int(val));

            }

            break;

        case '-':

            {

                const char *tmp = p;

                int has_option, skip_key = 0;

                /* option */

                c = *typestr++;

                if (c == '\0')

                    goto bad_type;

                while (qemu_isspace(*p))

                    p++;

                has_option = 0;

                if (*p == '-') {

                    p++;

                    if(c != *p) {

                        if(!is_valid_option(p, typestr)) {

                            monitor_printf(mon, "%s: unsupported option -%c\n",

                                           cmdname, *p);

                            goto fail;

                        } else {

                            skip_key = 1;

                        }

                    }

                    if(skip_key) {

                        p = tmp;

                    } else {

                        p++;

                        has_option = 1;

                    }

                }

                qdict_put(qdict, key, qint_from_int(has_option));

            }

            break;

        default:

        bad_type:

            monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);

            goto fail;

        }

        qemu_free(key);

        key = NULL;

    }

    /* check that all arguments were parsed */

    while (qemu_isspace(*p))

        p++;

    if (*p != '\0') {

        monitor_printf(mon, "%s: extraneous characters at the end of line\n",

                       cmdname);

        goto fail;

    }

    return cmd;

fail:

    qemu_free(key);

    return NULL;

}


static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,

                          int nb_sectors, QEMUIOVector *qiov)

{

    BDRVQcowState *s = bs->opaque;

    int index_in_cluster;

    uint64_t cluster_offset;

    int ret = 0, n;

    struct iovec hd_iov;

    QEMUIOVector hd_qiov;

    uint8_t *buf;

    void *orig_buf;

    s->cluster_cache_offset = -1; /* disable compressed cache */

    /* We must always copy the iov when encrypting, so we

     * don't modify the original data buffer during encryption */

    if (bs->encrypted || qiov->niov > 1) {

        buf = orig_buf = qemu_try_blockalign(bs, qiov->size);

        if (buf == NULL) {

            return -ENOMEM;

        }

        qemu_iovec_to_buf(qiov, 0, buf, qiov->size);

    } else {

        orig_buf = NULL;

        buf = (uint8_t *)qiov->iov->iov_base;

    }

    qemu_co_mutex_lock(&s->lock);

    while (nb_sectors != 0) {

        index_in_cluster = sector_num & (s->cluster_sectors - 1);

        n = s->cluster_sectors - index_in_cluster;

        if (n > nb_sectors) {

            n = nb_sectors;

        }

        cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,

                                            index_in_cluster,

                                            index_in_cluster + n);

        if (!cluster_offset || (cluster_offset & 511) != 0) {

            ret = -EIO;

            break;

        }

        if (bs->encrypted) {

            Error *err = NULL;

            assert(s->cipher);

            if (encrypt_sectors(s, sector_num, buf, n, true, &err) < 0) {

                error_free(err);

                ret = -EIO;

                break;

            }

        }

        hd_iov.iov_base = (void *)buf;

        hd_iov.iov_len = n * 512;

        qemu_iovec_init_external(&hd_qiov, &hd_iov, 1);

        qemu_co_mutex_unlock(&s->lock);

        ret = bdrv_co_writev(bs->file,

                             (cluster_offset >> 9) + index_in_cluster,

                             n, &hd_qiov);

        qemu_co_mutex_lock(&s->lock);

        if (ret < 0) {

            break;

        }

        ret = 0;

        nb_sectors -= n;

        sector_num += n;

        buf += n * 512;

    }

    qemu_co_mutex_unlock(&s->lock);

    qemu_vfree(orig_buf);

    return ret;

}


static void start_auth_vencrypt_subauth(VncState *vs)

{

    switch (vs->vd->subauth) {

    case VNC_AUTH_VENCRYPT_TLSNONE:

    case VNC_AUTH_VENCRYPT_X509NONE:

       VNC_DEBUG("Accept TLS auth none\n");

       vnc_write_u32(vs, 0); /* Accept auth completion */

       start_client_init(vs);

       break;

    case VNC_AUTH_VENCRYPT_TLSVNC:

    case VNC_AUTH_VENCRYPT_X509VNC:

       VNC_DEBUG("Start TLS auth VNC\n");

       start_auth_vnc(vs);

       break;

#ifdef CONFIG_VNC_SASL

    case VNC_AUTH_VENCRYPT_TLSSASL:

    case VNC_AUTH_VENCRYPT_X509SASL:

      VNC_DEBUG("Start TLS auth SASL\n");

      return start_auth_sasl(vs);

#endif /* CONFIG_VNC_SASL */

    default: /* Should not be possible, but just in case */

       VNC_DEBUG("Reject subauth %d server bug\n", vs->vd->auth);

       vnc_write_u8(vs, 1);

       if (vs->minor >= 8) {

           static const char err[] = "Unsupported authentication type";

           vnc_write_u32(vs, sizeof(err));

           vnc_write(vs, err, sizeof(err));

       }

       vnc_client_error(vs);

    }

}


static void disas_test_b_imm(DisasContext *s, uint32_t insn)

{

    unsigned int bit_pos, op, rt;

    uint64_t addr;

    int label_match;

    TCGv_i64 tcg_cmp;

    bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);

    op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */

    addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;

    rt = extract32(insn, 0, 5);

    tcg_cmp = tcg_temp_new_i64();

    tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));

    label_match = gen_new_label();

    tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,

                        tcg_cmp, 0, label_match);

    tcg_temp_free_i64(tcg_cmp);

    gen_goto_tb(s, 0, s->pc);

    gen_set_label(label_match);

    gen_goto_tb(s, 1, addr);

}


static QObject *parse_escape(JSONParserContext *ctxt, QList **tokens, va_list *ap)

{

    QObject *token = NULL, *obj;

    QList *working = qlist_copy(*tokens);

    if (ap == NULL) {

        goto out;

    }

    token = qlist_pop(working);

    if (token == NULL) {

        goto out;

    }

    if (token_is_escape(token, "%p")) {

        obj = va_arg(*ap, QObject *);

    } else if (token_is_escape(token, "%i")) {

        obj = QOBJECT(qbool_from_int(va_arg(*ap, int)));

    } else if (token_is_escape(token, "%d")) {

        obj = QOBJECT(qint_from_int(va_arg(*ap, int)));

    } else if (token_is_escape(token, "%ld")) {

        obj = QOBJECT(qint_from_int(va_arg(*ap, long)));

    } else if (token_is_escape(token, "%lld") ||

               token_is_escape(token, "%I64d")) {

        obj = QOBJECT(qint_from_int(va_arg(*ap, long long)));

    } else if (token_is_escape(token, "%s")) {

        obj = QOBJECT(qstring_from_str(va_arg(*ap, const char *)));

    } else if (token_is_escape(token, "%f")) {

        obj = QOBJECT(qfloat_from_double(va_arg(*ap, double)));

    } else {

        goto out;

    }

    qobject_decref(token);

    QDECREF(*tokens);

    *tokens = working;

    return obj;

out:

    qobject_decref(token);

    QDECREF(working);

    return NULL;

}


ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, CharDriverState *chr)

{

    ParallelState *s;

    int io_sw;

    s = qemu_mallocz(sizeof(ParallelState));

    s->irq = irq;

    s->chr = chr;

    s->it_shift = it_shift;

    qemu_register_reset(parallel_reset, s);

    io_sw = cpu_register_io_memory(parallel_mm_read_sw, parallel_mm_write_sw,

                                   s, DEVICE_NATIVE_ENDIAN);

    cpu_register_physical_memory(base, 8 << it_shift, io_sw);

    return s;

}


int float32_le( float32 a, float32 b STATUS_PARAM )

{

    flag aSign, bSign;

    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )

         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )

       ) {

        float_raise( float_flag_invalid STATUS_VAR);

        return 0;

    }

    aSign = extractFloat32Sign( a );

    bSign = extractFloat32Sign( b );

    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );

    return ( a == b ) || ( aSign ^ ( a < b ) );

}


static void ttafilter_init(TTAContext *s, TTAFilter *c, int32_t shift) {

    memset(c, 0, sizeof(TTAFilter));

    if (s->pass) {

        int i;

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

            c->qm[i] = sign_extend(s->crc_pass[i], 8);

    }

    c->shift = shift;

   c->round = shift_1[shift-1];

//    c->round = 1 << (shift - 1);

}


USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)

{

    MSDState *s;

    BlockDriverState *bdrv;

    BlockDriver *drv = NULL;

    const char *p1;

    char fmt[32];

    p1 = strchr(filename, ':');

    if (p1++) {

        const char *p2;

        if (strstart(filename, "format=", &p2)) {

            int len = MIN(p1 - p2, sizeof(fmt));

            pstrcpy(fmt, len, p2);

            drv = bdrv_find_format(fmt);

            if (!drv) {

                printf("invalid format %s\n", fmt);

                return NULL;

            }

        } else if (*filename != ':') {

            printf("unrecognized USB mass-storage option %s\n", filename);

            return NULL;

        }

        filename = p1;

    }

    if (!*filename) {

        printf("block device specification needed\n");

        return NULL;

    }

    s = qemu_mallocz(sizeof(MSDState));

    bdrv = bdrv_new("usb");

    if (bdrv_open2(bdrv, filename, 0, drv) < 0)

        goto fail;

    s->bs = bdrv;

    *pbs = bdrv;

    s->dev.speed = USB_SPEED_FULL;

    s->dev.handle_packet = usb_generic_handle_packet;

    s->dev.handle_reset = usb_msd_handle_reset;

    s->dev.handle_control = usb_msd_handle_control;

    s->dev.handle_data = usb_msd_handle_data;

    s->dev.handle_destroy = usb_msd_handle_destroy;

    snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",

             filename);

    s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);

    usb_msd_handle_reset((USBDevice *)s);

    return (USBDevice *)s;

 fail:

    qemu_free(s);

    return NULL;

}


static int buffered_rate_limit(void *opaque)

{

    QEMUFileBuffered *s = opaque;

    int ret;

    ret = qemu_file_get_error(s->file);

    if (ret) {

        return ret;

    }

    if (s->bytes_xfer > s->xfer_limit)

        return 1;

    return 0;

}


static int alloc_refcount_block(BlockDriverState *bs,

                                int64_t cluster_index, void **refcount_block)

{

    BDRVQcowState *s = bs->opaque;

    unsigned int refcount_table_index;

    int ret;

    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC);

    /* Find the refcount block for the given cluster */

    refcount_table_index = cluster_index >> s->refcount_block_bits;

    if (refcount_table_index < s->refcount_table_size) {

        uint64_t refcount_block_offset =

            s->refcount_table[refcount_table_index] & REFT_OFFSET_MASK;

        /* If it's already there, we're done */

        if (refcount_block_offset) {

            if (offset_into_cluster(s, refcount_block_offset)) {

                qcow2_signal_corruption(bs, true, -1, -1, "Refblock offset %#"

                                        PRIx64 " unaligned (reftable index: "

                                        "%#x)", refcount_block_offset,

                                        refcount_table_index);

                return -EIO;

            }

             return load_refcount_block(bs, refcount_block_offset,

                                        refcount_block);

        }

    }

    /*

     * If we came here, we need to allocate something. Something is at least

     * a cluster for the new refcount block. It may also include a new refcount

     * table if the old refcount table is too small.

     *

     * Note that allocating clusters here needs some special care:

     *

     * - We can't use the normal qcow2_alloc_clusters(), it would try to

     *   increase the refcount and very likely we would end up with an endless

     *   recursion. Instead we must place the refcount blocks in a way that

     *   they can describe them themselves.

     *

     * - We need to consider that at this point we are inside update_refcounts

     *   and potentially doing an initial refcount increase. This means that

     *   some clusters have already been allocated by the caller, but their

     *   refcount isn't accurate yet. If we allocate clusters for metadata, we

     *   need to return -EAGAIN to signal the caller that it needs to restart

     *   the search for free clusters.

     *

     * - alloc_clusters_noref and qcow2_free_clusters may load a different

     *   refcount block into the cache

     */

    *refcount_block = NULL;

    /* We write to the refcount table, so we might depend on L2 tables */

    ret = qcow2_cache_flush(bs, s->l2_table_cache);

    if (ret < 0) {

        return ret;

    }

    /* Allocate the refcount block itself and mark it as used */

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

    if (new_block < 0) {

        return new_block;

    }

#ifdef DEBUG_ALLOC2

    fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64

        " at %" PRIx64 "\n",

        refcount_table_index, cluster_index << s->cluster_bits, new_block);

#endif

    if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) {

        /* Zero the new refcount block before updating it */

        ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block,

                                    refcount_block);

        if (ret < 0) {

            goto fail_block;

        }

        memset(*refcount_block, 0, s->cluster_size);

        /* The block describes itself, need to update the cache */

        int block_index = (new_block >> s->cluster_bits) &

            (s->refcount_block_size - 1);

        s->set_refcount(*refcount_block, block_index, 1);

    } else {

        /* Described somewhere else. This can recurse at most twice before we

         * arrive at a block that describes itself. */

        ret = update_refcount(bs, new_block, s->cluster_size, 1, false,

                              QCOW2_DISCARD_NEVER);

        if (ret < 0) {

            goto fail_block;

        }

        ret = qcow2_cache_flush(bs, s->refcount_block_cache);

        if (ret < 0) {

            goto fail_block;

        }

        /* Initialize the new refcount block only after updating its refcount,

         * update_refcount uses the refcount cache itself */

        ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block,

                                    refcount_block);

        if (ret < 0) {

            goto fail_block;

        }

        memset(*refcount_block, 0, s->cluster_size);

    }

    /* Now the new refcount block needs to be written to disk */

    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE);

    qcow2_cache_entry_mark_dirty(bs, s->refcount_block_cache, *refcount_block);

    ret = qcow2_cache_flush(bs, s->refcount_block_cache);

    if (ret < 0) {

        goto fail_block;

    }

    /* If the refcount table is big enough, just hook the block up there */

    if (refcount_table_index < s->refcount_table_size) {

        uint64_t data64 = cpu_to_be64(new_block);

        BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP);

        ret = bdrv_pwrite_sync(bs->file,

            s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),

            &data64, sizeof(data64));

        if (ret < 0) {

            goto fail_block;

        }

        s->refcount_table[refcount_table_index] = new_block;

        /* The new refcount block may be where the caller intended to put its

         * data, so let it restart the search. */

        return -EAGAIN;

    }

    ret = qcow2_cache_put(bs, s->refcount_block_cache, refcount_block);

    if (ret < 0) {

        goto fail_block;

    }

    /*

     * If we come here, we need to grow the refcount table. Again, a new

     * refcount table needs some space and we can't simply allocate to avoid

     * endless recursion.

     *

     * Therefore let's grab new refcount blocks at the end of the image, which

     * will describe themselves and the new refcount table. This way we can

     * reference them only in the new table and do the switch to the new

     * refcount table at once without producing an inconsistent state in

     * between.

     */

    BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW);

    /* Calculate the number of refcount blocks needed so far; this will be the

     * basis for calculating the index of the first cluster used for the

     * self-describing refcount structures which we are about to create.

     *

     * Because we reached this point, there cannot be any refcount entries for

     * cluster_index or higher indices yet. However, because new_block has been

     * allocated to describe that cluster (and it will assume this role later

     * on), we cannot use that index; also, new_block may actually have a higher

     * cluster index than cluster_index, so it needs to be taken into account

     * here (and 1 needs to be added to its value because that cluster is used).

     */

    uint64_t blocks_used = DIV_ROUND_UP(MAX(cluster_index + 1,

                                            (new_block >> s->cluster_bits) + 1),

                                        s->refcount_block_size);

    if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) {

        return -EFBIG;

    }

    /* And now we need at least one block more for the new metadata */

    uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);

    uint64_t last_table_size;

    uint64_t blocks_clusters;

    do {

        uint64_t table_clusters =

            size_to_clusters(s, table_size * sizeof(uint64_t));

        blocks_clusters = 1 +

            ((table_clusters + s->refcount_block_size - 1)

            / s->refcount_block_size);

        uint64_t meta_clusters = table_clusters + blocks_clusters;

        last_table_size = table_size;

        table_size = next_refcount_table_size(s, blocks_used +

            ((meta_clusters + s->refcount_block_size - 1)

            / s->refcount_block_size));

    } while (last_table_size != table_size);

#ifdef DEBUG_ALLOC2

    fprintf(stderr, "qcow2: Grow refcount table %" PRId32 " => %" PRId64 "\n",

        s->refcount_table_size, table_size);

#endif

    /* Create the new refcount table and blocks */

    uint64_t meta_offset = (blocks_used * s->refcount_block_size) *

        s->cluster_size;

    uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size;

    uint64_t *new_table = g_try_new0(uint64_t, table_size);

    void *new_blocks = g_try_malloc0(blocks_clusters * s->cluster_size);

    assert(table_size > 0 && blocks_clusters > 0);

    if (new_table == NULL || new_blocks == NULL) {

        ret = -ENOMEM;

        goto fail_table;

    }

    /* Fill the new refcount table */

    memcpy(new_table, s->refcount_table,

        s->refcount_table_size * sizeof(uint64_t));

    new_table[refcount_table_index] = new_block;

    int i;

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

        new_table[blocks_used + i] = meta_offset + (i * s->cluster_size);

    }

    /* Fill the refcount blocks */

    uint64_t table_clusters = size_to_clusters(s, table_size * sizeof(uint64_t));

    int block = 0;

    for (i = 0; i < table_clusters + blocks_clusters; i++) {

        s->set_refcount(new_blocks, block++, 1);

    }

    /* Write refcount blocks to disk */

    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);

    ret = bdrv_pwrite_sync(bs->file, meta_offset, new_blocks,

        blocks_clusters * s->cluster_size);

    g_free(new_blocks);

    new_blocks = NULL;

    if (ret < 0) {

        goto fail_table;

    }

    /* Write refcount table to disk */

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

        cpu_to_be64s(&new_table[i]);

    }

    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);

    ret = bdrv_pwrite_sync(bs->file, table_offset, new_table,

        table_size * sizeof(uint64_t));

    if (ret < 0) {

        goto fail_table;

    }

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

        be64_to_cpus(&new_table[i]);

    }

    /* Hook up the new refcount table in the qcow2 header */

    uint8_t data[12];

    cpu_to_be64w((uint64_t*)data, table_offset);

    cpu_to_be32w((uint32_t*)(data + 8), table_clusters);

    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);

    ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, refcount_table_offset),

        data, sizeof(data));

    if (ret < 0) {

        goto fail_table;

    }

    /* And switch it in memory */

    uint64_t old_table_offset = s->refcount_table_offset;

    uint64_t old_table_size = s->refcount_table_size;

    g_free(s->refcount_table);

    s->refcount_table = new_table;

    s->refcount_table_size = table_size;

    s->refcount_table_offset = table_offset;

    /* Free old table. */

    qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t),

                        QCOW2_DISCARD_OTHER);

    ret = load_refcount_block(bs, new_block, refcount_block);

    if (ret < 0) {

        return ret;

    }

    /* If we were trying to do the initial refcount update for some cluster

     * allocation, we might have used the same clusters to store newly

     * allocated metadata. Make the caller search some new space. */

    return -EAGAIN;

fail_table:

    g_free(new_blocks);

    g_free(new_table);

fail_block:

    if (*refcount_block != NULL) {

        qcow2_cache_put(bs, s->refcount_block_cache, refcount_block);

    }

    return ret;

}


static inline int vc1_pred_dc(MpegEncContext *s, int overlap, int pq, int n,

                              int a_avail, int c_avail,

                              int16_t **dc_val_ptr, int *dir_ptr)

{

    int a, b, c, wrap, pred;

    int16_t *dc_val;

    int mb_pos = s->mb_x + s->mb_y * s->mb_stride;

    int q1, q2 = 0;

    wrap = s->block_wrap[n];

    dc_val = s->dc_val[0] + s->block_index[n];

    /* B A

     * C X

     */

    c = dc_val[ - 1];

    b = dc_val[ - 1 - wrap];

    a = dc_val[ - wrap];

    /* scale predictors if needed */

    q1 = s->current_picture.f.qscale_table[mb_pos];

    if (c_avail && (n != 1 && n != 3)) {

        q2 = s->current_picture.f.qscale_table[mb_pos - 1];

        if (q2 && q2 != q1)

            c = (c * s->y_dc_scale_table[q2] * ff_vc1_dqscale[s->y_dc_scale_table[q1] - 1] + 0x20000) >> 18;

    }

    if (a_avail && (n != 2 && n != 3)) {

        q2 = s->current_picture.f.qscale_table[mb_pos - s->mb_stride];

        if (q2 && q2 != q1)

            a = (a * s->y_dc_scale_table[q2] * ff_vc1_dqscale[s->y_dc_scale_table[q1] - 1] + 0x20000) >> 18;

    }

    if (a_avail && c_avail && (n != 3)) {

        int off = mb_pos;

        if (n != 1)

            off--;

        if (n != 2)

            off -= s->mb_stride;

        q2 = s->current_picture.f.qscale_table[off];

        if (q2 && q2 != q1)

            b = (b * s->y_dc_scale_table[q2] * ff_vc1_dqscale[s->y_dc_scale_table[q1] - 1] + 0x20000) >> 18;

    }

    if (a_avail && c_avail) {

        if (abs(a - b) <= abs(b - c)) {

            pred     = c;

            *dir_ptr = 1; // left

        } else {

            pred     = a;

            *dir_ptr = 0; // top

        }

    } else if (a_avail) {

        pred     = a;

        *dir_ptr = 0; // top

    } else if (c_avail) {

        pred     = c;

        *dir_ptr = 1; // left

    } else {

        pred     = 0;

        *dir_ptr = 1; // left

    }

    /* update predictor */

    *dc_val_ptr = &dc_val[0];

    return pred;

}


static void external_snapshot_prepare(BlkTransactionState *common,

                                      Error **errp)

{

    BlockDriver *drv;

    int flags, ret;

    QDict *options = NULL;

    Error *local_err = NULL;

    bool has_device = false;

    const char *device;

    bool has_node_name = false;

    const char *node_name;

    bool has_snapshot_node_name = false;

    const char *snapshot_node_name;

    const char *new_image_file;

    const char *format = "qcow2";

    enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;

    ExternalSnapshotState *state =

                             DO_UPCAST(ExternalSnapshotState, common, common);

    TransactionAction *action = common->action;

    /* get parameters */

    g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC);

    has_device = action->blockdev_snapshot_sync->has_device;

    device = action->blockdev_snapshot_sync->device;

    has_node_name = action->blockdev_snapshot_sync->has_node_name;

    node_name = action->blockdev_snapshot_sync->node_name;

    has_snapshot_node_name =

        action->blockdev_snapshot_sync->has_snapshot_node_name;

    snapshot_node_name = action->blockdev_snapshot_sync->snapshot_node_name;

    new_image_file = action->blockdev_snapshot_sync->snapshot_file;

    if (action->blockdev_snapshot_sync->has_format) {

        format = action->blockdev_snapshot_sync->format;

    }

    if (action->blockdev_snapshot_sync->has_mode) {

        mode = action->blockdev_snapshot_sync->mode;

    }

    /* start processing */

    drv = bdrv_find_format(format);

    if (!drv) {

        error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);

        return;

    }

    state->old_bs = bdrv_lookup_bs(has_device ? device : NULL,

                                   has_node_name ? node_name : NULL,

                                   &local_err);

    if (error_is_set(&local_err)) {

        error_propagate(errp, local_err);

        return;

    }

    if (has_node_name && !has_snapshot_node_name) {

        error_setg(errp, "New snapshot node name missing");

        return;

    }

    if (has_snapshot_node_name && bdrv_find_node(snapshot_node_name)) {

        error_setg(errp, "New snapshot node name already existing");

        return;

    }

    if (!bdrv_is_inserted(state->old_bs)) {

        error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);

        return;

    }

    if (bdrv_in_use(state->old_bs)) {

        error_set(errp, QERR_DEVICE_IN_USE, device);

        return;

    }

    if (!bdrv_is_read_only(state->old_bs)) {

        if (bdrv_flush(state->old_bs)) {

            error_set(errp, QERR_IO_ERROR);

            return;

        }

    }

    if (!bdrv_is_first_non_filter(state->old_bs)) {

        error_set(errp, QERR_FEATURE_DISABLED, "snapshot");

        return;

    }

    flags = state->old_bs->open_flags;

    /* create new image w/backing file */

    if (mode != NEW_IMAGE_MODE_EXISTING) {

        bdrv_img_create(new_image_file, format,

                        state->old_bs->filename,

                        state->old_bs->drv->format_name,

                        NULL, -1, flags, &local_err, false);

        if (error_is_set(&local_err)) {

            error_propagate(errp, local_err);

            return;

        }

    }

    if (has_snapshot_node_name) {

        options = qdict_new();

        qdict_put(options, "node-name",

                  qstring_from_str(snapshot_node_name));

    }

    /* We will manually add the backing_hd field to the bs later */

    state->new_bs = bdrv_new("");

    /* TODO Inherit bs->options or only take explicit options with an

     * extended QMP command? */

    ret = bdrv_open(state->new_bs, new_image_file, options,

                    flags | BDRV_O_NO_BACKING, drv, &local_err);

    if (ret != 0) {

        error_propagate(errp, local_err);

    }

    QDECREF(options);

}


int avio_get_str(AVIOContext *s, int maxlen, char *buf, int buflen)

{

    int i;

    // reserve 1 byte for terminating 0

    buflen = FFMIN(buflen - 1, maxlen);

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

        if (!(buf[i] = avio_r8(s)))

            return i + 1;

    if (buflen)

        buf[i] = 0;

    for (; i < maxlen; i++)

        if (!avio_r8(s))

            return i + 1;

    return maxlen;

}


static int RENAME(swScale)(SwsContext *c, const uint8_t* src[], int srcStride[], int srcSliceY,

                           int srcSliceH, uint8_t* dst[], int dstStride[])

{

    /* load a few things into local vars to make the code more readable? and faster */

    const int srcW= c->srcW;

    const int dstW= c->dstW;

    const int dstH= c->dstH;

    const int chrDstW= c->chrDstW;

    const int chrSrcW= c->chrSrcW;

    const int lumXInc= c->lumXInc;

    const int chrXInc= c->chrXInc;

    const enum PixelFormat dstFormat= c->dstFormat;

    const int flags= c->flags;

    int16_t *vLumFilterPos= c->vLumFilterPos;

    int16_t *vChrFilterPos= c->vChrFilterPos;

    int16_t *hLumFilterPos= c->hLumFilterPos;

    int16_t *hChrFilterPos= c->hChrFilterPos;

    int16_t *vLumFilter= c->vLumFilter;

    int16_t *vChrFilter= c->vChrFilter;

    int16_t *hLumFilter= c->hLumFilter;

    int16_t *hChrFilter= c->hChrFilter;

    int32_t *lumMmxFilter= c->lumMmxFilter;

    int32_t *chrMmxFilter= c->chrMmxFilter;

    int32_t av_unused *alpMmxFilter= c->alpMmxFilter;

    const int vLumFilterSize= c->vLumFilterSize;

    const int vChrFilterSize= c->vChrFilterSize;

    const int hLumFilterSize= c->hLumFilterSize;

    const int hChrFilterSize= c->hChrFilterSize;

    int16_t **lumPixBuf= c->lumPixBuf;

    int16_t **chrPixBuf= c->chrPixBuf;

    int16_t **alpPixBuf= c->alpPixBuf;

    const int vLumBufSize= c->vLumBufSize;

    const int vChrBufSize= c->vChrBufSize;

    uint8_t *formatConvBuffer= c->formatConvBuffer;

    const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;

    const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);

    int lastDstY;

    uint32_t *pal=c->pal_yuv;

    /* vars which will change and which we need to store back in the context */

    int dstY= c->dstY;

    int lumBufIndex= c->lumBufIndex;

    int chrBufIndex= c->chrBufIndex;

    int lastInLumBuf= c->lastInLumBuf;

    int lastInChrBuf= c->lastInChrBuf;

    if (isPacked(c->srcFormat)) {

        src[0]=

        src[1]=

        src[2]=

        src[3]= src[0];

        srcStride[0]=

        srcStride[1]=

        srcStride[2]=

        srcStride[3]= srcStride[0];

    }

    srcStride[1]<<= c->vChrDrop;

    srcStride[2]<<= c->vChrDrop;

    DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",

                  src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],

                  dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);

    DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",

                   srcSliceY,    srcSliceH,    dstY,    dstH);

    DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",

                   vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);

    if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {

        static int warnedAlready=0; //FIXME move this into the context perhaps

        if (flags & SWS_PRINT_INFO && !warnedAlready) {

            av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"

                   "         ->cannot do aligned memory accesses anymore\n");

            warnedAlready=1;

        }

    }

    /* Note the user might start scaling the picture in the middle so this

       will not get executed. This is not really intended but works

       currently, so people might do it. */

    if (srcSliceY ==0) {

        lumBufIndex=-1;

        chrBufIndex=-1;

        dstY=0;

        lastInLumBuf= -1;

        lastInChrBuf= -1;

    }

    lastDstY= dstY;

    for (;dstY < dstH; dstY++) {

        unsigned char *dest =dst[0]+dstStride[0]*dstY;

        const int chrDstY= dstY>>c->chrDstVSubSample;

        unsigned char *uDest=dst[1]+dstStride[1]*chrDstY;

        unsigned char *vDest=dst[2]+dstStride[2]*chrDstY;

        unsigned char *aDest=(CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3]+dstStride[3]*dstY : NULL;

        const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input

        const int firstLumSrcY2= vLumFilterPos[FFMIN(dstY | ((1<<c->chrDstVSubSample) - 1), dstH-1)];

        const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input

        int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input

        int lastLumSrcY2=firstLumSrcY2+ vLumFilterSize -1; // Last line needed as input

        int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input

        int enough_lines;

        //handle holes (FAST_BILINEAR & weird filters)

        if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;

        if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;

        assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);

        assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);

        DEBUG_BUFFERS("dstY: %d\n", dstY);

        DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",

                         firstLumSrcY,    lastLumSrcY,    lastInLumBuf);

        DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",

                         firstChrSrcY,    lastChrSrcY,    lastInChrBuf);

        // Do we have enough lines in this slice to output the dstY line

        enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);

        if (!enough_lines) {

            lastLumSrcY = srcSliceY + srcSliceH - 1;

            lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;

            DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",

                                            lastLumSrcY, lastChrSrcY);

        }

        //Do horizontal scaling

        while(lastInLumBuf < lastLumSrcY) {

            const uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];

            const uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];

            lumBufIndex++;

            assert(lumBufIndex < 2*vLumBufSize);

            assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);

            assert(lastInLumBuf + 1 - srcSliceY >= 0);

            RENAME(hyscale)(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,

                            hLumFilter, hLumFilterPos, hLumFilterSize,

                            formatConvBuffer,

                            pal, 0);

            if (CONFIG_SWSCALE_ALPHA && alpPixBuf)

                RENAME(hyscale)(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW, lumXInc,

                                hLumFilter, hLumFilterPos, hLumFilterSize,

                                formatConvBuffer,

                                pal, 1);

            lastInLumBuf++;

            DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",

                               lumBufIndex,    lastInLumBuf);

        }

        while(lastInChrBuf < lastChrSrcY) {

            const uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];

            const uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];

            chrBufIndex++;

            assert(chrBufIndex < 2*vChrBufSize);

            assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));

            assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);

            //FIXME replace parameters through context struct (some at least)

            if (c->needs_hcscale)

                RENAME(hcscale)(c, chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, chrSrcW, chrXInc,

                                hChrFilter, hChrFilterPos, hChrFilterSize,

                                formatConvBuffer,

                                pal);

            lastInChrBuf++;

            DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",

                               chrBufIndex,    lastInChrBuf);

        }

        //wrap buf index around to stay inside the ring buffer

        if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;

        if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;

        if (!enough_lines)

            break; //we can't output a dstY line so let's try with the next slice

#if COMPILE_TEMPLATE_MMX

        c->blueDither= ff_dither8[dstY&1];

        if (c->dstFormat == PIX_FMT_RGB555 || c->dstFormat == PIX_FMT_BGR555)

            c->greenDither= ff_dither8[dstY&1];

        else

            c->greenDither= ff_dither4[dstY&1];

        c->redDither= ff_dither8[(dstY+1)&1];

#endif

        if (dstY < dstH-2) {

            const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;

            const int16_t **chrSrcPtr= (const int16_t **) chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;

            const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;

#if COMPILE_TEMPLATE_MMX

            int i;

            if (flags & SWS_ACCURATE_RND) {

                int s= APCK_SIZE / 8;

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

                    *(const void**)&lumMmxFilter[s*i              ]= lumSrcPtr[i  ];

                    *(const void**)&lumMmxFilter[s*i+APCK_PTR2/4  ]= lumSrcPtr[i+(vLumFilterSize>1)];

                              lumMmxFilter[s*i+APCK_COEF/4  ]=

                              lumMmxFilter[s*i+APCK_COEF/4+1]= vLumFilter[dstY*vLumFilterSize + i    ]

                        + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0);

                    if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {

                        *(const void**)&alpMmxFilter[s*i              ]= alpSrcPtr[i  ];

                        *(const void**)&alpMmxFilter[s*i+APCK_PTR2/4  ]= alpSrcPtr[i+(vLumFilterSize>1)];

                                  alpMmxFilter[s*i+APCK_COEF/4  ]=

                                  alpMmxFilter[s*i+APCK_COEF/4+1]= lumMmxFilter[s*i+APCK_COEF/4  ];

                    }

                }

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

                    *(const void**)&chrMmxFilter[s*i              ]= chrSrcPtr[i  ];

                    *(const void**)&chrMmxFilter[s*i+APCK_PTR2/4  ]= chrSrcPtr[i+(vChrFilterSize>1)];

                              chrMmxFilter[s*i+APCK_COEF/4  ]=

                              chrMmxFilter[s*i+APCK_COEF/4+1]= vChrFilter[chrDstY*vChrFilterSize + i    ]

                        + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1]<<16 : 0);

                }

            } else {

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

                    lumMmxFilter[4*i+0]= (int32_t)lumSrcPtr[i];

                    lumMmxFilter[4*i+1]= (uint64_t)lumSrcPtr[i] >> 32;

                    lumMmxFilter[4*i+2]=

                    lumMmxFilter[4*i+3]=

                        ((uint16_t)vLumFilter[dstY*vLumFilterSize + i])*0x10001;

                    if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {

                        alpMmxFilter[4*i+0]= (int32_t)alpSrcPtr[i];

                        alpMmxFilter[4*i+1]= (uint64_t)alpSrcPtr[i] >> 32;

                        alpMmxFilter[4*i+2]=

                        alpMmxFilter[4*i+3]= lumMmxFilter[4*i+2];

                    }

                }

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

                    chrMmxFilter[4*i+0]= (int32_t)chrSrcPtr[i];

                    chrMmxFilter[4*i+1]= (uint64_t)chrSrcPtr[i] >> 32;

                    chrMmxFilter[4*i+2]=

                    chrMmxFilter[4*i+3]=

                        ((uint16_t)vChrFilter[chrDstY*vChrFilterSize + i])*0x10001;

                }

            }

#endif

            if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi

                c->yuv2nv12X(c,

                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                             vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                             dest, uDest, dstW, chrDstW, dstFormat);

            } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi

                if (is16BPS(dstFormat) || isNBPS(dstFormat)) {

                    yuv2yuvX16inC(

                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                  vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,

                                  dstFormat);

                } else if (vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12

                    const int16_t *lumBuf = lumSrcPtr[0];

                    const int16_t *chrBuf= chrSrcPtr[0];

                    const int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;

                    c->yuv2yuv1(c, lumBuf, chrBuf, alpBuf, dest, uDest, vDest, aDest, dstW, chrDstW);

                } else { //General YV12

                    c->yuv2yuvX(c,

                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

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

                }

            } else {

                assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);

                assert(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);

                if (vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB

                    int chrAlpha= vChrFilter[2*dstY+1];

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c, //FIXME write a packed1_full function

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packed1(c, *lumSrcPtr, *chrSrcPtr, *(chrSrcPtr+1),

                                       alpPixBuf ? *alpSrcPtr : NULL,

                                       dest, dstW, chrAlpha, dstFormat, flags, dstY);

                    }

                } else if (vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB

                    int lumAlpha= vLumFilter[2*dstY+1];

                    int chrAlpha= vChrFilter[2*dstY+1];

                    lumMmxFilter[2]=

                    lumMmxFilter[3]= vLumFilter[2*dstY   ]*0x10001;

                    chrMmxFilter[2]=

                    chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c, //FIXME write a packed2_full function

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packed2(c, *lumSrcPtr, *(lumSrcPtr+1), *chrSrcPtr, *(chrSrcPtr+1),

                                       alpPixBuf ? *alpSrcPtr : NULL, alpPixBuf ? *(alpSrcPtr+1) : NULL,

                                       dest, dstW, lumAlpha, chrAlpha, dstY);

                    }

                } else { //general RGB

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c,

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packedX(c,

                                       vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                       vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                       alpSrcPtr, dest, dstW, dstY);

                    }

                }

            }

        } else { // hmm looks like we can't use MMX here without overwriting this array's tail

            const int16_t **lumSrcPtr= (const int16_t **)lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;

            const int16_t **chrSrcPtr= (const int16_t **)chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;

            const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **)alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;

            if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi

                yuv2nv12XinC(

                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                             vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                             dest, uDest, dstW, chrDstW, dstFormat);

            } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi

                if (is16BPS(dstFormat) || isNBPS(dstFormat)) {

                    yuv2yuvX16inC(

                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                  vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,

                                  dstFormat);

                } else {

                    yuv2yuvXinC(

                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

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

                }

            } else {

                assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);

                assert(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);

                if(flags & SWS_FULL_CHR_H_INT) {

                    yuv2rgbXinC_full(c,

                                     vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                     vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                     alpSrcPtr, dest, dstW, dstY);

                } else {

                    yuv2packedXinC(c,

                                   vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                   vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                   alpSrcPtr, dest, dstW, dstY);

                }

            }

        }

    }

    if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)

        fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);

#if COMPILE_TEMPLATE_MMX

    if (flags & SWS_CPU_CAPS_MMX2 )  __asm__ volatile("sfence":::"memory");

    /* On K6 femms is faster than emms. On K7 femms is directly mapped to emms. */

    if (flags & SWS_CPU_CAPS_3DNOW)  __asm__ volatile("femms" :::"memory");

    else                             __asm__ volatile("emms"  :::"memory");

#endif

    /* store changed local vars back in the context */

    c->dstY= dstY;

    c->lumBufIndex= lumBufIndex;

    c->chrBufIndex= chrBufIndex;

    c->lastInLumBuf= lastInLumBuf;

    c->lastInChrBuf= lastInChrBuf;

    return dstY - lastDstY;

}


static inline int wv_unpack_mono(WavpackFrameContext *s, GetBitContext *gb,

                                 void *dst, const int type)

{

    int i, j, count = 0;

    int last, t;

    int A, S, T;

    int pos                  = s->pos;

    uint32_t crc             = s->sc.crc;

    uint32_t crc_extra_bits  = s->extra_sc.crc;

    int16_t *dst16           = dst;

    int32_t *dst32           = dst;

    float *dstfl             = dst;

    s->one = s->zero = s->zeroes = 0;

    do {

        T = wv_get_value(s, gb, 0, &last);

        S = 0;

        if (last)

            break;

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

            t = s->decorr[i].value;

            if (t > 8) {

                if (t & 1)

                    A =  2U * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1];

                else

                    A = (int)(3U * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1;

                s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0];

                j                        = 0;

            } else {

                A = s->decorr[i].samplesA[pos];

                j = (pos + t) & 7;

            }

            if (type != AV_SAMPLE_FMT_S16P)

                S = T + ((s->decorr[i].weightA * (int64_t)A + 512) >> 10);

            else

                S = T + ((s->decorr[i].weightA * A + 512) >> 10);

            if (A && T)

                s->decorr[i].weightA -= ((((T ^ A) >> 30) & 2) - 1) * s->decorr[i].delta;

            s->decorr[i].samplesA[j] = T = S;

        }

        pos = (pos + 1) & 7;

        crc = crc * 3 + S;

        if (type == AV_SAMPLE_FMT_FLTP) {

            *dstfl++ = wv_get_value_float(s, &crc_extra_bits, S);

        } else if (type == AV_SAMPLE_FMT_S32P) {

            *dst32++ = wv_get_value_integer(s, &crc_extra_bits, S);

        } else {

            *dst16++ = wv_get_value_integer(s, &crc_extra_bits, S);

        }

        count++;

    } while (!last && count < s->samples);

    wv_reset_saved_context(s);

    if (last && count < s->samples) {

        int size = av_get_bytes_per_sample(type);

        memset((uint8_t*)dst + count*size, 0, (s->samples-count)*size);

    }

    if (s->avctx->err_recognition & AV_EF_CRCCHECK) {

        int ret = wv_check_crc(s, crc, crc_extra_bits);

        if (ret < 0 && s->avctx->err_recognition & AV_EF_EXPLODE)

            return ret;

    }

    return 0;

}


static void mmu_init (CPUMIPSState *env, const mips_def_t *def)

{

    env->tlb = qemu_mallocz(sizeof(CPUMIPSTLBContext));

    switch (def->mmu_type) {

        case MMU_TYPE_NONE:

            no_mmu_init(env, def);

            break;

        case MMU_TYPE_R4000:

            r4k_mmu_init(env, def);

            break;

        case MMU_TYPE_FMT:

            fixed_mmu_init(env, def);

            break;

        case MMU_TYPE_R3000:

        case MMU_TYPE_R6000:

        case MMU_TYPE_R8000:

        default:

            cpu_abort(env, "MMU type not supported\n");

    }

    env->CP0_Random = env->tlb->nb_tlb - 1;

    env->tlb->tlb_in_use = env->tlb->nb_tlb;

}


static void sample_queue_push(HintSampleQueue *queue, uint8_t *data, int size,

                              int sample)

{

    /* No need to keep track of smaller samples, since describing them

     * with immediates is more efficient. */

    if (size <= 14)

        return;

    if (!queue->samples || queue->len >= queue->size) {

        HintSample *samples;

        samples = av_realloc(queue->samples, sizeof(HintSample) * (queue->size + 10));

        if (!samples)

            return;

        queue->size += 10;

        queue->samples = samples;

    }

    queue->samples[queue->len].data = data;

    queue->samples[queue->len].size = size;

    queue->samples[queue->len].sample_number = sample;

    queue->samples[queue->len].offset   = 0;

    queue->samples[queue->len].own_data = 0;

    queue->len++;

}


static void gen_spr_power8_tce_address_control(CPUPPCState *env)

{

    spr_register(env, SPR_TAR, "TAR",

                 &spr_read_generic, &spr_write_generic,

                 &spr_read_generic, &spr_write_generic,

                 0x00000000);

}