static int tm2_read_stream(TM2Context *ctx, const uint8_t *buf, int stream_id) {

    int i;

    int cur = 0;

    int skip = 0;

    int len, toks;

    TM2Codes codes;

    /* get stream length in dwords */

    len = AV_RB32(buf); buf += 4; cur += 4;

    skip = len * 4 + 4;

    if(len == 0)

        return 4;

    toks = AV_RB32(buf); buf += 4; cur += 4;

    if(toks & 1) {

        len = AV_RB32(buf); buf += 4; cur += 4;

        if(len == TM2_ESCAPE) {

            len = AV_RB32(buf); buf += 4; cur += 4;

        }

        if(len > 0) {

            init_get_bits(&ctx->gb, buf, (skip - cur) * 8);

            if(tm2_read_deltas(ctx, stream_id) == -1)

                return -1;

            buf += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;

            cur += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;

        }

    }

    /* skip unused fields */

    if(AV_RB32(buf) == TM2_ESCAPE) {

        buf += 4; cur += 4; /* some unknown length - could be escaped too */

    }

    buf += 4; cur += 4;

    buf += 4; cur += 4; /* unused by decoder */

    init_get_bits(&ctx->gb, buf, (skip - cur) * 8);

    if(tm2_build_huff_table(ctx, &codes) == -1)

        return -1;

    buf += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;

    cur += ((get_bits_count(&ctx->gb) + 31) >> 5) << 2;

    toks >>= 1;

    /* check if we have sane number of tokens */

    if((toks < 0) || (toks > 0xFFFFFF)){

        av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of tokens: %i\n", toks);

        tm2_free_codes(&codes);

        return -1;

    }

    ctx->tokens[stream_id] = av_realloc(ctx->tokens[stream_id], toks * sizeof(int));

    ctx->tok_lens[stream_id] = toks;

    len = AV_RB32(buf); buf += 4; cur += 4;

    if(len > 0) {

        init_get_bits(&ctx->gb, buf, (skip - cur) * 8);

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

            ctx->tokens[stream_id][i] = tm2_get_token(&ctx->gb, &codes);

    } else {

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

            ctx->tokens[stream_id][i] = codes.recode[0];

    }

    tm2_free_codes(&codes);

    return skip;

}


static void do_dma_memory_set(dma_addr_t addr, uint8_t c, dma_addr_t len)

{

#define FILLBUF_SIZE 512

    uint8_t fillbuf[FILLBUF_SIZE];

    int l;

    memset(fillbuf, c, FILLBUF_SIZE);

    while (len > 0) {

        l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;

        cpu_physical_memory_rw(addr, fillbuf, l, true);

        len -= len;

        addr += len;

    }

}


static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)

{

    int nearest_delta_ms = (delta + 999999) / 1000000;

    if (nearest_delta_ms < 1) {

        nearest_delta_ms = 1;

    }

    timeKillEvent(mm_timer);

    mm_timer = timeSetEvent(nearest_delta_ms,

                            mm_period,

                            mm_alarm_handler,

                            (DWORD_PTR)t,

                            TIME_ONESHOT | TIME_CALLBACK_FUNCTION);

    if (!mm_timer) {

        fprintf(stderr, "Failed to re-arm win32 alarm timer %ld\n",

                GetLastError());

        timeEndPeriod(mm_period);

        exit(1);

    }

}


static void DEF(avg, pixels16_x2)(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)

{

    MOVQ_BFE(mm6);

    JUMPALIGN();

    do {

        __asm__ volatile(

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

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

            "movq  %0, %%mm3            \n\t"

            PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)

            PAVGB_MMX(%%mm3, %%mm2, %%mm0, %%mm6)

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

            "movq  8%1, %%mm0           \n\t"

            "movq  9%1, %%mm1           \n\t"

            "movq  8%0, %%mm3           \n\t"

            PAVGB(%%mm0, %%mm1, %%mm2, %%mm6)

            PAVGB_MMX(%%mm3, %%mm2, %%mm0, %%mm6)

            "movq  %%mm0, 8%0           \n\t"

            :"+m"(*block)

            :"m"(*pixels)

            :"memory");

        pixels += line_size;

        block += line_size;

    } while (--h);

}


static int config_output(AVFilterLink *outlink) {

    static const char hdcd_baduse[] =

        "The HDCD filter is unlikely to produce a desirable result in this context.";

    AVFilterContext *ctx = outlink->src;

    HDCDContext *s = ctx->priv;

    AVFilterLink *lk = outlink;

    while(lk != NULL) {

        AVFilterContext *nextf = lk->dst;

        if (lk->type == AVMEDIA_TYPE_AUDIO) {

            if (lk->format == AV_SAMPLE_FMT_S16 || lk->format == AV_SAMPLE_FMT_U8) {

                av_log(ctx, AV_LOG_WARNING, "s24 output is being truncated to %s at %s.\n",

                    av_get_sample_fmt_name(lk->format),

                    (nextf->name) ? nextf->name : "<unknown>"

                    );

                s->bad_config = 1;

                break;

            }

        }

        lk = (nextf->outputs) ? nextf->outputs[0] : NULL;

    }

    if (s->bad_config)

        av_log(ctx, AV_LOG_WARNING, "%s\n", hdcd_baduse);

    return 0;

}


static inline int copy_siginfo_to_user(target_siginfo_t *tinfo,

                                       const target_siginfo_t *info)

{

    tswap_siginfo(tinfo, info);

    return 0;

}


iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num,

                 QEMUIOVector *qiov, int nb_sectors,

                 BlockDriverCompletionFunc *cb,

                 void *opaque)

{

    IscsiLun *iscsilun = bs->opaque;

    struct iscsi_context *iscsi = iscsilun->iscsi;

    IscsiAIOCB *acb;

    size_t size;

    uint32_t num_sectors;

    uint64_t lba;

#if !defined(LIBISCSI_FEATURE_IOVECTOR)

    struct iscsi_data data;

#endif

    int ret;

    acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque);

    trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb);

    acb->iscsilun = iscsilun;

    acb->qiov     = qiov;

    acb->canceled   = 0;

    acb->bh         = NULL;

    acb->status     = -EINPROGRESS;

    acb->buf        = NULL;

    /* this will allow us to get rid of 'buf' completely */

    size = nb_sectors * BDRV_SECTOR_SIZE;

#if !defined(LIBISCSI_FEATURE_IOVECTOR)

    data.size = MIN(size, acb->qiov->size);

    /* if the iovec only contains one buffer we can pass it directly */

    if (acb->qiov->niov == 1) {

        data.data = acb->qiov->iov[0].iov_base;

    } else {

        acb->buf = g_malloc(data.size);

        qemu_iovec_to_buf(acb->qiov, 0, acb->buf, data.size);

        data.data = acb->buf;

    }

#endif

    acb->task = malloc(sizeof(struct scsi_task));

    if (acb->task == NULL) {

        error_report("iSCSI: Failed to allocate task for scsi WRITE16 "

                     "command. %s", iscsi_get_error(iscsi));

        qemu_aio_release(acb);

        return NULL;

    }

    memset(acb->task, 0, sizeof(struct scsi_task));

    acb->task->xfer_dir = SCSI_XFER_WRITE;

    acb->task->cdb_size = 16;

    acb->task->cdb[0] = 0x8a;

    lba = sector_qemu2lun(sector_num, iscsilun);

    *(uint32_t *)&acb->task->cdb[2]  = htonl(lba >> 32);

    *(uint32_t *)&acb->task->cdb[6]  = htonl(lba & 0xffffffff);

    num_sectors = size / iscsilun->block_size;

    *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors);

    acb->task->expxferlen = size;

#if defined(LIBISCSI_FEATURE_IOVECTOR)

    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,

                                   iscsi_aio_write16_cb,

                                   NULL,

                                   acb);

#else

    ret = iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task,

                                   iscsi_aio_write16_cb,

                                   &data,

                                   acb);

#endif

    if (ret != 0) {

        scsi_free_scsi_task(acb->task);

        g_free(acb->buf);

        qemu_aio_release(acb);

        return NULL;

    }

#if defined(LIBISCSI_FEATURE_IOVECTOR)

    scsi_task_set_iov_out(acb->task, (struct scsi_iovec*) acb->qiov->iov, acb->qiov->niov);

#endif

    iscsi_set_events(iscsilun);

    return &acb->common;

}


static void mtree_print_flatview(fprintf_function p, void *f,

                                 AddressSpace *as)

{

    FlatView *view = address_space_get_flatview(as);

    FlatRange *range = &view->ranges[0];

    MemoryRegion *mr;

    int n = view->nr;

    if (n <= 0) {

        p(f, MTREE_INDENT "No rendered FlatView for "

          "address space '%s'\n", as->name);

        flatview_unref(view);

        return;

    }

    while (n--) {

        mr = range->mr;

        p(f, MTREE_INDENT TARGET_FMT_plx "-"

          TARGET_FMT_plx " (prio %d, %s): %s\n",

          int128_get64(range->addr.start),

          int128_get64(range->addr.start) + MR_SIZE(range->addr.size),

          mr->priority,

          memory_region_type(mr),

          memory_region_name(mr));

        range++;

    }

    flatview_unref(view);

}


static inline uint32_t efsctuf(uint32_t val)

{

    CPU_FloatU u;

    float32 tmp;

    u.l = val;

    /* NaN are not treated the same way IEEE 754 does */

    if (unlikely(float32_is_nan(u.f)))

        return 0;

    tmp = uint64_to_float32(1ULL << 32, &env->vec_status);

    u.f = float32_mul(u.f, tmp, &env->vec_status);

    return float32_to_uint32(u.f, &env->vec_status);

}


void ppce500_init(PPCE500Params *params)

{

    MemoryRegion *address_space_mem = get_system_memory();

    MemoryRegion *ram = g_new(MemoryRegion, 1);

    PCIBus *pci_bus;

    CPUPPCState *env = NULL;

    uint64_t elf_entry;

    uint64_t elf_lowaddr;

    hwaddr entry=0;

    hwaddr loadaddr=UIMAGE_LOAD_BASE;

    target_long kernel_size=0;

    target_ulong dt_base = 0;

    target_ulong initrd_base = 0;

    target_long initrd_size=0;

    int i=0;

    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};

    qemu_irq **irqs, *mpic;

    DeviceState *dev;

    CPUPPCState *firstenv = NULL;

    MemoryRegion *ccsr_addr_space;

    SysBusDevice *s;

    PPCE500CCSRState *ccsr;

    /* Setup CPUs */

    if (params->cpu_model == NULL) {

        params->cpu_model = "e500v2_v30";

    }

    irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));

    irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);

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

        PowerPCCPU *cpu;

        qemu_irq *input;

        cpu = cpu_ppc_init(params->cpu_model);

        if (cpu == NULL) {

            fprintf(stderr, "Unable to initialize CPU!\n");

            exit(1);

        }

        env = &cpu->env;

        if (!firstenv) {

            firstenv = env;

        }

        irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);

        input = (qemu_irq *)env->irq_inputs;

        irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];

        irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];

        env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;

        env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +

                              MPC8544_MPIC_REGS_OFFSET + 0x20000;

        ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);

        /* Register reset handler */

        if (!i) {

            /* Primary CPU */

            struct boot_info *boot_info;

            boot_info = g_malloc0(sizeof(struct boot_info));

            qemu_register_reset(ppce500_cpu_reset, cpu);

            env->load_info = boot_info;

        } else {

            /* Secondary CPUs */

            qemu_register_reset(ppce500_cpu_reset_sec, cpu);

        }

    }

    env = firstenv;

    /* Fixup Memory size on a alignment boundary */

    ram_size &= ~(RAM_SIZES_ALIGN - 1);

    /* Register Memory */

    memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);

    vmstate_register_ram_global(ram);

    memory_region_add_subregion(address_space_mem, 0, ram);

    dev = qdev_create(NULL, "e500-ccsr");

    object_property_add_child(qdev_get_machine(), "e500-ccsr",

                              OBJECT(dev), NULL);

    qdev_init_nofail(dev);

    ccsr = CCSR(dev);

    ccsr_addr_space = &ccsr->ccsr_space;

    memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,

                                ccsr_addr_space);

    /* MPIC */

    mpic = mpic_init(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,

                     smp_cpus, irqs, NULL);

    if (!mpic) {

        cpu_abort(env, "MPIC failed to initialize\n");

    }

    /* Serial */

    if (serial_hds[0]) {

        serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,

                       0, mpic[42], 399193,

                       serial_hds[0], DEVICE_BIG_ENDIAN);

    }

    if (serial_hds[1]) {

        serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,

                       0, mpic[42], 399193,

                       serial_hds[1], DEVICE_BIG_ENDIAN);

    }

    /* General Utility device */

    dev = qdev_create(NULL, "mpc8544-guts");

    qdev_init_nofail(dev);

    s = SYS_BUS_DEVICE(dev);

    memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,

                                sysbus_mmio_get_region(s, 0));

    /* PCI */

    dev = qdev_create(NULL, "e500-pcihost");

    qdev_init_nofail(dev);

    s = SYS_BUS_DEVICE(dev);

    sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);

    sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);

    sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);

    sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);

    memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,

                                sysbus_mmio_get_region(s, 0));

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

    if (!pci_bus)

        printf("couldn't create PCI controller!\n");

    sysbus_mmio_map(sysbus_from_qdev(dev), 1, MPC8544_PCI_IO);

    if (pci_bus) {

        /* Register network interfaces. */

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

            pci_nic_init_nofail(&nd_table[i], "virtio", NULL);

        }

    }

    /* Register spinning region */

    sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);

    /* Load kernel. */

    if (params->kernel_filename) {

        kernel_size = load_uimage(params->kernel_filename, &entry,

                                  &loadaddr, NULL);

        if (kernel_size < 0) {

            kernel_size = load_elf(params->kernel_filename, NULL, NULL,

                                   &elf_entry, &elf_lowaddr, NULL, 1,

                                   ELF_MACHINE, 0);

            entry = elf_entry;

            loadaddr = elf_lowaddr;

        }

        /* XXX try again as binary */

        if (kernel_size < 0) {

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

                    params->kernel_filename);

            exit(1);

        }

    }

    /* Load initrd. */

    if (params->initrd_filename) {

        initrd_base = (loadaddr + kernel_size + INITRD_LOAD_PAD) &

            ~INITRD_PAD_MASK;

        initrd_size = load_image_targphys(params->initrd_filename, initrd_base,

                                          ram_size - initrd_base);

        if (initrd_size < 0) {

            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",

                    params->initrd_filename);

            exit(1);

        }

    }

    /* If we're loading a kernel directly, we must load the device tree too. */

    if (params->kernel_filename) {

        struct boot_info *boot_info;

        int dt_size;

        dt_base = (loadaddr + kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;

        dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,

                                           initrd_size);

        if (dt_size < 0) {

            fprintf(stderr, "couldn't load device tree\n");

            exit(1);

        }

        boot_info = env->load_info;

        boot_info->entry = entry;

        boot_info->dt_base = dt_base;

        boot_info->dt_size = dt_size;

    }

    if (kvm_enabled()) {

        kvmppc_init();

    }

}


int nbd_trip(BlockDriverState *bs, int csock, off_t size,

             uint64_t dev_offset, uint32_t nbdflags,

             uint8_t *data)

{

    struct nbd_request request;

    struct nbd_reply reply;

    int ret;

    TRACE("Reading request.");

    if (nbd_receive_request(csock, &request) == -1)

        return -1;

    if (request.len + NBD_REPLY_SIZE > NBD_BUFFER_SIZE) {

        LOG("len (%u) is larger than max len (%u)",

            request.len + NBD_REPLY_SIZE, NBD_BUFFER_SIZE);

        errno = EINVAL;

        return -1;

    }

    if ((request.from + request.len) < request.from) {

        LOG("integer overflow detected! "

            "you're probably being attacked");

        errno = EINVAL;

        return -1;

    }

    if ((request.from + request.len) > size) {

            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64

            ", Offset: %" PRIu64 "\n",

                    request.from, request.len, (uint64_t)size, dev_offset);

        LOG("requested operation past EOF--bad client?");

        errno = EINVAL;

        return -1;

    }

    TRACE("Decoding type");

    reply.handle = request.handle;

    reply.error = 0;

    switch (request.type & NBD_CMD_MASK_COMMAND) {

    case NBD_CMD_READ:

        TRACE("Request type is READ");

        ret = bdrv_read(bs, (request.from + dev_offset) / 512,

                        data + NBD_REPLY_SIZE,

                        request.len / 512);

        if (ret < 0) {

            LOG("reading from file failed");

            reply.error = -ret;

            request.len = 0;

        }

        TRACE("Read %u byte(s)", request.len);

        /* Reply

           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)

           [ 4 ..  7]    error   (0 == no error)

           [ 7 .. 15]    handle

         */

        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);

        cpu_to_be32w((uint32_t*)(data + 4), reply.error);

        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);

        TRACE("Sending data to client");

        if (write_sync(csock, data,

                   request.len + NBD_REPLY_SIZE) !=

                   request.len + NBD_REPLY_SIZE) {

            LOG("writing to socket failed");

            errno = EINVAL;

            return -1;

        }

        break;

    case NBD_CMD_WRITE:

        TRACE("Request type is WRITE");

        TRACE("Reading %u byte(s)", request.len);

        if (read_sync(csock, data, request.len) != request.len) {

            LOG("reading from socket failed");

            errno = EINVAL;

            return -1;

        }

        if (nbdflags & NBD_FLAG_READ_ONLY) {

            TRACE("Server is read-only, return error");

            reply.error = 1;

        } else {

            TRACE("Writing to device");

            ret = bdrv_write(bs, (request.from + dev_offset) / 512,

                             data, request.len / 512);

            if (ret < 0) {

                LOG("writing to file failed");

                reply.error = -ret;

                request.len = 0;

            }

            if (request.type & NBD_CMD_FLAG_FUA) {

                ret = bdrv_flush(bs);

                if (ret < 0) {

                    LOG("flush failed");

                    reply.error = -ret;

                }

            }

        }

        if (nbd_send_reply(csock, &reply) == -1)

            return -1;

        break;

    case NBD_CMD_DISC:

        TRACE("Request type is DISCONNECT");

        errno = 0;

        return 1;

    case NBD_CMD_FLUSH:

        TRACE("Request type is FLUSH");

        ret = bdrv_flush(bs);

        if (ret < 0) {

            LOG("flush failed");

            reply.error = -ret;

        }

        if (nbd_send_reply(csock, &reply) == -1)

            return -1;

        break;

    case NBD_CMD_TRIM:

        TRACE("Request type is TRIM");

        ret = bdrv_discard(bs, (request.from + dev_offset) / 512,

                           request.len / 512);

        if (ret < 0) {

            LOG("discard failed");

            reply.error = -ret;

        }

        if (nbd_send_reply(csock, &reply) == -1)

            return -1;

        break;

    default:

        LOG("invalid request type (%u) received", request.type);

        errno = EINVAL;

        return -1;

    }

    TRACE("Request/Reply complete");

    return 0;

}


test_opts_range_unvisited(void)

{

    intList *list = NULL;

    intList *tail;

    QemuOpts *opts;

    Visitor *v;

    opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0-2", false,

                           &error_abort);

    v = opts_visitor_new(opts);

    visit_start_struct(v, NULL, NULL, 0, &error_abort);

    /* Would be simpler if the visitor genuinely supported virtual walks */

    visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),

                     &error_abort);

    tail = list;

    visit_type_int(v, NULL, &tail->value, &error_abort);

    g_assert_cmpint(tail->value, ==, 0);

    tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));

    g_assert(tail);

    visit_type_int(v, NULL, &tail->value, &error_abort);

    g_assert_cmpint(tail->value, ==, 1);

    tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));

    g_assert(tail);

    visit_end_list(v, (void **)&list);

    /* BUG: unvisited tail not reported; actually not reportable by design */

    visit_check_struct(v, &error_abort);

    visit_end_struct(v, NULL);

    qapi_free_intList(list);

    visit_free(v);

    qemu_opts_del(opts);

}


static int mpeg_decode_mb(MpegEncContext *s,

                          DCTELEM block[12][64])

{

    int i, j, k, cbp, val, mb_type, motion_type;

    dprintf("decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y);

    assert(s->mb_skiped==0);

    if (s->mb_skip_run-- != 0) {

        if(s->pict_type == I_TYPE){

            av_log(s->avctx, AV_LOG_ERROR, "skiped MB in I frame at %d %d\n", s->mb_x, s->mb_y);

            return -1;

        }

        /* skip mb */

        s->mb_intra = 0;

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

            s->block_last_index[i] = -1;

        if(s->picture_structure == PICT_FRAME)

            s->mv_type = MV_TYPE_16X16;

        else

            s->mv_type = MV_TYPE_FIELD;

        if (s->pict_type == P_TYPE) {

            /* if P type, zero motion vector is implied */

            s->mv_dir = MV_DIR_FORWARD;

            s->mv[0][0][0] = s->mv[0][0][1] = 0;

            s->last_mv[0][0][0] = s->last_mv[0][0][1] = 0;

            s->last_mv[0][1][0] = s->last_mv[0][1][1] = 0;

            s->field_select[0][0]= s->picture_structure - 1;

            s->mb_skiped = 1;

            s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride ]= MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16;

        } else {

            /* if B type, reuse previous vectors and directions */

            s->mv[0][0][0] = s->last_mv[0][0][0];

            s->mv[0][0][1] = s->last_mv[0][0][1];

            s->mv[1][0][0] = s->last_mv[1][0][0];

            s->mv[1][0][1] = s->last_mv[1][0][1];

            s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride ]=

                s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride - 1] | MB_TYPE_SKIP;

//            assert(s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride - 1]&(MB_TYPE_16x16|MB_TYPE_16x8));

            if((s->mv[0][0][0]|s->mv[0][0][1]|s->mv[1][0][0]|s->mv[1][0][1])==0)

                s->mb_skiped = 1;

        }

        return 0;

    }

    switch(s->pict_type) {

    default:

    case I_TYPE:

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

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

                av_log(s->avctx, AV_LOG_ERROR, "invalid mb type in I Frame at %d %d\n", s->mb_x, s->mb_y);

                return -1;

            }

            mb_type = MB_TYPE_QUANT | MB_TYPE_INTRA;

        } else {

            mb_type = MB_TYPE_INTRA;

        }

        break;

    case P_TYPE:

        mb_type = get_vlc2(&s->gb, mb_ptype_vlc.table, MB_PTYPE_VLC_BITS, 1);

        if (mb_type < 0){

            av_log(s->avctx, AV_LOG_ERROR, "invalid mb type in P Frame at %d %d\n", s->mb_x, s->mb_y);

            return -1;

        }

        mb_type = ptype2mb_type[ mb_type ];

        break;

    case B_TYPE:

        mb_type = get_vlc2(&s->gb, mb_btype_vlc.table, MB_BTYPE_VLC_BITS, 1);

        if (mb_type < 0){

            av_log(s->avctx, AV_LOG_ERROR, "invalid mb type in B Frame at %d %d\n", s->mb_x, s->mb_y);

            return -1;

        }

        mb_type = btype2mb_type[ mb_type ];

        break;

    }

    dprintf("mb_type=%x\n", mb_type);

//    motion_type = 0; /* avoid warning */

    if (IS_INTRA(mb_type)) {

        /* compute dct type */

        if (s->picture_structure == PICT_FRAME && //FIXME add a interlaced_dct coded var?

            !s->frame_pred_frame_dct) {

            s->interlaced_dct = get_bits1(&s->gb);

        }

        if (IS_QUANT(mb_type))

            s->qscale = get_qscale(s);

        if (s->concealment_motion_vectors) {

            /* just parse them */

            if (s->picture_structure != PICT_FRAME)

                skip_bits1(&s->gb); /* field select */

            s->mv[0][0][0]= s->last_mv[0][0][0]= s->last_mv[0][1][0] =

                mpeg_decode_motion(s, s->mpeg_f_code[0][0], s->last_mv[0][0][0]);

            s->mv[0][0][1]= s->last_mv[0][0][1]= s->last_mv[0][1][1] =

                mpeg_decode_motion(s, s->mpeg_f_code[0][1], s->last_mv[0][0][1]);

            skip_bits1(&s->gb); /* marker */

        }else

            memset(s->last_mv, 0, sizeof(s->last_mv)); /* reset mv prediction */

        s->mb_intra = 1;

#ifdef HAVE_XVMC

        //one 1 we memcpy blocks in xvmcvideo

        if(s->avctx->xvmc_acceleration > 1){

            XVMC_pack_pblocks(s,-1);//inter are always full blocks

            if(s->swap_uv){

                exchange_uv(s);

            }

        }

#endif

        if (s->codec_id == CODEC_ID_MPEG2VIDEO) {

            for(i=0;i<4+(1<<s->chroma_format);i++) {

                if (mpeg2_decode_block_intra(s, s->pblocks[i], i) < 0)

                    return -1;

            }

        } else {

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

                if (mpeg1_decode_block_intra(s, s->pblocks[i], i) < 0)

                    return -1;

            }

        }

    } else {

        if (mb_type & MB_TYPE_ZERO_MV){

            assert(mb_type & MB_TYPE_CBP);

            /* compute dct type */

            if (s->picture_structure == PICT_FRAME && //FIXME add a interlaced_dct coded var?

                !s->frame_pred_frame_dct) {

                s->interlaced_dct = get_bits1(&s->gb);

            }

            if (IS_QUANT(mb_type))

                s->qscale = get_qscale(s);

            s->mv_dir = MV_DIR_FORWARD;

            if(s->picture_structure == PICT_FRAME)

                s->mv_type = MV_TYPE_16X16;

            else{

                s->mv_type = MV_TYPE_FIELD;

                mb_type |= MB_TYPE_INTERLACED;

                s->field_select[0][0]= s->picture_structure - 1;

            }

            s->last_mv[0][0][0] = 0;

            s->last_mv[0][0][1] = 0;

            s->last_mv[0][1][0] = 0;

            s->last_mv[0][1][1] = 0;

            s->mv[0][0][0] = 0;

            s->mv[0][0][1] = 0;

        }else{

            assert(mb_type & MB_TYPE_L0L1);

//FIXME decide if MBs in field pictures are MB_TYPE_INTERLACED

            /* get additionnal motion vector type */

            if (s->frame_pred_frame_dct)

                motion_type = MT_FRAME;

            else{

                motion_type = get_bits(&s->gb, 2);

            }

            /* compute dct type */

            if (s->picture_structure == PICT_FRAME && //FIXME add a interlaced_dct coded var?

                !s->frame_pred_frame_dct && HAS_CBP(mb_type)) {

                s->interlaced_dct = get_bits1(&s->gb);

            }

            if (IS_QUANT(mb_type))

                s->qscale = get_qscale(s);

            /* motion vectors */

            s->mv_dir = 0;

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

                if (USES_LIST(mb_type, i)) {

                    s->mv_dir |= (MV_DIR_FORWARD >> i);

                    dprintf("motion_type=%d\n", motion_type);

                    switch(motion_type) {

                    case MT_FRAME: /* or MT_16X8 */

                        if (s->picture_structure == PICT_FRAME) {

                            /* MT_FRAME */

                            mb_type |= MB_TYPE_16x16;

                            s->mv_type = MV_TYPE_16X16;

                            s->mv[i][0][0]= s->last_mv[i][0][0]= s->last_mv[i][1][0] =

                                mpeg_decode_motion(s, s->mpeg_f_code[i][0], s->last_mv[i][0][0]);

                            s->mv[i][0][1]= s->last_mv[i][0][1]= s->last_mv[i][1][1] =

                                mpeg_decode_motion(s, s->mpeg_f_code[i][1], s->last_mv[i][0][1]);

                            /* full_pel: only for mpeg1 */

                            if (s->full_pel[i]){

                                s->mv[i][0][0] <<= 1;

                                s->mv[i][0][1] <<= 1;

                            }

                        } else {

                            /* MT_16X8 */

                            mb_type |= MB_TYPE_16x8 | MB_TYPE_INTERLACED;

                            s->mv_type = MV_TYPE_16X8;

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

                                s->field_select[i][j] = get_bits1(&s->gb);

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

                                    val = mpeg_decode_motion(s, s->mpeg_f_code[i][k],

                                                             s->last_mv[i][j][k]);

                                    s->last_mv[i][j][k] = val;

                                    s->mv[i][j][k] = val;

                                }

                            }

                        }

                        break;

                    case MT_FIELD:

                        s->mv_type = MV_TYPE_FIELD;

                        if (s->picture_structure == PICT_FRAME) {

                            mb_type |= MB_TYPE_16x8 | MB_TYPE_INTERLACED;

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

                                s->field_select[i][j] = get_bits1(&s->gb);

                                val = mpeg_decode_motion(s, s->mpeg_f_code[i][0],

                                                         s->last_mv[i][j][0]);

                                s->last_mv[i][j][0] = val;

                                s->mv[i][j][0] = val;

                                dprintf("fmx=%d\n", val);

                                val = mpeg_decode_motion(s, s->mpeg_f_code[i][1],

                                                         s->last_mv[i][j][1] >> 1);

                                s->last_mv[i][j][1] = val << 1;

                                s->mv[i][j][1] = val;

                                dprintf("fmy=%d\n", val);

                            }

                        } else {

                            mb_type |= MB_TYPE_16x16 | MB_TYPE_INTERLACED;

                            s->field_select[i][0] = get_bits1(&s->gb);

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

                                val = mpeg_decode_motion(s, s->mpeg_f_code[i][k],

                                                         s->last_mv[i][0][k]);

                                s->last_mv[i][0][k] = val;

                                s->last_mv[i][1][k] = val;

                                s->mv[i][0][k] = val;

                            }

                        }

                        break;

                    case MT_DMV:

                        {

                            int dmx, dmy, mx, my, m;

                            mx = mpeg_decode_motion(s, s->mpeg_f_code[i][0],

                                                    s->last_mv[i][0][0]);

                            s->last_mv[i][0][0] = mx;

                            s->last_mv[i][1][0] = mx;

                            dmx = get_dmv(s);

                            my = mpeg_decode_motion(s, s->mpeg_f_code[i][1],

                                                    s->last_mv[i][0][1] >> 1);

                            dmy = get_dmv(s);

                            s->mv_type = MV_TYPE_DMV;

                            s->last_mv[i][0][1] = my<<1;

                            s->last_mv[i][1][1] = my<<1;

                            s->mv[i][0][0] = mx;

                            s->mv[i][0][1] = my;

                            s->mv[i][1][0] = mx;//not used

                            s->mv[i][1][1] = my;//not used

                            if (s->picture_structure == PICT_FRAME) {

                                mb_type |= MB_TYPE_16x16 | MB_TYPE_INTERLACED;

                                //m = 1 + 2 * s->top_field_first;

                                m = s->top_field_first ? 1 : 3;

                                /* top -> top pred */

                                s->mv[i][2][0] = ((mx * m + (mx > 0)) >> 1) + dmx;

                                s->mv[i][2][1] = ((my * m + (my > 0)) >> 1) + dmy - 1;

                                m = 4 - m;

                                s->mv[i][3][0] = ((mx * m + (mx > 0)) >> 1) + dmx;

                                s->mv[i][3][1] = ((my * m + (my > 0)) >> 1) + dmy + 1;

                            } else {

                                mb_type |= MB_TYPE_16x16;

                                s->mv[i][2][0] = ((mx + (mx > 0)) >> 1) + dmx;

                                s->mv[i][2][1] = ((my + (my > 0)) >> 1) + dmy;

                                if(s->picture_structure == PICT_TOP_FIELD)

                                    s->mv[i][2][1]--;

                                else

                                    s->mv[i][2][1]++;

                            }

                        }

                        break;

                    default:

                        av_log(s->avctx, AV_LOG_ERROR, "00 motion_type at %d %d\n", s->mb_x, s->mb_y);

                        return -1;

                    }

                }

            }

        }

        s->mb_intra = 0;

        if (HAS_CBP(mb_type)) {

            cbp = get_vlc2(&s->gb, mb_pat_vlc.table, MB_PAT_VLC_BITS, 1);

            if (cbp < 0){

                av_log(s->avctx, AV_LOG_ERROR, "invalid cbp at %d %d\n", s->mb_x, s->mb_y);

                return -1;

            }

            cbp++;

            if(s->chroma_format == 2){//CHROMA422

                 cbp|= ( get_bits(&s->gb,2) ) << 6;

            }else

            if(s->chroma_format >  2){//CHROMA444

                 cbp|= ( get_bits(&s->gb,6) ) << 6;

            }

#ifdef HAVE_XVMC

            //on 1 we memcpy blocks in xvmcvideo

            if(s->avctx->xvmc_acceleration > 1){

                XVMC_pack_pblocks(s,cbp);

                if(s->swap_uv){

                    exchange_uv(s);

                }

            }

#endif

            if (s->codec_id == CODEC_ID_MPEG2VIDEO) {

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

                    if (cbp & (1<<(5-i)) ) {

                        if (mpeg2_decode_block_non_intra(s, s->pblocks[i], i) < 0)

                            return -1;

                    } else {

                        s->block_last_index[i] = -1;

                    }

                }

                if (s->chroma_format >= 2) {

                    if (s->chroma_format == 2) {//CHROMA_422)

                        for(i=6;i<8;i++) {

                            if (cbp & (1<<(6+7-i)) ) {

                                if (mpeg2_decode_block_non_intra(s, s->pblocks[i], i) < 0)

                                    return -1;

                            } else {

                                s->block_last_index[i] = -1;

                            }

                        }

                    }else{ /*CHROMA_444*/

                        for(i=6;i<12;i++) {

                            if (cbp & (1<<(6+11-i)) ) {

                                if (mpeg2_decode_block_non_intra(s, s->pblocks[i], i) < 0)

                                    return -1;

                            } else {

                                s->block_last_index[i] = -1;

                            }

                        }

                    }

                }

            } else {

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

                    if (cbp & 32) {

                        if (mpeg1_decode_block_inter(s, s->pblocks[i], i) < 0)

                            return -1;

                    } else {

                        s->block_last_index[i] = -1;

                    }

                    cbp+=cbp;

                }

            }

        }else{

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

                s->block_last_index[i] = -1;

        }

    }

    s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride ]= mb_type;

    return 0;

}


static av_cold int rv10_decode_init(AVCodecContext *avctx)

{

    RVDecContext  *rv = avctx->priv_data;

    MpegEncContext *s = &rv->m;

    static int done=0;

    int major_ver, minor_ver, micro_ver;

    if (avctx->extradata_size < 8) {

        av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");

        return -1;

    }

    ff_MPV_decode_defaults(s);

    s->avctx= avctx;

    s->out_format = FMT_H263;

    s->codec_id= avctx->codec_id;

    s->orig_width = s->width  = avctx->coded_width;

    s->orig_height= s->height = avctx->coded_height;

    s->h263_long_vectors= ((uint8_t*)avctx->extradata)[3] & 1;

    rv->sub_id = AV_RB32((uint8_t*)avctx->extradata + 4);

    major_ver = RV_GET_MAJOR_VER(rv->sub_id);

    minor_ver = RV_GET_MINOR_VER(rv->sub_id);

    micro_ver = RV_GET_MICRO_VER(rv->sub_id);

    s->low_delay = 1;

    switch (major_ver) {

    case 1:

        s->rv10_version = micro_ver ? 3 : 1;

        s->obmc = micro_ver == 2;

        break;

    case 2:

        if (minor_ver >= 2) {

            s->low_delay = 0;

            s->avctx->has_b_frames = 1;

        }

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR, "unknown header %X\n", rv->sub_id);

        av_log_missing_feature(avctx, "RV1/2 version", 1);

        return AVERROR_PATCHWELCOME;

    }

    if(avctx->debug & FF_DEBUG_PICT_INFO){

        av_log(avctx, AV_LOG_DEBUG, "ver:%X ver0:%X\n", rv->sub_id, avctx->extradata_size >= 4 ? ((uint32_t*)avctx->extradata)[0] : -1);

    }

    avctx->pix_fmt = AV_PIX_FMT_YUV420P;

    if (ff_MPV_common_init(s) < 0)

        return -1;

    ff_h263_decode_init_vlc();

    /* init rv vlc */

    if (!done) {

        INIT_VLC_STATIC(&rv_dc_lum, DC_VLC_BITS, 256,

                 rv_lum_bits, 1, 1,

                 rv_lum_code, 2, 2, 16384);

        INIT_VLC_STATIC(&rv_dc_chrom, DC_VLC_BITS, 256,

                 rv_chrom_bits, 1, 1,

                 rv_chrom_code, 2, 2, 16388);

        done = 1;

    }

    return 0;

}


static inline float32 ucf64_itos(uint32_t i)

{

    union {

        uint32_t i;

        float32 s;

    } v;

    v.i = i;

    return v.s;

}


static int get_whole_cluster(BlockDriverState *bs,

                VmdkExtent *extent,

                uint64_t cluster_offset,

                uint64_t offset,

                bool allocate)

{

    /* 128 sectors * 512 bytes each = grain size 64KB */

    uint8_t  whole_grain[extent->cluster_sectors * 512];

    /* we will be here if it's first write on non-exist grain(cluster).

     * try to read from parent image, if exist */

    if (bs->backing_hd) {

        int ret;

        if (!vmdk_is_cid_valid(bs))

            return -1;

        /* floor offset to cluster */

        offset -= offset % (extent->cluster_sectors * 512);

        ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,

                extent->cluster_sectors);

        if (ret < 0) {

            return -1;

        }

        /* Write grain only into the active image */

        ret = bdrv_write(extent->file, cluster_offset, whole_grain,

                extent->cluster_sectors);

        if (ret < 0) {

            return -1;

        }

    }

    return 0;

}


static void virtio_pci_reset(DeviceState *qdev)

{

    VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev);

    VirtioBusState *bus = VIRTIO_BUS(&proxy->bus);

    virtio_pci_stop_ioeventfd(proxy);

    virtio_bus_reset(bus);

    msix_unuse_all_vectors(&proxy->pci_dev);

    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;

}


void nbd_client_session_attach_aio_context(NbdClientSession *client,

                                           AioContext *new_context)

{

    aio_set_fd_handler(new_context, client->sock,

                       nbd_reply_ready, NULL, client);

}


int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)

{

    ram_addr_t addr;

    uint64_t bytes_transferred_last;

    double bwidth = 0;

    uint64_t expected_time = 0;

    if (stage < 0) {

        cpu_physical_memory_set_dirty_tracking(0);

        return 0;

    }

    if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {

        qemu_file_set_error(f, -EINVAL);

        return 0;

    }

    if (stage == 1) {

        RAMBlock *block;

        bytes_transferred = 0;

        last_block = NULL;

        last_offset = 0;

        sort_ram_list();

        /* Make sure all dirty bits are set */

        QLIST_FOREACH(block, &ram_list.blocks, next) {

            for (addr = block->offset; addr < block->offset + block->length;

                 addr += TARGET_PAGE_SIZE) {

                if (!cpu_physical_memory_get_dirty(addr,

                                                   MIGRATION_DIRTY_FLAG)) {

                    cpu_physical_memory_set_dirty(addr);

                }

            }

        }

        /* Enable dirty memory tracking */

        cpu_physical_memory_set_dirty_tracking(1);

        qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);

        QLIST_FOREACH(block, &ram_list.blocks, next) {

            qemu_put_byte(f, strlen(block->idstr));

            qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));

            qemu_put_be64(f, block->length);

        }

    }

    bytes_transferred_last = bytes_transferred;

    bwidth = qemu_get_clock_ns(rt_clock);

    while (!qemu_file_rate_limit(f)) {

        int bytes_sent;

        bytes_sent = ram_save_block(f);

        bytes_transferred += bytes_sent;

        if (bytes_sent == 0) { /* no more blocks */

            break;

        }

    }

    bwidth = qemu_get_clock_ns(rt_clock) - bwidth;

    bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;

    /* if we haven't transferred anything this round, force expected_time to a

     * a very high value, but without crashing */

    if (bwidth == 0) {

        bwidth = 0.000001;

    }

    /* try transferring iterative blocks of memory */

    if (stage == 3) {

        int bytes_sent;

        /* flush all remaining blocks regardless of rate limiting */

        while ((bytes_sent = ram_save_block(f)) != 0) {

            bytes_transferred += bytes_sent;

        }

        cpu_physical_memory_set_dirty_tracking(0);

    }

    qemu_put_be64(f, RAM_SAVE_FLAG_EOS);

    expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;

    return (stage == 2) && (expected_time <= migrate_max_downtime());

}


static void test_submit(void)

{

    WorkerTestData data = { .n = 0 };

    thread_pool_submit(worker_cb, &data);

    qemu_aio_flush();

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

}


int bdrv_commit(BlockDriverState *bs)

{

    BlockDriver *drv = bs->drv;

    int64_t sector, total_sectors, length, backing_length;

    int n, ro, open_flags;

    int ret = 0;

    uint8_t *buf = NULL;

    char filename[PATH_MAX];

    if (!drv)

        return -ENOMEDIUM;

    if (!bs->backing_hd) {

        return -ENOTSUP;

    }

    if (bdrv_in_use(bs) || bdrv_in_use(bs->backing_hd)) {

        return -EBUSY;

    }

    ro = bs->backing_hd->read_only;

    /* Use pstrcpy (not strncpy): filename must be NUL-terminated. */

    pstrcpy(filename, sizeof(filename), bs->backing_hd->filename);

    open_flags =  bs->backing_hd->open_flags;

    if (ro) {

        if (bdrv_reopen(bs->backing_hd, open_flags | BDRV_O_RDWR, NULL)) {

            return -EACCES;

        }

    }

    length = bdrv_getlength(bs);

    if (length < 0) {

        ret = length;

        goto ro_cleanup;

    }

    backing_length = bdrv_getlength(bs->backing_hd);

    if (backing_length < 0) {

        ret = backing_length;

        goto ro_cleanup;

    }

    /* If our top snapshot is larger than the backing file image,

     * grow the backing file image if possible.  If not possible,

     * we must return an error */

    if (length > backing_length) {

        ret = bdrv_truncate(bs->backing_hd, length);

        if (ret < 0) {

            goto ro_cleanup;

        }

    }

    total_sectors = length >> BDRV_SECTOR_BITS;

    buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);

    for (sector = 0; sector < total_sectors; sector += n) {

        ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);

        if (ret < 0) {

            goto ro_cleanup;

        }

        if (ret) {

            ret = bdrv_read(bs, sector, buf, n);

            if (ret < 0) {

                goto ro_cleanup;

            }

            ret = bdrv_write(bs->backing_hd, sector, buf, n);

            if (ret < 0) {

                goto ro_cleanup;

            }

        }

    }

    if (drv->bdrv_make_empty) {

        ret = drv->bdrv_make_empty(bs);

        if (ret < 0) {

            goto ro_cleanup;

        }

        bdrv_flush(bs);

    }

    /*

     * Make sure all data we wrote to the backing device is actually

     * stable on disk.

     */

    if (bs->backing_hd) {

        bdrv_flush(bs->backing_hd);

    }

    ret = 0;

ro_cleanup:

    g_free(buf);

    if (ro) {

        /* ignoring error return here */

        bdrv_reopen(bs->backing_hd, open_flags & ~BDRV_O_RDWR, NULL);

    }

    return ret;

}


static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)

{

    /* binary search */

    uint32_t chunk1=0,chunk2=s->n_chunks,chunk3;

    while(chunk1!=chunk2) {

	chunk3 = (chunk1+chunk2)/2;

	if(s->sectors[chunk3]>sector_num)

	    chunk2 = chunk3;

	else if(s->sectors[chunk3]+s->sectorcounts[chunk3]>sector_num)

	    return chunk3;

	else

	    chunk1 = chunk3;

    }

    return s->n_chunks; /* error */

}


static inline void RENAME(rgb32tobgr16)(const uint8_t *src, uint8_t *dst, long src_size)

{

	const uint8_t *s = src;

	const uint8_t *end;

#ifdef HAVE_MMX

	const uint8_t *mm_end;

#endif

	uint16_t *d = (uint16_t *)dst;

	end = s + src_size;

#ifdef HAVE_MMX

	__asm __volatile(PREFETCH"	%0"::"m"(*src):"memory");

	__asm __volatile(

	    "movq	%0, %%mm7\n\t"

	    "movq	%1, %%mm6\n\t"

	    ::"m"(red_16mask),"m"(green_16mask));

	mm_end = end - 15;

	while(s < mm_end)

	{

	    __asm __volatile(

		PREFETCH" 32%1\n\t"

		"movd	%1, %%mm0\n\t"

		"movd	4%1, %%mm3\n\t"

		"punpckldq 8%1, %%mm0\n\t"

		"punpckldq 12%1, %%mm3\n\t"

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

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

		"movq	%%mm3, %%mm4\n\t"

		"movq	%%mm3, %%mm5\n\t"

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

		"psllq	$8, %%mm3\n\t"

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

		"pand	%%mm7, %%mm3\n\t"

		"psrlq	$5, %%mm1\n\t"

		"psrlq	$5, %%mm4\n\t"

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

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

		"psrlq	$19, %%mm2\n\t"

		"psrlq	$19, %%mm5\n\t"

		"pand	%2, %%mm2\n\t"

		"pand	%2, %%mm5\n\t"

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

		"por	%%mm4, %%mm3\n\t"

		"por	%%mm2, %%mm0\n\t"

		"por	%%mm5, %%mm3\n\t"

		"psllq	$16, %%mm3\n\t"

		"por	%%mm3, %%mm0\n\t"

		MOVNTQ"	%%mm0, %0\n\t"

		:"=m"(*d):"m"(*s),"m"(blue_16mask):"memory");

		d += 4;

		s += 16;

	}

	__asm __volatile(SFENCE:::"memory");

	__asm __volatile(EMMS:::"memory");

#endif

	while(s < end)

	{

		register int rgb = *(uint32_t*)s; s += 4;

		*d++ = ((rgb&0xF8)<<8) + ((rgb&0xFC00)>>5) + ((rgb&0xF80000)>>19);

	}

}


static void conv411(uint8_t *dst, int dst_wrap,
                    uint8_t *src, int src_wrap,
                    int width, int height)
{
    int w, c;
    uint8_t *s1, *s2, *d;
    for(;height > 0; height--) {
        s1 = src;
        s2 = src + src_wrap;
        d = dst;
        for(w = width;w > 0; w--) {
            c = (s1[0] + s2[0]) >> 1;
            d[0] = c;
            d[1] = c;
            s1++;
            s2++;
            d += 2;
        }
        src += src_wrap * 2;
        dst += dst_wrap;
    }
}


static void *acpi_set_bsel(PCIBus *bus, void *opaque)

{

    unsigned *bsel_alloc = opaque;

    unsigned *bus_bsel;

    if (qbus_is_hotpluggable(BUS(bus))) {

        bus_bsel = g_malloc(sizeof *bus_bsel);

        *bus_bsel = (*bsel_alloc)++;

        object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,

                                       bus_bsel, NULL);

    }

    return bsel_alloc;

}


static void vncws_send_handshake_response(VncState *vs, const char* key)

{

    char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1];

    char hash[SHA1_DIGEST_LEN];

    size_t hash_size = SHA1_DIGEST_LEN;

    char *accept = NULL, *response = NULL;

    gnutls_datum_t in;

    g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1);

    g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1);

    /* hash and encode it */

    in.data = (void *)combined_key;

    in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN;

    if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size)

            == GNUTLS_E_SUCCESS) {

        accept = g_base64_encode((guchar *)hash, SHA1_DIGEST_LEN);

    }

    if (accept == NULL) {

        VNC_DEBUG("Hashing Websocket combined key failed\n");

        vnc_client_error(vs);

        return;

    }

    response = g_strdup_printf(WS_HANDSHAKE, accept);

    vnc_write(vs, response, strlen(response));

    vnc_flush(vs);

    g_free(accept);

    g_free(response);

    vs->encode_ws = 1;

    vnc_init_state(vs);

}


int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)

{

    int i, o, i0, o0, ret;

    char in_layout_name[128];

    char out_layout_name[128];

    if ( am->in_channels <= 0 ||  am->in_channels > AVRESAMPLE_MAX_CHANNELS ||

        am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {

        av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");

        return AVERROR(EINVAL);

    }

    if (am->matrix) {

        av_free(am->matrix[0]);

        am->matrix = NULL;

    }

    am->in_matrix_channels  = am->in_channels;

    am->out_matrix_channels = am->out_channels;

    reduce_matrix(am, matrix, stride);

#define CONVERT_MATRIX(type, expr)                                          \

    am->matrix_## type[0] = av_mallocz(am->out_matrix_channels *            \

                                       am->in_matrix_channels  *            \

                                       sizeof(*am->matrix_## type[0]));     \

    if (!am->matrix_## type[0])                                             \

        return AVERROR(ENOMEM);                                             \

    for (o = 0, o0 = 0; o < am->out_channels; o++) {                        \

        if (am->output_zero[o] || am->output_skip[o])                       \

            continue;                                                       \

        if (o0 > 0)                                                         \

            am->matrix_## type[o0] = am->matrix_## type[o0 - 1] +           \

                                     am->in_matrix_channels;                \

        for (i = 0, i0 = 0; i < am->in_channels; i++) {                     \

            double v;                                                       \

            if (am->input_skip[i])                                          \

                continue;                                                   \

            v = matrix[o * stride + i];                                     \

            am->matrix_## type[o0][i0] = expr;                              \

            i0++;                                                           \

        }                                                                   \

        o0++;                                                               \

    }                                                                       \

    am->matrix = (void **)am->matrix_## type;

    if (am->in_matrix_channels && am->out_matrix_channels) {

        switch (am->coeff_type) {

        case AV_MIX_COEFF_TYPE_Q8:

            CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))

            break;

        case AV_MIX_COEFF_TYPE_Q15:

            CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))

            break;

        case AV_MIX_COEFF_TYPE_FLT:

            CONVERT_MATRIX(flt, v)

            break;

        default:

            av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");

            return AVERROR(EINVAL);

        }

    }

    ret = mix_function_init(am);

    if (ret < 0)

        return ret;

    av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),

                                 am->in_channels, am->in_layout);

    av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),

                                 am->out_channels, am->out_layout);

    av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",

           in_layout_name, out_layout_name);

    av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",

           am->in_matrix_channels, am->out_matrix_channels);

    for (o = 0; o < am->out_channels; o++) {

        for (i = 0; i < am->in_channels; i++) {

            if (am->output_zero[o])

                av_log(am->avr, AV_LOG_DEBUG, "  (ZERO)");

            else if (am->input_skip[i] || am->output_skip[o])

                av_log(am->avr, AV_LOG_DEBUG, "  (SKIP)");

            else

                av_log(am->avr, AV_LOG_DEBUG, "  %0.3f ",

                       matrix[o * am->in_channels + i]);

        }

        av_log(am->avr, AV_LOG_DEBUG, "\n");

    }

    return 0;

}


BlockBackend *blk_new_open(const char *filename, const char *reference,

                           QDict *options, int flags, Error **errp)

{

    BlockBackend *blk;

    BlockDriverState *bs;

    uint64_t perm;

    /* blk_new_open() is mainly used in .bdrv_create implementations and the

     * tools where sharing isn't a concern because the BDS stays private, so we

     * just request permission according to the flags.

     *

     * The exceptions are xen_disk and blockdev_init(); in these cases, the

     * caller of blk_new_open() doesn't make use of the permissions, but they

     * shouldn't hurt either. We can still share everything here because the

     * guest devices will add their own blockers if they can't share. */

    perm = BLK_PERM_CONSISTENT_READ;

    if (flags & BDRV_O_RDWR) {

        perm |= BLK_PERM_WRITE;

    }

    if (flags & BDRV_O_RESIZE) {

        perm |= BLK_PERM_RESIZE;

    }

    blk = blk_new(perm, BLK_PERM_ALL);

    bs = bdrv_open(filename, reference, options, flags, errp);

    if (!bs) {

        blk_unref(blk);

        return NULL;

    }

    blk->root = bdrv_root_attach_child(bs, "root", &child_root,

                                       perm, BLK_PERM_ALL, blk, &error_abort);

    return blk;

}


static int pci_dec_21154_init_device(SysBusDevice *dev)

{

    UNINState *s;

    int pci_mem_config, pci_mem_data;

    /* Uninorth bridge */

    s = FROM_SYSBUS(UNINState, dev);

    // XXX: s = &pci_bridge[2];

    pci_mem_config = cpu_register_io_memory(pci_unin_config_read,

                                            pci_unin_config_write, s);

    pci_mem_data = cpu_register_io_memory(pci_unin_main_read,

                                          pci_unin_main_write, &s->host_state);

    sysbus_init_mmio(dev, 0x1000, pci_mem_config);

    sysbus_init_mmio(dev, 0x1000, pci_mem_data);

    return 0;

}


static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state)

{

    sPAPRDRConnector *drc = spapr_drc_by_index(idx);

    sPAPRDRConnectorClass *drck;

    if (!drc) {

        return RTAS_OUT_PARAM_ERROR;

    }

    drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

    return drck->set_isolation_state(drc, state);

}


static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)

{

    NFSClient *client = bs->opaque;

    NFSRPC task = {0};

    struct stat st;

    if (bdrv_is_read_only(bs) &&

        !(bs->open_flags & BDRV_O_NOCACHE)) {

        return client->st_blocks * 512;

    }

    task.st = &st;

    if (nfs_fstat_async(client->context, client->fh, nfs_co_generic_cb,

                        &task) != 0) {

        return -ENOMEM;

    }

    while (!task.complete) {

        nfs_set_events(client);

        aio_poll(client->aio_context, true);

    }

    return (task.ret < 0 ? task.ret : st.st_blocks * 512);

}


static CadenceTimerState *cadence_timer_from_addr(void *opaque,

                                        target_phys_addr_t offset)

{

    unsigned int index;

    CadenceTTCState *s = (CadenceTTCState *)opaque;

    index = (offset >> 2) % 3;

    return &s->timer[index];

}


static ssize_t net_rx_packet(NetClientState *nc, const uint8_t *buf, size_t size)

{

    struct XenNetDev *netdev = qemu_get_nic_opaque(nc);

    netif_rx_request_t rxreq;

    RING_IDX rc, rp;

    void *page;

    if (netdev->xendev.be_state != XenbusStateConnected) {

        return -1;

    }

    rc = netdev->rx_ring.req_cons;

    rp = netdev->rx_ring.sring->req_prod;

    xen_rmb(); /* Ensure we see queued requests up to 'rp'. */

    if (rc == rp || RING_REQUEST_CONS_OVERFLOW(&netdev->rx_ring, rc)) {

        xen_be_printf(&netdev->xendev, 2, "no buffer, drop packet\n");

        return -1;

    }

    if (size > XC_PAGE_SIZE - NET_IP_ALIGN) {

        xen_be_printf(&netdev->xendev, 0, "packet too big (%lu > %ld)",

                      (unsigned long)size, XC_PAGE_SIZE - NET_IP_ALIGN);

        return -1;

    }

    memcpy(&rxreq, RING_GET_REQUEST(&netdev->rx_ring, rc), sizeof(rxreq));

    netdev->rx_ring.req_cons = ++rc;

    page = xc_gnttab_map_grant_ref(netdev->xendev.gnttabdev,

                                   netdev->xendev.dom,

                                   rxreq.gref, PROT_WRITE);

    if (page == NULL) {

        xen_be_printf(&netdev->xendev, 0, "error: rx gref dereference failed (%d)\n",

                      rxreq.gref);

        net_rx_response(netdev, &rxreq, NETIF_RSP_ERROR, 0, 0, 0);

        return -1;

    }

    memcpy(page + NET_IP_ALIGN, buf, size);

    xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1);

    net_rx_response(netdev, &rxreq, NETIF_RSP_OKAY, NET_IP_ALIGN, size, 0);

    return size;

}


static void mb_add_mod(MultibootState *s,

                       target_phys_addr_t start, target_phys_addr_t end,

                       target_phys_addr_t cmdline_phys)

{

    char *p;

    assert(s->mb_mods_count < s->mb_mods_avail);

    p = (char *)s->mb_buf + s->offset_mbinfo + MB_MOD_SIZE * s->mb_mods_count;

    stl_p(p + MB_MOD_START,   start);

    stl_p(p + MB_MOD_END,     end);

    stl_p(p + MB_MOD_CMDLINE, cmdline_phys);

    mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",

             s->mb_mods_count, start, end);

    s->mb_mods_count++;

}


static void vnc_init_basic_info_from_server_addr(QIOChannelSocket *ioc,

                                                 VncBasicInfo *info,

                                                 Error **errp)

{

    SocketAddress *addr = NULL;

    if (!ioc) {

        error_setg(errp, "No listener socket available");

        return;

    }

    addr = qio_channel_socket_get_local_address(ioc, errp);

    if (!addr) {

        return;

    }

    vnc_init_basic_info(addr, info, errp);

    qapi_free_SocketAddress(addr);

}


static void nbd_teardown_connection(NbdClientSession *client)

{

    /* finish any pending coroutines */

    shutdown(client->sock, 2);

    nbd_recv_coroutines_enter_all(client);

    nbd_client_session_detach_aio_context(client);

    closesocket(client->sock);

    client->sock = -1;

}


static int usb_uhci_common_initfn(UHCIState *s)

{

    uint8_t *pci_conf = s->dev.config;

    int i;

    pci_conf[PCI_REVISION_ID] = 0x01; // revision number

    pci_conf[PCI_CLASS_PROG] = 0x00;

    pci_config_set_class(pci_conf, PCI_CLASS_SERIAL_USB);

    /* TODO: reset value should be 0. */

    pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3

    pci_conf[0x60] = 0x10; // release number

    usb_bus_new(&s->bus, &s->dev.qdev);

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

        usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,

                          USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);

        usb_port_location(&s->ports[i].port, NULL, i+1);

    }

    s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);

    s->expire_time = qemu_get_clock_ns(vm_clock) +

        (get_ticks_per_sec() / FRAME_TIMER_FREQ);

    s->num_ports_vmstate = NB_PORTS;

    qemu_register_reset(uhci_reset, s);

    /* Use region 4 for consistency with real hardware.  BSD guests seem

       to rely on this.  */

    pci_register_bar(&s->dev, 4, 0x20,

                           PCI_BASE_ADDRESS_SPACE_IO, uhci_map);

    return 0;

}


Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)

{

    Visitor *v;

    QDict *pdict;

    Object *obj;

    const char *id = qemu_opts_id(opts);

    const char *type = qemu_opt_get(opts, "qom-type");

    if (!type) {

        error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");

        return NULL;

    }

    if (!id) {

        error_setg(errp, QERR_MISSING_PARAMETER, "id");

        return NULL;

    }

    pdict = qemu_opts_to_qdict(opts, NULL);

    qdict_del(pdict, "qom-type");

    qdict_del(pdict, "id");

    v = opts_visitor_new(opts);

    obj = user_creatable_add_type(type, id, pdict, v, errp);

    visit_free(v);

    QDECREF(pdict);

    return obj;

}


int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice)

{

    MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp;

    int mmco_index = 0, i = 0;

    assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count);

    if (h->short_ref_count &&

        h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count &&

        !(FIELD_PICTURE(h) && !h->first_field && h->cur_pic_ptr->reference)) {

        mmco[0].opcode        = MMCO_SHORT2UNUSED;

        mmco[0].short_pic_num = h->short_ref[h->short_ref_count - 1]->frame_num;

        mmco_index            = 1;

        if (FIELD_PICTURE(h)) {

            mmco[0].short_pic_num *= 2;

            mmco[1].opcode         = MMCO_SHORT2UNUSED;

            mmco[1].short_pic_num  = mmco[0].short_pic_num + 1;

            mmco_index             = 2;

        }

    }

    if (first_slice) {

        h->mmco_index = mmco_index;

    } else if (!first_slice && mmco_index >= 0 &&

               (mmco_index != h->mmco_index ||

                (i = check_opcodes(h->mmco, mmco_temp, mmco_index)))) {

        av_log(h->avctx, AV_LOG_ERROR,

               "Inconsistent MMCO state between slices [%d, %d, %d]\n",

               mmco_index, h->mmco_index, i);

        return AVERROR_INVALIDDATA;

    }

    return 0;

}


static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,

    uint64_t *host_offset, unsigned int *nb_clusters)

{

    BDRVQcowState *s = bs->opaque;

    int ret;

    trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,

                                         *host_offset, *nb_clusters);

    ret = handle_dependencies(bs, guest_offset, nb_clusters);

    if (ret < 0) {

        return ret;

    }

    /* Allocate new clusters */

    trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());

    if (*host_offset == 0) {

        int64_t cluster_offset =

            qcow2_alloc_clusters(bs, *nb_clusters * s->cluster_size);

        if (cluster_offset < 0) {

            return cluster_offset;

        }

        *host_offset = cluster_offset;

        return 0;

    } else {

        ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);

        if (ret < 0) {

            return ret;

        }

        *nb_clusters = ret;

        return 0;

    }

}


static int pit_initfn(ISADevice *dev)

{

    PITState *pit = DO_UPCAST(PITState, dev, dev);

    PITChannelState *s;

    s = &pit->channels[0];

    /* the timer 0 is connected to an IRQ */

    s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);

    s->irq = isa_reserve_irq(pit->irq);

    register_ioport_write(pit->iobase, 4, 1, pit_ioport_write, pit);

    register_ioport_read(pit->iobase, 3, 1, pit_ioport_read, pit);

    isa_init_ioport(dev, pit->iobase);

    return 0;

}


int64_t bdrv_get_block_status_above(BlockDriverState *bs,

                                    BlockDriverState *base,

                                    int64_t sector_num,

                                    int nb_sectors, int *pnum)

{

    Coroutine *co;

    BdrvCoGetBlockStatusData data = {

        .bs = bs,

        .base = base,

        .sector_num = sector_num,

        .nb_sectors = nb_sectors,

        .pnum = pnum,

        .done = false,

    };

    if (qemu_in_coroutine()) {

        /* Fast-path if already in coroutine context */

        bdrv_get_block_status_above_co_entry(&data);

    } else {

        AioContext *aio_context = bdrv_get_aio_context(bs);

        co = qemu_coroutine_create(bdrv_get_block_status_above_co_entry);

        qemu_coroutine_enter(co, &data);

        while (!data.done) {

            aio_poll(aio_context, true);

        }

    }

    return data.ret;

}


static int usb_linux_update_endp_table(USBHostDevice *s)

{

    uint8_t *descriptors;

    uint8_t devep, type, alt_interface;

    int interface, length, i, ep, pid;

    struct endp_data *epd;

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

        s->ep_in[i].type = INVALID_EP_TYPE;

        s->ep_out[i].type = INVALID_EP_TYPE;

    }

    if (s->configuration == 0) {

        /* not configured yet -- leave all endpoints disabled */

        return 0;

    }

    /* get the desired configuration, interface, and endpoint descriptors

     * from device description */

    descriptors = &s->descr[18];

    length = s->descr_len - 18;

    i = 0;

    if (descriptors[i + 1] != USB_DT_CONFIG ||

        descriptors[i + 5] != s->configuration) {

        fprintf(stderr, "invalid descriptor data - configuration %d\n",

                s->configuration);

        return 1;

    }

    i += descriptors[i];

    while (i < length) {

        if (descriptors[i + 1] != USB_DT_INTERFACE ||

            (descriptors[i + 1] == USB_DT_INTERFACE &&

             descriptors[i + 4] == 0)) {

            i += descriptors[i];

            continue;

        }

        interface = descriptors[i + 2];

        alt_interface = usb_linux_get_alt_setting(s, s->configuration,

                                                  interface);

        /* the current interface descriptor is the active interface

         * and has endpoints */

        if (descriptors[i + 3] != alt_interface) {

            i += descriptors[i];

            continue;

        }

        /* advance to the endpoints */

        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {

            i += descriptors[i];

        }

        if (i >= length)

            break;

        while (i < length) {

            if (descriptors[i + 1] != USB_DT_ENDPOINT) {

                break;

            }

            devep = descriptors[i + 2];

            pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;

            ep = devep & 0xf;

            if (ep == 0) {

                fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");

                return 1;

            }

            switch (descriptors[i + 3] & 0x3) {

            case 0x00:

                type = USBDEVFS_URB_TYPE_CONTROL;

                break;

            case 0x01:

                type = USBDEVFS_URB_TYPE_ISO;

                set_max_packet_size(s, pid, ep, descriptors + i);

                break;

            case 0x02:

                type = USBDEVFS_URB_TYPE_BULK;

                break;

            case 0x03:

                type = USBDEVFS_URB_TYPE_INTERRUPT;

                break;

            default:

                DPRINTF("usb_host: malformed endpoint type\n");

                type = USBDEVFS_URB_TYPE_BULK;

            }

            epd = get_endp(s, pid, ep);

            assert(epd->type == INVALID_EP_TYPE);

            epd->type = type;

            epd->halted = 0;

            i += descriptors[i];

        }

    }

    return 0;

}


pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri)

{

    int i;

    uint32_t len_log2;

    uint32_t ring_size;

    if (ri->numPages > PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES) {

        return -1;

    }

    ring_size = ri->numPages * PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE;

    len_log2 = pvscsi_log2(ring_size - 1);

    m->msg_len_mask = MASK(len_log2);

    m->filled_msg_ptr = 0;

    for (i = 0; i < ri->numPages; i++) {

        m->msg_ring_pages_pa[i] = ri->ringPPNs[i] << VMW_PAGE_SHIFT;

    }

    RS_SET_FIELD(m, msgProdIdx, 0);

    RS_SET_FIELD(m, msgConsIdx, 0);

    RS_SET_FIELD(m, msgNumEntriesLog2, len_log2);

    trace_pvscsi_ring_init_msg(len_log2);

    /* Flush ring state page changes */

    smp_wmb();

    return 0;

}


void ppc_hash64_stop_access(PowerPCCPU *cpu, uint64_t token)

{

    if (cpu->env.external_htab == MMU_HASH64_KVM_MANAGED_HPT) {

        kvmppc_hash64_free_pteg(token);

    }

}


static void puv3_load_kernel(const char *kernel_filename)

{

    int size;

    assert(kernel_filename != NULL);

    /* only zImage format supported */

    size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,

            KERNEL_MAX_SIZE);

    if (size < 0) {

        hw_error("Load kernel error: '%s'\n", kernel_filename);

    }

    /* cheat curses that we have a graphic console, only under ocd console */

    graphic_console_init(NULL, NULL, NULL, NULL, NULL);

}


static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma,

                               int current_index, uint64_t current_addr,

                               uint64_t length)

{

    struct ibv_sge sge;

    struct ibv_send_wr send_wr = { 0 };

    struct ibv_send_wr *bad_wr;

    int reg_result_idx, ret, count = 0;

    uint64_t chunk, chunks;

    uint8_t *chunk_start, *chunk_end;

    RDMALocalBlock *block = &(rdma->local_ram_blocks.block[current_index]);

    RDMARegister reg;

    RDMARegisterResult *reg_result;

    RDMAControlHeader resp = { .type = RDMA_CONTROL_REGISTER_RESULT };

    RDMAControlHeader head = { .len = sizeof(RDMARegister),

                               .type = RDMA_CONTROL_REGISTER_REQUEST,

                               .repeat = 1,

                             };

retry:

    sge.addr = (uint64_t)(block->local_host_addr +

                            (current_addr - block->offset));

    sge.length = length;

    chunk = ram_chunk_index(block->local_host_addr, (uint8_t *) sge.addr);

    chunk_start = ram_chunk_start(block, chunk);

    if (block->is_ram_block) {

        chunks = length / (1UL << RDMA_REG_CHUNK_SHIFT);

        if (chunks && ((length % (1UL << RDMA_REG_CHUNK_SHIFT)) == 0)) {

            chunks--;

        }

    } else {

        chunks = block->length / (1UL << RDMA_REG_CHUNK_SHIFT);

        if (chunks && ((block->length % (1UL << RDMA_REG_CHUNK_SHIFT)) == 0)) {

            chunks--;

        }

    }

    DDPRINTF("Writing %" PRIu64 " chunks, (%" PRIu64 " MB)\n",

        chunks + 1, (chunks + 1) * (1UL << RDMA_REG_CHUNK_SHIFT) / 1024 / 1024);

    chunk_end = ram_chunk_end(block, chunk + chunks);

    if (!rdma->pin_all) {

#ifdef RDMA_UNREGISTRATION_EXAMPLE

        qemu_rdma_unregister_waiting(rdma);

#endif

    }

    while (test_bit(chunk, block->transit_bitmap)) {

        (void)count;

        DDPRINTF("(%d) Not clobbering: block: %d chunk %" PRIu64

                " current %" PRIu64 " len %" PRIu64 " %d %d\n",

                count++, current_index, chunk,

                sge.addr, length, rdma->nb_sent, block->nb_chunks);

        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);

        if (ret < 0) {

            fprintf(stderr, "Failed to Wait for previous write to complete "

                    "block %d chunk %" PRIu64

                    " current %" PRIu64 " len %" PRIu64 " %d\n",

                    current_index, chunk, sge.addr, length, rdma->nb_sent);

            return ret;

        }

    }

    if (!rdma->pin_all || !block->is_ram_block) {

        if (!block->remote_keys[chunk]) {

            /*

             * This chunk has not yet been registered, so first check to see

             * if the entire chunk is zero. If so, tell the other size to

             * memset() + madvise() the entire chunk without RDMA.

             */

            if (can_use_buffer_find_nonzero_offset((void *)sge.addr, length)

                   && buffer_find_nonzero_offset((void *)sge.addr,

                                                    length) == length) {

                RDMACompress comp = {

                                        .offset = current_addr,

                                        .value = 0,

                                        .block_idx = current_index,

                                        .length = length,

                                    };

                head.len = sizeof(comp);

                head.type = RDMA_CONTROL_COMPRESS;

                DDPRINTF("Entire chunk is zero, sending compress: %"

                    PRIu64 " for %d "

                    "bytes, index: %d, offset: %" PRId64 "...\n",

                    chunk, sge.length, current_index, current_addr);

                compress_to_network(&comp);

                ret = qemu_rdma_exchange_send(rdma, &head,

                                (uint8_t *) &comp, NULL, NULL, NULL);

                if (ret < 0) {

                    return -EIO;

                }

                acct_update_position(f, sge.length, true);

                return 1;

            }

            /*

             * Otherwise, tell other side to register.

             */

            reg.current_index = current_index;

            if (block->is_ram_block) {

                reg.key.current_addr = current_addr;

            } else {

                reg.key.chunk = chunk;

            }

            reg.chunks = chunks;

            DDPRINTF("Sending registration request chunk %" PRIu64 " for %d "

                    "bytes, index: %d, offset: %" PRId64 "...\n",

                    chunk, sge.length, current_index, current_addr);

            register_to_network(&reg);

            ret = qemu_rdma_exchange_send(rdma, &head, (uint8_t *) &reg,

                                    &resp, &reg_result_idx, NULL);

            if (ret < 0) {

                return ret;

            }

            /* try to overlap this single registration with the one we sent. */

            if (qemu_rdma_register_and_get_keys(rdma, block,

                                                (uint8_t *) sge.addr,

                                                &sge.lkey, NULL, chunk,

                                                chunk_start, chunk_end)) {

                fprintf(stderr, "cannot get lkey!\n");

                return -EINVAL;

            }

            reg_result = (RDMARegisterResult *)

                    rdma->wr_data[reg_result_idx].control_curr;

            network_to_result(reg_result);

            DDPRINTF("Received registration result:"

                    " my key: %x their key %x, chunk %" PRIu64 "\n",

                    block->remote_keys[chunk], reg_result->rkey, chunk);

            block->remote_keys[chunk] = reg_result->rkey;

            block->remote_host_addr = reg_result->host_addr;

        } else {

            /* already registered before */

            if (qemu_rdma_register_and_get_keys(rdma, block,

                                                (uint8_t *)sge.addr,

                                                &sge.lkey, NULL, chunk,

                                                chunk_start, chunk_end)) {

                fprintf(stderr, "cannot get lkey!\n");

                return -EINVAL;

            }

        }

        send_wr.wr.rdma.rkey = block->remote_keys[chunk];

    } else {

        send_wr.wr.rdma.rkey = block->remote_rkey;

        if (qemu_rdma_register_and_get_keys(rdma, block, (uint8_t *)sge.addr,

                                                     &sge.lkey, NULL, chunk,

                                                     chunk_start, chunk_end)) {

            fprintf(stderr, "cannot get lkey!\n");

            return -EINVAL;

        }

    }

    /*

     * Encode the ram block index and chunk within this wrid.

     * We will use this information at the time of completion

     * to figure out which bitmap to check against and then which

     * chunk in the bitmap to look for.

     */

    send_wr.wr_id = qemu_rdma_make_wrid(RDMA_WRID_RDMA_WRITE,

                                        current_index, chunk);

    send_wr.opcode = IBV_WR_RDMA_WRITE;

    send_wr.send_flags = IBV_SEND_SIGNALED;

    send_wr.sg_list = &sge;

    send_wr.num_sge = 1;

    send_wr.wr.rdma.remote_addr = block->remote_host_addr +

                                (current_addr - block->offset);

    DDDPRINTF("Posting chunk: %" PRIu64 ", addr: %lx"

              " remote: %lx, bytes %" PRIu32 "\n",

              chunk, sge.addr, send_wr.wr.rdma.remote_addr,

              sge.length);

    /*

     * ibv_post_send() does not return negative error numbers,

     * per the specification they are positive - no idea why.

     */

    ret = ibv_post_send(rdma->qp, &send_wr, &bad_wr);

    if (ret == ENOMEM) {

        DDPRINTF("send queue is full. wait a little....\n");

        ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);

        if (ret < 0) {

            fprintf(stderr, "rdma migration: failed to make "

                            "room in full send queue! %d\n", ret);

            return ret;

        }

        goto retry;

    } else if (ret > 0) {

        perror("rdma migration: post rdma write failed");

        return -ret;

    }

    set_bit(chunk, block->transit_bitmap);

    acct_update_position(f, sge.length, false);

    rdma->total_writes++;

    return 0;

}


void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,

                      bool has_base, const char *base,

                      bool has_top, const char *top,

                      bool has_backing_file, const char *backing_file,

                      bool has_speed, int64_t speed,

                      Error **errp)

{

    BlockDriverState *bs;

    BlockDriverState *base_bs, *top_bs;

    AioContext *aio_context;

    Error *local_err = NULL;

    /* This will be part of the QMP command, if/when the

     * BlockdevOnError change for blkmirror makes it in

     */

    BlockdevOnError on_error = BLOCKDEV_ON_ERROR_REPORT;

    if (!has_speed) {

        speed = 0;

    }

    /* Important Note:

     *  libvirt relies on the DeviceNotFound error class in order to probe for

     *  live commit feature versions; for this to work, we must make sure to

     *  perform the device lookup before any generic errors that may occur in a

     *  scenario in which all optional arguments are omitted. */

    bs = qmp_get_root_bs(device, &local_err);

    if (!bs) {

        bs = bdrv_lookup_bs(device, device, NULL);

        if (!bs) {

            error_free(local_err);

            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,

                      "Device '%s' not found", device);

        } else {

            error_propagate(errp, local_err);

        }

        return;

    }

    aio_context = bdrv_get_aio_context(bs);

    aio_context_acquire(aio_context);

    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, errp)) {

        goto out;

    }

    /* default top_bs is the active layer */

    top_bs = bs;

    if (has_top && top) {

        if (strcmp(bs->filename, top) != 0) {

            top_bs = bdrv_find_backing_image(bs, top);

        }

    }

    if (top_bs == NULL) {

        error_setg(errp, "Top image file %s not found", top ? top : "NULL");

        goto out;

    }

    assert(bdrv_get_aio_context(top_bs) == aio_context);

    if (has_base && base) {

        base_bs = bdrv_find_backing_image(top_bs, base);

    } else {

        base_bs = bdrv_find_base(top_bs);

    }

    if (base_bs == NULL) {

        error_setg(errp, QERR_BASE_NOT_FOUND, base ? base : "NULL");

        goto out;

    }

    assert(bdrv_get_aio_context(base_bs) == aio_context);

    if (bdrv_op_is_blocked(base_bs, BLOCK_OP_TYPE_COMMIT_TARGET, errp)) {

        goto out;

    }

    /* Do not allow attempts to commit an image into itself */

    if (top_bs == base_bs) {

        error_setg(errp, "cannot commit an image into itself");

        goto out;

    }

    if (top_bs == bs) {

        if (has_backing_file) {

            error_setg(errp, "'backing-file' specified,"

                             " but 'top' is the active layer");

            goto out;

        }

        commit_active_start(has_job_id ? job_id : NULL, bs, base_bs, speed,

                            on_error, block_job_cb, bs, &local_err, false);

    } else {

        commit_start(has_job_id ? job_id : NULL, bs, base_bs, top_bs, speed,

                     on_error, block_job_cb, bs,

                     has_backing_file ? backing_file : NULL, &local_err);

    }

    if (local_err != NULL) {

        error_propagate(errp, local_err);

        goto out;

    }

out:

    aio_context_release(aio_context);

}


static void ffmpeg_cleanup(int ret)

{

    int i, j;

    if (do_benchmark) {

        int maxrss = getmaxrss() / 1024;

        printf("bench: maxrss=%ikB\n", maxrss);

    }

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

        FilterGraph *fg = filtergraphs[i];

        avfilter_graph_free(&fg->graph);

        for (j = 0; j < fg->nb_inputs; j++) {

            av_freep(&fg->inputs[j]->name);

            av_freep(&fg->inputs[j]);

        }

        av_freep(&fg->inputs);

        for (j = 0; j < fg->nb_outputs; j++) {

            av_freep(&fg->outputs[j]->name);

            av_freep(&fg->outputs[j]);

        }

        av_freep(&fg->outputs);

        av_freep(&fg->graph_desc);

        av_freep(&filtergraphs[i]);

    }

    av_freep(&filtergraphs);

    av_freep(&subtitle_out);

    /* close files */

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

        OutputFile *of = output_files[i];

        AVFormatContext *s = of->ctx;

        if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE) && s->pb)

            avio_closep(&s->pb);

        avformat_free_context(s);

        av_dict_free(&of->opts);

        av_freep(&output_files[i]);

    }

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

        OutputStream *ost = output_streams[i];

        AVBitStreamFilterContext *bsfc = ost->bitstream_filters;

        while (bsfc) {

            AVBitStreamFilterContext *next = bsfc->next;

            av_bitstream_filter_close(bsfc);

            bsfc = next;

        }

        ost->bitstream_filters = NULL;

        av_frame_free(&ost->filtered_frame);

        av_frame_free(&ost->last_frame);

        av_parser_close(ost->parser);

        av_freep(&ost->forced_keyframes);

        av_expr_free(ost->forced_keyframes_pexpr);

        av_freep(&ost->avfilter);

        av_freep(&ost->logfile_prefix);

        av_freep(&ost->audio_channels_map);

        ost->audio_channels_mapped = 0;

        avcodec_free_context(&ost->enc_ctx);

        av_freep(&output_streams[i]);

    }

#if HAVE_PTHREADS

    free_input_threads();

#endif

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

        avformat_close_input(&input_files[i]->ctx);

        av_freep(&input_files[i]);

    }

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

        InputStream *ist = input_streams[i];

        av_frame_free(&ist->decoded_frame);

        av_frame_free(&ist->filter_frame);

        av_dict_free(&ist->decoder_opts);

        avsubtitle_free(&ist->prev_sub.subtitle);

        av_frame_free(&ist->sub2video.frame);

        av_freep(&ist->filters);

        av_freep(&ist->hwaccel_device);

        avcodec_free_context(&ist->dec_ctx);

        av_freep(&input_streams[i]);

    }

    if (vstats_file)

        fclose(vstats_file);

    av_freep(&vstats_filename);

    av_freep(&input_streams);

    av_freep(&input_files);

    av_freep(&output_streams);

    av_freep(&output_files);

    uninit_opts();

    avformat_network_deinit();

    if (received_sigterm) {

        av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n",

               (int) received_sigterm);

    } else if (ret && transcode_init_done) {

        av_log(NULL, AV_LOG_INFO, "Conversion failed!\n");

    }

    term_exit();

}


Aml *aml_local(int num)

{

    Aml *var;

    uint8_t op = 0x60 /* Local0Op */ + num;

    assert(num <= 7);

    var = aml_opcode(op);

    return var;

}


static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)

{

    static const TCGTargetOpDef r = { .args_ct_str = { "r" } };

    static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };

    static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };

    static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };

    static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };

    static const TCGTargetOpDef r_rC = { .args_ct_str = { "r", "rC" } };

    static const TCGTargetOpDef r_rZ = { .args_ct_str = { "r", "rZ" } };

    static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };

    static const TCGTargetOpDef r_0_ri = { .args_ct_str = { "r", "0", "ri" } };

    static const TCGTargetOpDef r_0_rI = { .args_ct_str = { "r", "0", "rI" } };

    static const TCGTargetOpDef r_0_rJ = { .args_ct_str = { "r", "0", "rJ" } };

    static const TCGTargetOpDef r_0_rO = { .args_ct_str = { "r", "0", "rO" } };

    static const TCGTargetOpDef r_0_rX = { .args_ct_str = { "r", "0", "rX" } };

    switch (op) {

    case INDEX_op_goto_ptr:

        return &r;

    case INDEX_op_ld8u_i32:

    case INDEX_op_ld8u_i64:

    case INDEX_op_ld8s_i32:

    case INDEX_op_ld8s_i64:

    case INDEX_op_ld16u_i32:

    case INDEX_op_ld16u_i64:

    case INDEX_op_ld16s_i32:

    case INDEX_op_ld16s_i64:

    case INDEX_op_ld_i32:

    case INDEX_op_ld32u_i64:

    case INDEX_op_ld32s_i64:

    case INDEX_op_ld_i64:

    case INDEX_op_st8_i32:

    case INDEX_op_st8_i64:

    case INDEX_op_st16_i32:

    case INDEX_op_st16_i64:

    case INDEX_op_st_i32:

    case INDEX_op_st32_i64:

    case INDEX_op_st_i64:

        return &r_r;

    case INDEX_op_add_i32:

    case INDEX_op_add_i64:

        return &r_r_ri;

    case INDEX_op_sub_i32:

    case INDEX_op_sub_i64:

        return &r_0_ri;

    case INDEX_op_mul_i32:

        /* If we have the general-instruction-extensions, then we have

           MULTIPLY SINGLE IMMEDIATE with a signed 32-bit, otherwise we

           have only MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit.  */

        return (s390_facilities & FACILITY_GEN_INST_EXT ? &r_0_ri : &r_0_rI);

    case INDEX_op_mul_i64:

        return (s390_facilities & FACILITY_GEN_INST_EXT ? &r_0_rJ : &r_0_rI);

    case INDEX_op_or_i32:

    case INDEX_op_or_i64:

        return &r_0_rO;

    case INDEX_op_xor_i32:

    case INDEX_op_xor_i64:

        return &r_0_rX;

    case INDEX_op_and_i32:

    case INDEX_op_and_i64:

        return &r_0_ri;

    case INDEX_op_shl_i32:

    case INDEX_op_shr_i32:

    case INDEX_op_sar_i32:

        return &r_0_ri;

    case INDEX_op_shl_i64:

    case INDEX_op_shr_i64:

    case INDEX_op_sar_i64:

        return &r_r_ri;

    case INDEX_op_rotl_i32:

    case INDEX_op_rotl_i64:

    case INDEX_op_rotr_i32:

    case INDEX_op_rotr_i64:

        return &r_r_ri;

    case INDEX_op_brcond_i32:

        /* Without EXT_IMM, only the LOAD AND TEST insn is available.  */

        return (s390_facilities & FACILITY_EXT_IMM ? &r_ri : &r_rZ);

    case INDEX_op_brcond_i64:

        return (s390_facilities & FACILITY_EXT_IMM ? &r_rC : &r_rZ);

    case INDEX_op_bswap16_i32:

    case INDEX_op_bswap16_i64:

    case INDEX_op_bswap32_i32:

    case INDEX_op_bswap32_i64:

    case INDEX_op_bswap64_i64:

    case INDEX_op_neg_i32:

    case INDEX_op_neg_i64:

    case INDEX_op_ext8s_i32:

    case INDEX_op_ext8s_i64:

    case INDEX_op_ext8u_i32:

    case INDEX_op_ext8u_i64:

    case INDEX_op_ext16s_i32:

    case INDEX_op_ext16s_i64:

    case INDEX_op_ext16u_i32:

    case INDEX_op_ext16u_i64:

    case INDEX_op_ext32s_i64:

    case INDEX_op_ext32u_i64:

    case INDEX_op_ext_i32_i64:

    case INDEX_op_extu_i32_i64:

    case INDEX_op_extract_i32:

    case INDEX_op_extract_i64:

        return &r_r;

    case INDEX_op_clz_i64:

        return &r_r_ri;

    case INDEX_op_qemu_ld_i32:

    case INDEX_op_qemu_ld_i64:

        return &r_L;

    case INDEX_op_qemu_st_i64:

    case INDEX_op_qemu_st_i32:

        return &L_L;

    case INDEX_op_deposit_i32:

    case INDEX_op_deposit_i64:

        {

            static const TCGTargetOpDef dep

                = { .args_ct_str = { "r", "rZ", "r" } };

            return &dep;

        }

    case INDEX_op_setcond_i32:

    case INDEX_op_setcond_i64:

        {

            /* Without EXT_IMM, only the LOAD AND TEST insn is available.  */

            static const TCGTargetOpDef setc_z

                = { .args_ct_str = { "r", "r", "rZ" } };

            static const TCGTargetOpDef setc_c

                = { .args_ct_str = { "r", "r", "rC" } };

            return (s390_facilities & FACILITY_EXT_IMM ? &setc_c : &setc_z);

        }

    case INDEX_op_movcond_i32:

    case INDEX_op_movcond_i64:

        {

            /* Without EXT_IMM, only the LOAD AND TEST insn is available.  */

            static const TCGTargetOpDef movc_z

                = { .args_ct_str = { "r", "r", "rZ", "r", "0" } };

            static const TCGTargetOpDef movc_c

                = { .args_ct_str = { "r", "r", "rC", "r", "0" } };

            return (s390_facilities & FACILITY_EXT_IMM ? &movc_c : &movc_z);

        }

    case INDEX_op_div2_i32:

    case INDEX_op_div2_i64:

    case INDEX_op_divu2_i32:

    case INDEX_op_divu2_i64:

        {

            static const TCGTargetOpDef div2

                = { .args_ct_str = { "b", "a", "0", "1", "r" } };

            return &div2;

        }

    case INDEX_op_mulu2_i64:

        {

            static const TCGTargetOpDef mul2

                = { .args_ct_str = { "b", "a", "0", "r" } };

            return &mul2;

        }

    case INDEX_op_add2_i32:

    case INDEX_op_add2_i64:

    case INDEX_op_sub2_i32:

    case INDEX_op_sub2_i64:

        {

            static const TCGTargetOpDef arith2

                = { .args_ct_str = { "r", "r", "0", "1", "rA", "r" } };

            return &arith2;

        }

    default:

        break;

    }

    return NULL;

}


void portio_list_del(PortioList *piolist)

{

    MemoryRegion *mr, *alias;

    unsigned i;

    for (i = 0; i < piolist->nr; ++i) {

        mr = piolist->regions[i];

        alias = piolist->aliases[i];

        memory_region_del_subregion(piolist->address_space, alias);

        memory_region_destroy(alias);

        memory_region_destroy(mr);

        g_free((MemoryRegionOps *)mr->ops);

        g_free(mr);

        g_free(alias);

        piolist->regions[i] = NULL;

        piolist->aliases[i] = NULL;

    }

}


static void set_gsi(KVMState *s, unsigned int gsi)

{

    assert(gsi < s->max_gsi);

    s->used_gsi_bitmap[gsi / 32] |= 1U << (gsi % 32);

}


void arm_cpu_do_interrupt(CPUState *cs)

{

    ARMCPU *cpu = ARM_CPU(cs);

    CPUARMState *env = &cpu->env;

    uint32_t addr;

    uint32_t mask;

    int new_mode;

    uint32_t offset;

    uint32_t moe;

    assert(!IS_M(env));

    arm_log_exception(cs->exception_index);

    if (arm_is_psci_call(cpu, cs->exception_index)) {

        arm_handle_psci_call(cpu);

        qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n");

        return;

    }

    /* If this is a debug exception we must update the DBGDSCR.MOE bits */

    switch (env->exception.syndrome >> ARM_EL_EC_SHIFT) {

    case EC_BREAKPOINT:

    case EC_BREAKPOINT_SAME_EL:

        moe = 1;

        break;

    case EC_WATCHPOINT:

    case EC_WATCHPOINT_SAME_EL:

        moe = 10;

        break;

    case EC_AA32_BKPT:

        moe = 3;

        break;

    case EC_VECTORCATCH:

        moe = 5;

        break;

    default:

        moe = 0;

        break;

    }

    if (moe) {

        env->cp15.mdscr_el1 = deposit64(env->cp15.mdscr_el1, 2, 4, moe);

    }

    /* TODO: Vectored interrupt controller.  */

    switch (cs->exception_index) {

    case EXCP_UDEF:

        new_mode = ARM_CPU_MODE_UND;

        addr = 0x04;

        mask = CPSR_I;

        if (env->thumb)

            offset = 2;

        else

            offset = 4;

        break;

    case EXCP_SWI:

        if (semihosting_enabled) {

            /* Check for semihosting interrupt.  */

            if (env->thumb) {

                mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)

                    & 0xff;

            } else {

                mask = arm_ldl_code(env, env->regs[15] - 4, env->bswap_code)

                    & 0xffffff;

            }

            /* Only intercept calls from privileged modes, to provide some

               semblance of security.  */

            if (((mask == 0x123456 && !env->thumb)

                    || (mask == 0xab && env->thumb))

                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {

                env->regs[0] = do_arm_semihosting(env);

                qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");

                return;

            }

        }

        new_mode = ARM_CPU_MODE_SVC;

        addr = 0x08;

        mask = CPSR_I;

        /* The PC already points to the next instruction.  */

        offset = 0;

        break;

    case EXCP_BKPT:

        /* See if this is a semihosting syscall.  */

        if (env->thumb && semihosting_enabled) {

            mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;

            if (mask == 0xab

                  && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {

                env->regs[15] += 2;

                env->regs[0] = do_arm_semihosting(env);

                qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");

                return;

            }

        }

        env->exception.fsr = 2;

        /* Fall through to prefetch abort.  */

    case EXCP_PREFETCH_ABORT:

        env->cp15.ifsr_el2 = env->exception.fsr;

        env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 32, 32,

                                        env->exception.vaddress);

        qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",

                      env->cp15.ifsr_el2, (uint32_t)env->exception.vaddress);

        new_mode = ARM_CPU_MODE_ABT;

        addr = 0x0c;

        mask = CPSR_A | CPSR_I;

        offset = 4;

        break;

    case EXCP_DATA_ABORT:

        env->cp15.esr_el[1] = env->exception.fsr;

        env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 0, 32,

                                        env->exception.vaddress);

        qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",

                      (uint32_t)env->cp15.esr_el[1],

                      (uint32_t)env->exception.vaddress);

        new_mode = ARM_CPU_MODE_ABT;

        addr = 0x10;

        mask = CPSR_A | CPSR_I;

        offset = 8;

        break;

    case EXCP_IRQ:

        new_mode = ARM_CPU_MODE_IRQ;

        addr = 0x18;

        /* Disable IRQ and imprecise data aborts.  */

        mask = CPSR_A | CPSR_I;

        offset = 4;

        if (env->cp15.scr_el3 & SCR_IRQ) {

            /* IRQ routed to monitor mode */

            new_mode = ARM_CPU_MODE_MON;

            mask |= CPSR_F;

        }

        break;

    case EXCP_FIQ:

        new_mode = ARM_CPU_MODE_FIQ;

        addr = 0x1c;

        /* Disable FIQ, IRQ and imprecise data aborts.  */

        mask = CPSR_A | CPSR_I | CPSR_F;

        if (env->cp15.scr_el3 & SCR_FIQ) {

            /* FIQ routed to monitor mode */

            new_mode = ARM_CPU_MODE_MON;

        }

        offset = 4;

        break;

    case EXCP_SMC:

        new_mode = ARM_CPU_MODE_MON;

        addr = 0x08;

        mask = CPSR_A | CPSR_I | CPSR_F;

        offset = 0;

        break;

    default:

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

        return; /* Never happens.  Keep compiler happy.  */

    }

    if (new_mode == ARM_CPU_MODE_MON) {

        addr += env->cp15.mvbar;

    } else if (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_V) {

        /* High vectors. When enabled, base address cannot be remapped. */

        addr += 0xffff0000;

    } else {

        /* ARM v7 architectures provide a vector base address register to remap

         * the interrupt vector table.

         * This register is only followed in non-monitor mode, and is banked.

         * Note: only bits 31:5 are valid.

         */

        addr += env->cp15.vbar_el[1];

    }

    if ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_MON) {

        env->cp15.scr_el3 &= ~SCR_NS;

    }

    switch_mode (env, new_mode);

    /* For exceptions taken to AArch32 we must clear the SS bit in both

     * PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.

     */

    env->uncached_cpsr &= ~PSTATE_SS;

    env->spsr = cpsr_read(env);

    /* Clear IT bits.  */

    env->condexec_bits = 0;

    /* Switch to the new mode, and to the correct instruction set.  */

    env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;

    env->daif |= mask;

    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares

     * and we should just guard the thumb mode on V4 */

    if (arm_feature(env, ARM_FEATURE_V4T)) {

        env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;

    }

    env->regs[14] = env->regs[15] + offset;

    env->regs[15] = addr;

    cs->interrupt_request |= CPU_INTERRUPT_EXITTB;

}