static int coroutine_fn backup_do_cow(BackupBlockJob *job,

                                      int64_t sector_num, int nb_sectors,

                                      bool *error_is_read,

                                      bool is_write_notifier)

{

    BlockBackend *blk = job->common.blk;

    CowRequest cow_request;

    struct iovec iov;

    QEMUIOVector bounce_qiov;

    void *bounce_buffer = NULL;

    int ret = 0;

    int64_t sectors_per_cluster = cluster_size_sectors(job);

    int64_t start, end;

    int n;

    qemu_co_rwlock_rdlock(&job->flush_rwlock);

    start = sector_num / sectors_per_cluster;

    end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);

    trace_backup_do_cow_enter(job, start, sector_num, nb_sectors);

    wait_for_overlapping_requests(job, start, end);

    cow_request_begin(&cow_request, job, start, end);

    for (; start < end; start++) {

        if (test_bit(start, job->done_bitmap)) {

            trace_backup_do_cow_skip(job, start);

            continue; /* already copied */

        }

        trace_backup_do_cow_process(job, start);

        n = MIN(sectors_per_cluster,

                job->common.len / BDRV_SECTOR_SIZE -

                start * sectors_per_cluster);

        if (!bounce_buffer) {

            bounce_buffer = blk_blockalign(blk, job->cluster_size);

        }

        iov.iov_base = bounce_buffer;

        iov.iov_len = n * BDRV_SECTOR_SIZE;

        qemu_iovec_init_external(&bounce_qiov, &iov, 1);

        ret = blk_co_preadv(blk, start * job->cluster_size,

                            bounce_qiov.size, &bounce_qiov,

                            is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);

        if (ret < 0) {

            trace_backup_do_cow_read_fail(job, start, ret);

            if (error_is_read) {

                *error_is_read = true;

            }

            goto out;

        }

        if (buffer_is_zero(iov.iov_base, iov.iov_len)) {

            ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,

                                       bounce_qiov.size, BDRV_REQ_MAY_UNMAP);

        } else {

            ret = blk_co_pwritev(job->target, start * job->cluster_size,

                                 bounce_qiov.size, &bounce_qiov, 0);

        }

        if (ret < 0) {

            trace_backup_do_cow_write_fail(job, start, ret);

            if (error_is_read) {

                *error_is_read = false;

            }

            goto out;

        }

        set_bit(start, job->done_bitmap);

        /* Publish progress, guest I/O counts as progress too.  Note that the

         * offset field is an opaque progress value, it is not a disk offset.

         */

        job->sectors_read += n;

        job->common.offset += n * BDRV_SECTOR_SIZE;

    }

out:

    if (bounce_buffer) {

        qemu_vfree(bounce_buffer);

    }

    cow_request_end(&cow_request);

    trace_backup_do_cow_return(job, sector_num, nb_sectors, ret);

    qemu_co_rwlock_unlock(&job->flush_rwlock);

    return ret;

}


static inline int memory_access_size(MemoryRegion *mr, int l, hwaddr addr)

{

    if (l >= 4 && (((addr & 3) == 0 || mr->ops->impl.unaligned))) {

        return 4;

    }

    if (l >= 2 && (((addr & 1) == 0) || mr->ops->impl.unaligned)) {

        return 2;

    }

    return 1;

}


static void bonito_spciconf_writew(void *opaque, target_phys_addr_t addr,

                                   uint32_t val)

{

    PCIBonitoState *s = opaque;

    PCIDevice *d = PCI_DEVICE(s);

    PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);

    uint32_t pciaddr;

    uint16_t status;

    DPRINTF("bonito_spciconf_writew "TARGET_FMT_plx" val %x\n", addr, val);

    assert((addr & 0x1) == 0);

    pciaddr = bonito_sbridge_pciaddr(s, addr);

    if (pciaddr == 0xffffffff) {

        return;

    }

    /* set the pci address in s->config_reg */

    phb->config_reg = (pciaddr) | (1u << 31);

    pci_data_write(phb->bus, phb->config_reg, val, 2);

    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */

    status = pci_get_word(d->config + PCI_STATUS);

    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);

    pci_set_word(d->config + PCI_STATUS, status);

}


static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v,

                                              const char *name, void *opaque,

                                              Error **errp)

{

    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);

    uint32_t value = s->pci_hole.begin;

    visit_type_uint32(v, name, &value, errp);

}


static void numa_stat_memory_devices(uint64_t node_mem[])

{

    MemoryDeviceInfoList *info_list = NULL;

    MemoryDeviceInfoList **prev = &info_list;

    MemoryDeviceInfoList *info;

    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);

    for (info = info_list; info; info = info->next) {

        MemoryDeviceInfo *value = info->value;

        if (value) {

            switch (value->type) {

            case MEMORY_DEVICE_INFO_KIND_DIMM:

                node_mem[value->u.dimm->node] += value->u.dimm->size;

                break;

            default:

                break;

            }

        }

    }

    qapi_free_MemoryDeviceInfoList(info_list);

}


static void blkverify_refresh_filename(BlockDriverState *bs)

{

    BDRVBlkverifyState *s = bs->opaque;

    /* bs->file->bs has already been refreshed */

    bdrv_refresh_filename(s->test_file->bs);

    if (bs->file->bs->full_open_options

        && s->test_file->bs->full_open_options)

    {

        QDict *opts = qdict_new();

        qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("blkverify")));

        QINCREF(bs->file->bs->full_open_options);

        qdict_put_obj(opts, "raw", QOBJECT(bs->file->bs->full_open_options));

        QINCREF(s->test_file->bs->full_open_options);

        qdict_put_obj(opts, "test",

                      QOBJECT(s->test_file->bs->full_open_options));

        bs->full_open_options = opts;

    }

    if (bs->file->bs->exact_filename[0]

        && s->test_file->bs->exact_filename[0])

    {

        snprintf(bs->exact_filename, sizeof(bs->exact_filename),

                 "blkverify:%s:%s",

                 bs->file->bs->exact_filename,

                 s->test_file->bs->exact_filename);

    }

}


static int ehci_init_transfer(EHCIQueue *q)

{

    uint32_t cpage, offset, bytes, plen;

    target_phys_addr_t page;

    cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);

    bytes  = get_field(q->qh.token, QTD_TOKEN_TBYTES);

    offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;

    qemu_sglist_init(&q->sgl, 5);

    while (bytes > 0) {

        if (cpage > 4) {

            fprintf(stderr, "cpage out of range (%d)\n", cpage);

            return USB_RET_PROCERR;

        }

        page  = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;

        page += offset;

        plen  = bytes;

        if (plen > 4096 - offset) {

            plen = 4096 - offset;

            offset = 0;

            cpage++;

        }

        qemu_sglist_add(&q->sgl, page, plen);

        bytes -= plen;

    }

    return 0;

}


static void allocate_buffers(FLACContext *s){

    int i;

    assert(s->max_blocksize);

    if(s->max_framesize == 0 && s->max_blocksize){

        s->max_framesize= (s->channels * s->bps * s->max_blocksize + 7)/ 8; //FIXME header overhead

    }

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

    {

        s->decoded[i] = av_realloc(s->decoded[i], sizeof(int32_t)*s->max_blocksize);

    }

    s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);

}


void ff_vp3_idct_add_c(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/){

    idct(dest, line_size, block, 2);

}


static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,

                          const char *boot_device,

                          DisplayState *ds, const char *kernel_filename,

                          const char *kernel_cmdline,

                          const char *initrd_filename, const char *cpu_model)

{

    CPUState *env, *envs[MAX_CPUS];

    unsigned int i;

    void *iommu, *espdma, *ledma, *main_esp, *nvram;

    qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq,

        *espdma_irq, *ledma_irq;

    qemu_irq *esp_reset, *le_reset;

    qemu_irq *fdc_tc;

    qemu_irq *cpu_halt;

    ram_addr_t ram_offset, prom_offset, tcx_offset, idreg_offset;

    unsigned long kernel_size;

    int ret;

    char buf[1024];

    BlockDriverState *fd[MAX_FD];

    int drive_index;

    void *fw_cfg;

    /* init CPUs */

    if (!cpu_model)

        cpu_model = hwdef->default_cpu_model;

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

        env = cpu_init(cpu_model);

        if (!env) {

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

            exit(1);

        }

        cpu_sparc_set_id(env, i);

        envs[i] = env;

        if (i == 0) {

            qemu_register_reset(main_cpu_reset, env);

        } else {

            qemu_register_reset(secondary_cpu_reset, env);

            env->halted = 1;

        }

        cpu_irqs[i] = qemu_allocate_irqs(cpu_set_irq, envs[i], MAX_PILS);

        env->prom_addr = hwdef->slavio_base;

    }

    for (i = smp_cpus; i < MAX_CPUS; i++)

        cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS);

    /* allocate RAM */

    if ((uint64_t)RAM_size > hwdef->max_mem) {

        fprintf(stderr,

                "qemu: Too much memory for this machine: %d, maximum %d\n",

                (unsigned int)(RAM_size / (1024 * 1024)),

                (unsigned int)(hwdef->max_mem / (1024 * 1024)));

        exit(1);

    }

    ram_offset = qemu_ram_alloc(RAM_size);

    cpu_register_physical_memory(0, RAM_size, ram_offset);

    /* load boot prom */

    prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);

    cpu_register_physical_memory(hwdef->slavio_base,

                                 (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) &

                                 TARGET_PAGE_MASK,

                                 prom_offset | IO_MEM_ROM);

    if (bios_name == NULL)

        bios_name = PROM_FILENAME;

    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);

    ret = load_elf(buf, hwdef->slavio_base - PROM_VADDR, NULL, NULL, NULL);

    if (ret < 0 || ret > PROM_SIZE_MAX)

        ret = load_image_targphys(buf, hwdef->slavio_base, PROM_SIZE_MAX);

    if (ret < 0 || ret > PROM_SIZE_MAX) {

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

                buf);

        exit(1);

    }

    /* set up devices */

    slavio_intctl = slavio_intctl_init(hwdef->intctl_base,

                                       hwdef->intctl_base + 0x10000ULL,

                                       &hwdef->intbit_to_level[0],

                                       &slavio_irq, &slavio_cpu_irq,

                                       cpu_irqs,

                                       hwdef->clock_irq);

    if (hwdef->idreg_base) {

        static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };

        idreg_offset = qemu_ram_alloc(sizeof(idreg_data));

        cpu_register_physical_memory(hwdef->idreg_base, sizeof(idreg_data),

                                     idreg_offset | IO_MEM_ROM);

        cpu_physical_memory_write_rom(hwdef->idreg_base, idreg_data,

                                      sizeof(idreg_data));

    }

    iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,

                       slavio_irq[hwdef->me_irq]);

    espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq],

                              iommu, &espdma_irq, &esp_reset);

    ledma = sparc32_dma_init(hwdef->dma_base + 16ULL,

                             slavio_irq[hwdef->le_irq], iommu, &ledma_irq,

                             &le_reset);

    if (graphic_depth != 8 && graphic_depth != 24) {

        fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth);

        exit (1);

    }

    tcx_offset = qemu_ram_alloc(hwdef->vram_size);

    tcx_init(ds, hwdef->tcx_base, phys_ram_base + tcx_offset, tcx_offset,

             hwdef->vram_size, graphic_width, graphic_height, graphic_depth);

    if (nd_table[0].model == NULL)

        nd_table[0].model = "lance";

    if (strcmp(nd_table[0].model, "lance") == 0) {

        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);

    } else if (strcmp(nd_table[0].model, "?") == 0) {

        fprintf(stderr, "qemu: Supported NICs: lance\n");

        exit (1);

    } else {

        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);

        exit (1);

    }

    nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,

                        hwdef->nvram_size, 8);

    slavio_timer_init_all(hwdef->counter_base, slavio_irq[hwdef->clock1_irq],

                          slavio_cpu_irq, smp_cpus);

    slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq],

                              nographic, ESCC_CLOCK, 1);

    // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device

    // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device

    escc_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq], serial_hds[1],

              serial_hds[0], ESCC_CLOCK, 1);

    cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);

    slavio_misc = slavio_misc_init(hwdef->slavio_base, hwdef->apc_base,

                                   hwdef->aux1_base, hwdef->aux2_base,

                                   slavio_irq[hwdef->me_irq], cpu_halt[0],

                                   &fdc_tc);

    if (hwdef->fd_base) {

        /* there is zero or one floppy drive */

        memset(fd, 0, sizeof(fd));

        drive_index = drive_get_index(IF_FLOPPY, 0, 0);

        if (drive_index != -1)

            fd[0] = drives_table[drive_index].bdrv;

        sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd,

                          fdc_tc);

    }

    if (drive_get_max_bus(IF_SCSI) > 0) {

        fprintf(stderr, "qemu: too many SCSI bus\n");

        exit(1);

    }

    main_esp = esp_init(hwdef->esp_base, 2,

                        espdma_memory_read, espdma_memory_write,

                        espdma, *espdma_irq, esp_reset);

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

        drive_index = drive_get_index(IF_SCSI, 0, i);

        if (drive_index == -1)

            continue;

        esp_scsi_attach(main_esp, drives_table[drive_index].bdrv, i);

    }

    if (hwdef->cs_base)

        cs_init(hwdef->cs_base, hwdef->cs_irq, slavio_intctl);

    kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,

                                    RAM_size);

    nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,

               boot_device, RAM_size, kernel_size, graphic_width,

               graphic_height, graphic_depth, hwdef->nvram_machine_id,

               "Sun4m");

    if (hwdef->ecc_base)

        ecc_init(hwdef->ecc_base, slavio_irq[hwdef->ecc_irq],

                 hwdef->ecc_version);

    fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);

    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);

    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);

    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);

    fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);

}


static void mptsas_update_interrupt(MPTSASState *s)

{

    PCIDevice *pci = (PCIDevice *) s;

    uint32_t state = s->intr_status & ~(s->intr_mask | MPI_HIS_IOP_DOORBELL_STATUS);

    if (s->msi_in_use && msi_enabled(pci)) {

        if (state) {

            trace_mptsas_irq_msi(s);

            msi_notify(pci, 0);

        }

    }

    trace_mptsas_irq_intx(s, !!state);

    pci_set_irq(pci, !!state);

}


static int find_pte64(CPUPPCState *env, struct mmu_ctx_hash64 *ctx,

                      target_ulong eaddr, int h, int rwx, int target_page_bits)

{

    hwaddr pteg_off;

    target_ulong pte0, pte1;

    int i, good = -1;

    int ret;

    ret = -1; /* No entry found */

    pteg_off = (ctx->hash[h] * HASH_PTEG_SIZE_64) & env->htab_mask;

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

        pte0 = ppc_hash64_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_64);

        pte1 = ppc_hash64_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_64);

        LOG_MMU("Load pte from %016" HWADDR_PRIx " => " TARGET_FMT_lx " "

                TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",

                pteg_off + (i * 16), pte0, pte1, !!(pte0 & HPTE64_V_VALID),

                h, !!(pte0 & HPTE64_V_SECONDARY), ctx->ptem);

        if (pte64_match(pte0, pte1, h, ctx->ptem)) {

            good = i;

            break;

        }

    }

    if (good != -1) {

        ret = pte64_check(ctx, pte0, pte1, rwx);

        LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",

                ctx->raddr, ctx->prot, ret);

        /* Update page flags */

        pte1 = ctx->raddr;

        if (ppc_hash64_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {

            ppc_hash64_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_64, pte1);

        }

    }

    /* We have a TLB that saves 4K pages, so let's

     * split a huge page to 4k chunks */

    if (target_page_bits != TARGET_PAGE_BITS) {

        ctx->raddr |= (eaddr & ((1 << target_page_bits) - 1))

                      & TARGET_PAGE_MASK;

    }

    return ret;

}


static int ds1338_init(I2CSlave *i2c)

{

    return 0;

}


static void qbus_print(Monitor *mon, BusState *bus, int indent)

{

    struct DeviceState *dev;

    qdev_printf("bus: %s\n", bus->name);

    indent += 2;

    qdev_printf("type %s\n", bus_type_names[bus->type]);

    LIST_FOREACH(dev, &bus->children, sibling) {

        qdev_print(mon, dev, indent);

    }

}


static void mvc_fast_memset(CPUS390XState *env, uint32_t l, uint64_t dest,

                            uint8_t byte)

{

    S390CPU *cpu = s390_env_get_cpu(env);

    hwaddr dest_phys;

    hwaddr len = l;

    void *dest_p;

    uint64_t asc = env->psw.mask & PSW_MASK_ASC;

    int flags;

    if (mmu_translate(env, dest, 1, asc, &dest_phys, &flags)) {

        cpu_stb_data(env, dest, byte);

        cpu_abort(CPU(cpu), "should never reach here");

    }

    dest_phys |= dest & ~TARGET_PAGE_MASK;

    dest_p = cpu_physical_memory_map(dest_phys, &len, 1);

    memset(dest_p, byte, len);

    cpu_physical_memory_unmap(dest_p, 1, len, len);

}


static ssize_t nbd_receive_request(QIOChannel *ioc, struct nbd_request *request)

{

    uint8_t buf[NBD_REQUEST_SIZE];

    uint32_t magic;

    ssize_t ret;

    ret = read_sync(ioc, buf, sizeof(buf));

    if (ret < 0) {

        return ret;

    }

    if (ret != sizeof(buf)) {

        LOG("read failed");

        return -EINVAL;

    }

    /* Request

       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)

       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)

       [ 8 .. 15]   handle

       [16 .. 23]   from

       [24 .. 27]   len

     */

    magic = ldl_be_p(buf);

    request->type   = ldl_be_p(buf + 4);

    request->handle = ldq_be_p(buf + 8);

    request->from   = ldq_be_p(buf + 16);

    request->len    = ldl_be_p(buf + 24);

    TRACE("Got request: { magic = 0x%" PRIx32 ", .type = %" PRIx32

          ", from = %" PRIu64 " , len = %" PRIu32 " }",

          magic, request->type, request->from, request->len);

    if (magic != NBD_REQUEST_MAGIC) {

        LOG("invalid magic (got 0x%" PRIx32 ")", magic);

        return -EINVAL;

    }

    return 0;

}


BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,

        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,

        BlockDriverCompletionFunc *cb, void *opaque, int type)

{

    struct qemu_laio_state *s = aio_ctx;

    struct qemu_laiocb *laiocb;

    struct iocb *iocbs;

    off_t offset = sector_num * 512;

    laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);

    if (!laiocb)

        return NULL;

    laiocb->nbytes = nb_sectors * 512;

    laiocb->ctx = s;

    laiocb->ret = -EINPROGRESS;

    laiocb->async_context_id = get_async_context_id();

    iocbs = &laiocb->iocb;

    switch (type) {

    case QEMU_AIO_WRITE:

        io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset);

	break;

    case QEMU_AIO_READ:

        io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);

	break;

    default:

        fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",

                        __func__, type);

        goto out_free_aiocb;

    }

    io_set_eventfd(&laiocb->iocb, s->efd);

    s->count++;

    if (io_submit(s->ctx, 1, &iocbs) < 0)

        goto out_dec_count;

    return &laiocb->common;

out_free_aiocb:

    qemu_aio_release(laiocb);

out_dec_count:

    s->count--;

    return NULL;

}


void helper_cpuid(void)

{

    if (EAX == 0) {

        EAX = 1; /* max EAX index supported */

        EBX = 0x756e6547;

        ECX = 0x6c65746e;

        EDX = 0x49656e69;

    } else {

        /* EAX = 1 info */

        EAX = 0x52b;

        EBX = 0;

        ECX = 0;

        EDX = CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE |

            CPUID_TSC | CPUID_MSR | CPUID_MCE |

            CPUID_CX8;

    }

}


void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,

                          int mvn, int r_x, int r_y, uint8_t* is_intra, int dir)

{

    MpegEncContext *s = &v->s;

    int xy, wrap, off = 0;

    int A[2], B[2], C[2];

    int px, py;

    int a_valid = 0, b_valid = 0, c_valid = 0;

    int field_a, field_b, field_c; // 0: same, 1: opposit

    int total_valid, num_samefield, num_oppfield;

    int pos_c, pos_b, n_adj;

    wrap = s->b8_stride;

    xy = s->block_index[n];

    if (s->mb_intra) {

        s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0;

        s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0;

        s->current_picture.motion_val[1][xy][0] = 0;

        s->current_picture.motion_val[1][xy][1] = 0;

        if (mvn == 1) { /* duplicate motion data for 1-MV block */

            s->current_picture.motion_val[0][xy + 1][0]        = 0;

            s->current_picture.motion_val[0][xy + 1][1]        = 0;

            s->current_picture.motion_val[0][xy + wrap][0]     = 0;

            s->current_picture.motion_val[0][xy + wrap][1]     = 0;

            s->current_picture.motion_val[0][xy + wrap + 1][0] = 0;

            s->current_picture.motion_val[0][xy + wrap + 1][1] = 0;

            v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0;

            s->current_picture.motion_val[1][xy + 1][0]        = 0;

            s->current_picture.motion_val[1][xy + 1][1]        = 0;

            s->current_picture.motion_val[1][xy + wrap][0]     = 0;

            s->current_picture.motion_val[1][xy + wrap][1]     = 0;

            s->current_picture.motion_val[1][xy + wrap + 1][0] = 0;

            s->current_picture.motion_val[1][xy + wrap + 1][1] = 0;

        }

        return;

    }

    off = ((n == 0) || (n == 1)) ? 1 : -1;

    /* predict A */

    if (s->mb_x || (n == 1) || (n == 3)) {

        if ((v->blk_mv_type[xy]) // current block (MB) has a field MV

            || (!v->blk_mv_type[xy] && !v->blk_mv_type[xy - 1])) { // or both have frame MV

            A[0] = s->current_picture.motion_val[dir][xy - 1][0];

            A[1] = s->current_picture.motion_val[dir][xy - 1][1];

            a_valid = 1;

        } else { // current block has frame mv and cand. has field MV (so average)

            A[0] = (s->current_picture.motion_val[dir][xy - 1][0]

                    + s->current_picture.motion_val[dir][xy - 1 + off * wrap][0] + 1) >> 1;

            A[1] = (s->current_picture.motion_val[dir][xy - 1][1]

                    + s->current_picture.motion_val[dir][xy - 1 + off * wrap][1] + 1) >> 1;

            a_valid = 1;

        }

        if (!(n & 1) && v->is_intra[s->mb_x - 1]) {

            a_valid = 0;

            A[0] = A[1] = 0;

        }

    } else

        A[0] = A[1] = 0;

    /* Predict B and C */

    B[0] = B[1] = C[0] = C[1] = 0;

    if (n == 0 || n == 1 || v->blk_mv_type[xy]) {

        if (!s->first_slice_line) {

            if (!v->is_intra[s->mb_x - s->mb_stride]) {

                b_valid = 1;

                n_adj   = n | 2;

                pos_b   = s->block_index[n_adj] - 2 * wrap;

                if (v->blk_mv_type[pos_b] && v->blk_mv_type[xy]) {

                    n_adj = (n & 2) | (n & 1);

                }

                B[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][0];

                B[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap][1];

                if (v->blk_mv_type[pos_b] && !v->blk_mv_type[xy]) {

                    B[0] = (B[0] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][0] + 1) >> 1;

                    B[1] = (B[1] + s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap][1] + 1) >> 1;

                }

            }

            if (s->mb_width > 1) {

                if (!v->is_intra[s->mb_x - s->mb_stride + 1]) {

                    c_valid = 1;

                    n_adj   = 2;

                    pos_c   = s->block_index[2] - 2 * wrap + 2;

                    if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {

                        n_adj = n & 2;

                    }

                    C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][0];

                    C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap + 2][1];

                    if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {

                        C[0] = (1 + C[0] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][0])) >> 1;

                        C[1] = (1 + C[1] + (s->current_picture.motion_val[dir][s->block_index[n_adj ^ 2] - 2 * wrap + 2][1])) >> 1;

                    }

                    if (s->mb_x == s->mb_width - 1) {

                        if (!v->is_intra[s->mb_x - s->mb_stride - 1]) {

                            c_valid = 1;

                            n_adj   = 3;

                            pos_c   = s->block_index[3] - 2 * wrap - 2;

                            if (v->blk_mv_type[pos_c] && v->blk_mv_type[xy]) {

                                n_adj = n | 1;

                            }

                            C[0] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][0];

                            C[1] = s->current_picture.motion_val[dir][s->block_index[n_adj] - 2 * wrap - 2][1];

                            if (v->blk_mv_type[pos_c] && !v->blk_mv_type[xy]) {

                                C[0] = (1 + C[0] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][0]) >> 1;

                                C[1] = (1 + C[1] + s->current_picture.motion_val[dir][s->block_index[1] - 2 * wrap - 2][1]) >> 1;

                            }

                        } else

                            c_valid = 0;

                    }

                }

            }

        }

    } else {

        pos_b   = s->block_index[1];

        b_valid = 1;

        B[0]    = s->current_picture.motion_val[dir][pos_b][0];

        B[1]    = s->current_picture.motion_val[dir][pos_b][1];

        pos_c   = s->block_index[0];

        c_valid = 1;

        C[0]    = s->current_picture.motion_val[dir][pos_c][0];

        C[1]    = s->current_picture.motion_val[dir][pos_c][1];

    }

    total_valid = a_valid + b_valid + c_valid;

    // check if predictor A is out of bounds

    if (!s->mb_x && !(n == 1 || n == 3)) {

        A[0] = A[1] = 0;

    }

    // check if predictor B is out of bounds

    if ((s->first_slice_line && v->blk_mv_type[xy]) || (s->first_slice_line && !(n & 2))) {

        B[0] = B[1] = C[0] = C[1] = 0;

    }

    if (!v->blk_mv_type[xy]) {

        if (s->mb_width == 1) {

            px = B[0];

            py = B[1];

        } else {

            if (total_valid >= 2) {

                px = mid_pred(A[0], B[0], C[0]);

                py = mid_pred(A[1], B[1], C[1]);

            } else if (total_valid) {

                if (a_valid) { px = A[0]; py = A[1]; }

                if (b_valid) { px = B[0]; py = B[1]; }

                if (c_valid) { px = C[0]; py = C[1]; }

            } else

                px = py = 0;

        }

    } else {

        if (a_valid)

            field_a = (A[1] & 4) ? 1 : 0;

        else

            field_a = 0;

        if (b_valid)

            field_b = (B[1] & 4) ? 1 : 0;

        else

            field_b = 0;

        if (c_valid)

            field_c = (C[1] & 4) ? 1 : 0;

        else

            field_c = 0;

        num_oppfield  = field_a + field_b + field_c;

        num_samefield = total_valid - num_oppfield;

        if (total_valid == 3) {

            if ((num_samefield == 3) || (num_oppfield == 3)) {

                px = mid_pred(A[0], B[0], C[0]);

                py = mid_pred(A[1], B[1], C[1]);

            } else if (num_samefield >= num_oppfield) {

                /* take one MV from same field set depending on priority

                the check for B may not be necessary */

                px = !field_a ? A[0] : B[0];

                py = !field_a ? A[1] : B[1];

            } else {

                px =  field_a ? A[0] : B[0];

                py =  field_a ? A[1] : B[1];

            }

        } else if (total_valid == 2) {

            if (num_samefield >= num_oppfield) {

                if (!field_a && a_valid) {

                    px = A[0];

                    py = A[1];

                } else if (!field_b && b_valid) {

                    px = B[0];

                    py = B[1];

                } else if (c_valid) {

                    px = C[0];

                    py = C[1];

                }

            } else {

                if (field_a && a_valid) {

                    px = A[0];

                    py = A[1];

                } else if (field_b && b_valid) {

                    px = B[0];

                    py = B[1];

                }

            }

        } else if (total_valid == 1) {

            px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);

            py = (a_valid) ? A[1] : ((b_valid) ? B[1] : C[1]);

        } else

            px = py = 0;

    }

    /* store MV using signed modulus of MV range defined in 4.11 */

    s->mv[dir][n][0] = s->current_picture.motion_val[dir][xy][0] = ((px + dmv_x + r_x) & ((r_x << 1) - 1)) - r_x;

    s->mv[dir][n][1] = s->current_picture.motion_val[dir][xy][1] = ((py + dmv_y + r_y) & ((r_y << 1) - 1)) - r_y;

    if (mvn == 1) { /* duplicate motion data for 1-MV block */

        s->current_picture.motion_val[dir][xy +    1    ][0] = s->current_picture.motion_val[dir][xy][0];

        s->current_picture.motion_val[dir][xy +    1    ][1] = s->current_picture.motion_val[dir][xy][1];

        s->current_picture.motion_val[dir][xy + wrap    ][0] = s->current_picture.motion_val[dir][xy][0];

        s->current_picture.motion_val[dir][xy + wrap    ][1] = s->current_picture.motion_val[dir][xy][1];

        s->current_picture.motion_val[dir][xy + wrap + 1][0] = s->current_picture.motion_val[dir][xy][0];

        s->current_picture.motion_val[dir][xy + wrap + 1][1] = s->current_picture.motion_val[dir][xy][1];

    } else if (mvn == 2) { /* duplicate motion data for 2-Field MV block */

        s->current_picture.motion_val[dir][xy + 1][0] = s->current_picture.motion_val[dir][xy][0];

        s->current_picture.motion_val[dir][xy + 1][1] = s->current_picture.motion_val[dir][xy][1];

        s->mv[dir][n + 1][0] = s->mv[dir][n][0];

        s->mv[dir][n + 1][1] = s->mv[dir][n][1];

    }

}


static inline void gen_stack_update(DisasContext *s, int addend)

{

#ifdef TARGET_X86_64

    if (CODE64(s)) {

        gen_op_addq_ESP_im(addend);

    } else

#endif

    if (s->ss32) {

        gen_op_addl_ESP_im(addend);

    } else {

        gen_op_addw_ESP_im(addend);

    }

}


void ide_exec_cmd(IDEBus *bus, uint32_t val)

{

    uint16_t *identify_data;

    IDEState *s;

    int n;

#if defined(DEBUG_IDE)

    printf("ide: CMD=%02x\n", val);

#endif

    s = idebus_active_if(bus);

    /* ignore commands to non existent slave */

    if (s != bus->ifs && !s->bs)

        return;

    /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */

    if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)

        return;

    if (!ide_cmd_permitted(s, val)) {

        goto abort_cmd;

    }

    if (ide_cmd_table[val].handler != NULL) {

        bool complete;

        s->status = READY_STAT | BUSY_STAT;

        s->error = 0;

        complete = ide_cmd_table[val].handler(s, val);

        if (complete) {

            s->status &= ~BUSY_STAT;

            assert(!!s->error == !!(s->status & ERR_STAT));

            if ((ide_cmd_table[val].flags & SET_DSC) && !s->error) {

                s->status |= SEEK_STAT;

            }

            ide_set_irq(s->bus);

        }

        return;

    }

    switch(val) {

    case WIN_CHECKPOWERMODE1:

    case WIN_CHECKPOWERMODE2:

        s->error = 0;

        s->nsector = 0xff; /* device active or idle */

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case WIN_SETFEATURES:

        if (!s->bs)

            goto abort_cmd;

        /* XXX: valid for CDROM ? */

        switch(s->feature) {

        case 0x02: /* write cache enable */

            bdrv_set_enable_write_cache(s->bs, true);

            identify_data = (uint16_t *)s->identify_data;

            put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1);

            s->status = READY_STAT | SEEK_STAT;

            ide_set_irq(s->bus);

            break;

        case 0x82: /* write cache disable */

            bdrv_set_enable_write_cache(s->bs, false);

            identify_data = (uint16_t *)s->identify_data;

            put_le16(identify_data + 85, (1 << 14) | 1);

            ide_flush_cache(s);

            break;

        case 0xcc: /* reverting to power-on defaults enable */

        case 0x66: /* reverting to power-on defaults disable */

        case 0xaa: /* read look-ahead enable */

        case 0x55: /* read look-ahead disable */

        case 0x05: /* set advanced power management mode */

        case 0x85: /* disable advanced power management mode */

        case 0x69: /* NOP */

        case 0x67: /* NOP */

        case 0x96: /* NOP */

        case 0x9a: /* NOP */

        case 0x42: /* enable Automatic Acoustic Mode */

        case 0xc2: /* disable Automatic Acoustic Mode */

            s->status = READY_STAT | SEEK_STAT;

            ide_set_irq(s->bus);

            break;

        case 0x03: { /* set transfer mode */

		uint8_t val = s->nsector & 0x07;

		identify_data = (uint16_t *)s->identify_data;

		switch (s->nsector >> 3) {

		case 0x00: /* pio default */

		case 0x01: /* pio mode */

			put_le16(identify_data + 62,0x07);

			put_le16(identify_data + 63,0x07);

			put_le16(identify_data + 88,0x3f);

			break;

                case 0x02: /* sigle word dma mode*/

			put_le16(identify_data + 62,0x07 | (1 << (val + 8)));

			put_le16(identify_data + 63,0x07);

			put_le16(identify_data + 88,0x3f);

			break;

		case 0x04: /* mdma mode */

			put_le16(identify_data + 62,0x07);

			put_le16(identify_data + 63,0x07 | (1 << (val + 8)));

			put_le16(identify_data + 88,0x3f);

			break;

		case 0x08: /* udma mode */

			put_le16(identify_data + 62,0x07);

			put_le16(identify_data + 63,0x07);

			put_le16(identify_data + 88,0x3f | (1 << (val + 8)));

			break;

		default:

			goto abort_cmd;

		}

            s->status = READY_STAT | SEEK_STAT;

            ide_set_irq(s->bus);

            break;

	}

        default:

            goto abort_cmd;

        }

        break;

    case WIN_FLUSH_CACHE:

    case WIN_FLUSH_CACHE_EXT:

        ide_flush_cache(s);

        break;

    case WIN_SEEK:

        /* XXX: Check that seek is within bounds */

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

        /* ATAPI commands */

    case WIN_PIDENTIFY:

        ide_atapi_identify(s);

        s->status = READY_STAT | SEEK_STAT;

        ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);

        ide_set_irq(s->bus);

        break;

    case WIN_DIAGNOSE:

        ide_set_signature(s);

        if (s->drive_kind == IDE_CD)

            s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet

                            * devices to return a clear status register

                            * with READY_STAT *not* set. */

        else

            s->status = READY_STAT | SEEK_STAT;

        s->error = 0x01; /* Device 0 passed, Device 1 passed or not

                          * present.

                          */

        ide_set_irq(s->bus);

        break;

    case WIN_DEVICE_RESET:

        ide_set_signature(s);

        s->status = 0x00; /* NOTE: READY is _not_ set */

        s->error = 0x01;

        break;

    case WIN_PACKETCMD:

        /* overlapping commands not supported */

        if (s->feature & 0x02)

            goto abort_cmd;

        s->status = READY_STAT | SEEK_STAT;

        s->atapi_dma = s->feature & 1;

        s->nsector = 1;

        ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,

                           ide_atapi_cmd);

        break;

    /* CF-ATA commands */

    case CFA_REQ_EXT_ERROR_CODE:

        s->error = 0x09;    /* miscellaneous error */

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case CFA_ERASE_SECTORS:

    case CFA_WEAR_LEVEL:

#if 0

    /* This one has the same ID as CFA_WEAR_LEVEL and is required for

       Windows 8 to work with AHCI */

    case WIN_SECURITY_FREEZE_LOCK:

#endif

        if (val == CFA_WEAR_LEVEL)

            s->nsector = 0;

        if (val == CFA_ERASE_SECTORS)

            s->media_changed = 1;

        s->error = 0x00;

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case CFA_TRANSLATE_SECTOR:

        s->error = 0x00;

        s->status = READY_STAT | SEEK_STAT;

        memset(s->io_buffer, 0, 0x200);

        s->io_buffer[0x00] = s->hcyl;			/* Cyl MSB */

        s->io_buffer[0x01] = s->lcyl;			/* Cyl LSB */

        s->io_buffer[0x02] = s->select;			/* Head */

        s->io_buffer[0x03] = s->sector;			/* Sector */

        s->io_buffer[0x04] = ide_get_sector(s) >> 16;	/* LBA MSB */

        s->io_buffer[0x05] = ide_get_sector(s) >> 8;	/* LBA */

        s->io_buffer[0x06] = ide_get_sector(s) >> 0;	/* LBA LSB */

        s->io_buffer[0x13] = 0x00;				/* Erase flag */

        s->io_buffer[0x18] = 0x00;				/* Hot count */

        s->io_buffer[0x19] = 0x00;				/* Hot count */

        s->io_buffer[0x1a] = 0x01;				/* Hot count */

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        ide_set_irq(s->bus);

        break;

    case CFA_ACCESS_METADATA_STORAGE:

        switch (s->feature) {

        case 0x02:	/* Inquiry Metadata Storage */

            ide_cfata_metadata_inquiry(s);

            break;

        case 0x03:	/* Read Metadata Storage */

            ide_cfata_metadata_read(s);

            break;

        case 0x04:	/* Write Metadata Storage */

            ide_cfata_metadata_write(s);

            break;

        default:

            goto abort_cmd;

        }

        ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

        s->status = 0x00; /* NOTE: READY is _not_ set */

        ide_set_irq(s->bus);

        break;

    case IBM_SENSE_CONDITION:

        switch (s->feature) {

        case 0x01:  /* sense temperature in device */

            s->nsector = 0x50;      /* +20 C */

            break;

        default:

            goto abort_cmd;

        }

        s->status = READY_STAT | SEEK_STAT;

        ide_set_irq(s->bus);

        break;

    case WIN_SMART:

	if (s->hcyl != 0xc2 || s->lcyl != 0x4f)

		goto abort_cmd;

	if (!s->smart_enabled && s->feature != SMART_ENABLE)

		goto abort_cmd;

	switch (s->feature) {

	case SMART_DISABLE:

		s->smart_enabled = 0;

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_ENABLE:

		s->smart_enabled = 1;

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_ATTR_AUTOSAVE:

		switch (s->sector) {

		case 0x00:

		s->smart_autosave = 0;

		break;

		case 0xf1:

		s->smart_autosave = 1;

		break;

		default:

		goto abort_cmd;

		}

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_STATUS:

		if (!s->smart_errors) {

		s->hcyl = 0xc2;

		s->lcyl = 0x4f;

		} else {

		s->hcyl = 0x2c;

		s->lcyl = 0xf4;

		}

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

	case SMART_READ_THRESH:

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01; /* smart struct version */

		for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {

		s->io_buffer[2+0+(n*12)] = smart_attributes[n][0];

		s->io_buffer[2+1+(n*12)] = smart_attributes[n][11];

		}

		for (n=0; n<511; n++) /* checksum */

		s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		s->status = READY_STAT | SEEK_STAT;

		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

		ide_set_irq(s->bus);

		break;

	case SMART_READ_DATA:

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01; /* smart struct version */

		for (n = 0; n < ARRAY_SIZE(smart_attributes); n++) {

		    int i;

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

			s->io_buffer[2+i+(n*12)] = smart_attributes[n][i];

		    }

		}

		s->io_buffer[362] = 0x02 | (s->smart_autosave?0x80:0x00);

		if (s->smart_selftest_count == 0) {

		s->io_buffer[363] = 0;

		} else {

		s->io_buffer[363] =

			s->smart_selftest_data[3 +

					   (s->smart_selftest_count - 1) *

					   24];

		}

		s->io_buffer[364] = 0x20;

		s->io_buffer[365] = 0x01;

		/* offline data collection capacity: execute + self-test*/

		s->io_buffer[367] = (1<<4 | 1<<3 | 1);

		s->io_buffer[368] = 0x03; /* smart capability (1) */

		s->io_buffer[369] = 0x00; /* smart capability (2) */

		s->io_buffer[370] = 0x01; /* error logging supported */

		s->io_buffer[372] = 0x02; /* minutes for poll short test */

		s->io_buffer[373] = 0x36; /* minutes for poll ext test */

		s->io_buffer[374] = 0x01; /* minutes for poll conveyance */

		for (n=0; n<511; n++)

		s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		s->status = READY_STAT | SEEK_STAT;

		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

		ide_set_irq(s->bus);

		break;

	case SMART_READ_LOG:

		switch (s->sector) {

		case 0x01: /* summary smart error log */

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01;

		s->io_buffer[1] = 0x00; /* no error entries */

		s->io_buffer[452] = s->smart_errors & 0xff;

		s->io_buffer[453] = (s->smart_errors & 0xff00) >> 8;

		for (n=0; n<511; n++)

			s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		break;

		case 0x06: /* smart self test log */

		memset(s->io_buffer, 0, 0x200);

		s->io_buffer[0] = 0x01;

		if (s->smart_selftest_count == 0) {

			s->io_buffer[508] = 0;

		} else {

			s->io_buffer[508] = s->smart_selftest_count;

			for (n=2; n<506; n++)

			s->io_buffer[n] = s->smart_selftest_data[n];

		}

		for (n=0; n<511; n++)

			s->io_buffer[511] += s->io_buffer[n];

		s->io_buffer[511] = 0x100 - s->io_buffer[511];

		break;

		default:

		goto abort_cmd;

		}

		s->status = READY_STAT | SEEK_STAT;

		ide_transfer_start(s, s->io_buffer, 0x200, ide_transfer_stop);

		ide_set_irq(s->bus);

		break;

	case SMART_EXECUTE_OFFLINE:

		switch (s->sector) {

		case 0: /* off-line routine */

		case 1: /* short self test */

		case 2: /* extended self test */

		s->smart_selftest_count++;

		if(s->smart_selftest_count > 21)

			s->smart_selftest_count = 0;

		n = 2 + (s->smart_selftest_count - 1) * 24;

		s->smart_selftest_data[n] = s->sector;

		s->smart_selftest_data[n+1] = 0x00; /* OK and finished */

		s->smart_selftest_data[n+2] = 0x34; /* hour count lsb */

		s->smart_selftest_data[n+3] = 0x12; /* hour count msb */

		s->status = READY_STAT | SEEK_STAT;

		ide_set_irq(s->bus);

		break;

		default:

		goto abort_cmd;

		}

		break;

	default:

		goto abort_cmd;

	}

	break;

    default:

        /* should not be reachable */

    abort_cmd:

        ide_abort_command(s);

        ide_set_irq(s->bus);

        break;

    }

}


void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,

                               DeviceState *dev, Error **errp)

{

    PCIDevice *pdev = PCI_DEVICE(dev);

    int slot = PCI_SLOT(pdev->devfn);

    int bsel = acpi_pcihp_get_bsel(pdev->bus);

    if (bsel < 0) {

        error_setg(errp, "Unsupported bus. Bus doesn't have property '"

                   ACPI_PCIHP_PROP_BSEL "' set");

        return;

    }

    /* Don't send event when device is enabled during qemu machine creation:

     * it is present on boot, no hotplug event is necessary. We do send an

     * event when the device is disabled later. */

    if (!dev->hotplugged) {

        return;

    }

    s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);

    acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);

}


void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)

{

    GArray *table_offsets;

    unsigned dsdt, rsdt;

    VirtAcpiCpuInfo cpuinfo;

    GArray *tables_blob = tables->table_data;

    virt_acpi_get_cpu_info(&cpuinfo);

    table_offsets = g_array_new(false, true /* clear */,

                                        sizeof(uint32_t));

    bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,

                             64, false /* high memory */);

    /*

     * The ACPI v5.1 tables for Hardware-reduced ACPI platform are:

     * RSDP

     * RSDT

     * FADT

     * GTDT

     * MADT

     * MCFG

     * DSDT

     */

    /* DSDT is pointed to by FADT */

    dsdt = tables_blob->len;

    build_dsdt(tables_blob, tables->linker, guest_info);

    /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */

    acpi_add_table(table_offsets, tables_blob);

    build_fadt(tables_blob, tables->linker, dsdt);

    acpi_add_table(table_offsets, tables_blob);

    build_madt(tables_blob, tables->linker, guest_info, &cpuinfo);

    acpi_add_table(table_offsets, tables_blob);

    build_gtdt(tables_blob, tables->linker);

    acpi_add_table(table_offsets, tables_blob);

    build_mcfg(tables_blob, tables->linker, guest_info);

    acpi_add_table(table_offsets, tables_blob);

    build_spcr(tables_blob, tables->linker, guest_info);

    /* RSDT is pointed to by RSDP */

    rsdt = tables_blob->len;

    build_rsdt(tables_blob, tables->linker, table_offsets);

    /* RSDP is in FSEG memory, so allocate it separately */

    build_rsdp(tables->rsdp, tables->linker, rsdt);

    /* Cleanup memory that's no longer used. */

    g_array_free(table_offsets, true);

}


static void code_gen_alloc(unsigned long tb_size)

{

#ifdef USE_STATIC_CODE_GEN_BUFFER

    code_gen_buffer = static_code_gen_buffer;

    code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;

    map_exec(code_gen_buffer, code_gen_buffer_size);

#else

    code_gen_buffer_size = tb_size;

    if (code_gen_buffer_size == 0) {

#if defined(CONFIG_USER_ONLY)

        /* in user mode, phys_ram_size is not meaningful */

        code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;

#else

        /* XXX: needs adjustments */

        code_gen_buffer_size = (unsigned long)(ram_size / 4);

#endif

    }

    if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)

        code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;

    /* The code gen buffer location may have constraints depending on

       the host cpu and OS */

#if defined(__linux__)

    {

        int flags;

        void *start = NULL;

        flags = MAP_PRIVATE | MAP_ANONYMOUS;

#if defined(__x86_64__)

        flags |= MAP_32BIT;

        /* Cannot map more than that */

        if (code_gen_buffer_size > (800 * 1024 * 1024))

            code_gen_buffer_size = (800 * 1024 * 1024);

#elif defined(__sparc_v9__)

        // Map the buffer below 2G, so we can use direct calls and branches

        flags |= MAP_FIXED;

        start = (void *) 0x60000000UL;

        if (code_gen_buffer_size > (512 * 1024 * 1024))

            code_gen_buffer_size = (512 * 1024 * 1024);

#elif defined(__arm__)

        /* Map the buffer below 32M, so we can use direct calls and branches */

        flags |= MAP_FIXED;

        start = (void *) 0x01000000UL;

        if (code_gen_buffer_size > 16 * 1024 * 1024)

            code_gen_buffer_size = 16 * 1024 * 1024;

#elif defined(__s390x__)

        /* Map the buffer so that we can use direct calls and branches.  */

        /* We have a +- 4GB range on the branches; leave some slop.  */

        if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {

            code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;

        }

        start = (void *)0x90000000UL;

#endif

        code_gen_buffer = mmap(start, code_gen_buffer_size,

                               PROT_WRITE | PROT_READ | PROT_EXEC,

                               flags, -1, 0);

        if (code_gen_buffer == MAP_FAILED) {

            fprintf(stderr, "Could not allocate dynamic translator buffer\n");

            exit(1);

        }

    }

#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \

    || defined(__DragonFly__) || defined(__OpenBSD__)

    {

        int flags;

        void *addr = NULL;

        flags = MAP_PRIVATE | MAP_ANONYMOUS;

#if defined(__x86_64__)

        /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume

         * 0x40000000 is free */

        flags |= MAP_FIXED;

        addr = (void *)0x40000000;

        /* Cannot map more than that */

        if (code_gen_buffer_size > (800 * 1024 * 1024))

            code_gen_buffer_size = (800 * 1024 * 1024);

#elif defined(__sparc_v9__)

        // Map the buffer below 2G, so we can use direct calls and branches

        flags |= MAP_FIXED;

        addr = (void *) 0x60000000UL;

        if (code_gen_buffer_size > (512 * 1024 * 1024)) {

            code_gen_buffer_size = (512 * 1024 * 1024);

        }

#endif

        code_gen_buffer = mmap(addr, code_gen_buffer_size,

                               PROT_WRITE | PROT_READ | PROT_EXEC,

                               flags, -1, 0);

        if (code_gen_buffer == MAP_FAILED) {

            fprintf(stderr, "Could not allocate dynamic translator buffer\n");

            exit(1);

        }

    }

#else

    code_gen_buffer = qemu_malloc(code_gen_buffer_size);

    map_exec(code_gen_buffer, code_gen_buffer_size);

#endif

#endif /* !USE_STATIC_CODE_GEN_BUFFER */

    map_exec(code_gen_prologue, sizeof(code_gen_prologue));

    code_gen_buffer_max_size = code_gen_buffer_size -

        (TCG_MAX_OP_SIZE * OPC_MAX_SIZE);

    code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;

    tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));

}


static void spapr_cpu_core_register_types(void)

{

    const SPAPRCoreInfo *info = spapr_cores;

    type_register_static(&spapr_cpu_core_type_info);

    while (info->name) {

        spapr_cpu_core_register(info);

        info++;

    }

}


void address_space_rw(AddressSpace *as, target_phys_addr_t addr, uint8_t *buf,

                      int len, bool is_write)

{

    AddressSpaceDispatch *d = as->dispatch;

    int l;

    uint8_t *ptr;

    uint32_t val;

    target_phys_addr_t page;

    MemoryRegionSection *section;

    while (len > 0) {

        page = addr & TARGET_PAGE_MASK;

        l = (page + TARGET_PAGE_SIZE) - addr;

        if (l > len)

            l = len;

        section = phys_page_find(d, page >> TARGET_PAGE_BITS);

        if (is_write) {

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

                target_phys_addr_t addr1;

                addr1 = memory_region_section_addr(section, addr);

                /* XXX: could force cpu_single_env to NULL to avoid

                   potential bugs */

                if (l >= 4 && ((addr1 & 3) == 0)) {

                    /* 32 bit write access */

                    val = ldl_p(buf);

                    io_mem_write(section->mr, addr1, val, 4);

                    l = 4;

                } else if (l >= 2 && ((addr1 & 1) == 0)) {

                    /* 16 bit write access */

                    val = lduw_p(buf);

                    io_mem_write(section->mr, addr1, val, 2);

                    l = 2;

                } else {

                    /* 8 bit write access */

                    val = ldub_p(buf);

                    io_mem_write(section->mr, addr1, val, 1);

                    l = 1;

                }

            } else if (!section->readonly) {

                ram_addr_t addr1;

                addr1 = memory_region_get_ram_addr(section->mr)

                    + memory_region_section_addr(section, addr);

                /* RAM case */

                ptr = qemu_get_ram_ptr(addr1);

                memcpy(ptr, buf, l);

                invalidate_and_set_dirty(addr1, l);

                qemu_put_ram_ptr(ptr);

            }

        } else {

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

                  memory_region_is_romd(section->mr))) {

                target_phys_addr_t addr1;

                /* I/O case */

                addr1 = memory_region_section_addr(section, addr);

                if (l >= 4 && ((addr1 & 3) == 0)) {

                    /* 32 bit read access */

                    val = io_mem_read(section->mr, addr1, 4);

                    stl_p(buf, val);

                    l = 4;

                } else if (l >= 2 && ((addr1 & 1) == 0)) {

                    /* 16 bit read access */

                    val = io_mem_read(section->mr, addr1, 2);

                    stw_p(buf, val);

                    l = 2;

                } else {

                    /* 8 bit read access */

                    val = io_mem_read(section->mr, addr1, 1);

                    stb_p(buf, val);

                    l = 1;

                }

            } else {

                /* RAM case */

                ptr = qemu_get_ram_ptr(section->mr->ram_addr

                                       + memory_region_section_addr(section,

                                                                    addr));

                memcpy(buf, ptr, l);

                qemu_put_ram_ptr(ptr);

            }

        }

        len -= l;

        buf += l;

        addr += l;

    }

}


float32 int64_to_float32( int64 a STATUS_PARAM )

{

    flag zSign;

    uint64 absA;

    int8 shiftCount;

    if ( a == 0 ) return 0;

    zSign = ( a < 0 );

    absA = zSign ? - a : a;

    shiftCount = countLeadingZeros64( absA ) - 40;

    if ( 0 <= shiftCount ) {

        return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount );

    }

    else {

        shiftCount += 7;

        if ( shiftCount < 0 ) {

            shift64RightJamming( absA, - shiftCount, &absA );

        }

        else {

            absA <<= shiftCount;

        }

        return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA STATUS_VAR );

    }

}


void clear_blocks_dcbz32_ppc(DCTELEM *blocks)

{

POWERPC_TBL_DECLARE(powerpc_clear_blocks_dcbz32, 1);

    register int misal = ((unsigned long)blocks & 0x00000010);

    register int i = 0;

POWERPC_TBL_START_COUNT(powerpc_clear_blocks_dcbz32, 1);

#if 1

    if (misal) {

      ((unsigned long*)blocks)[0] = 0L;

      ((unsigned long*)blocks)[1] = 0L;

      ((unsigned long*)blocks)[2] = 0L;

      ((unsigned long*)blocks)[3] = 0L;

      i += 16;

    }

    for ( ; i < sizeof(DCTELEM)*6*64 ; i += 32) {

      asm volatile("dcbz %0,%1" : : "b" (blocks), "r" (i) : "memory");

    }

    if (misal) {

      ((unsigned long*)blocks)[188] = 0L;

      ((unsigned long*)blocks)[189] = 0L;

      ((unsigned long*)blocks)[190] = 0L;

      ((unsigned long*)blocks)[191] = 0L;

      i += 16;

    }

#else

    memset(blocks, 0, sizeof(DCTELEM)*6*64);

#endif

POWERPC_TBL_STOP_COUNT(powerpc_clear_blocks_dcbz32, 1);

}


static uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri)

{

    /* Raw read of a coprocessor register (as needed for migration, etc). */

    if (ri->type & ARM_CP_CONST) {

        return ri->resetvalue;

    } else if (ri->raw_readfn) {

        return ri->raw_readfn(env, ri);

    } else if (ri->readfn) {

        return ri->readfn(env, ri);

    } else {

        return raw_read(env, ri);

    }

}


static void exec_accept_incoming_migration(void *opaque)

{

    QEMUFile *f = opaque;

    int ret;

    ret = qemu_loadvm_state(f);

    if (ret < 0) {

        fprintf(stderr, "load of migration failed\n");

        goto err;

    }

    qemu_announce_self();

    DPRINTF("successfully loaded vm state\n");

    /* we've successfully migrated, close the fd */

    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);

    if (autostart)

        vm_start();

err:

    qemu_fclose(f);

}


static void mainstone_common_init(ram_addr_t ram_size, int vga_ram_size,

                const char *kernel_filename,

                const char *kernel_cmdline, const char *initrd_filename,

                const char *cpu_model, enum mainstone_model_e model, int arm_id)

{

    uint32_t sector_len = 256 * 1024;

    target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };

    struct pxa2xx_state_s *cpu;

    qemu_irq *mst_irq;

    int i, index;

    if (!cpu_model)

        cpu_model = "pxa270-c5";

    /* Setup CPU & memory */

    if (ram_size < MAINSTONE_RAM + MAINSTONE_ROM + 2 * MAINSTONE_FLASH +

                    PXA2XX_INTERNAL_SIZE) {

        fprintf(stderr, "This platform requires %i bytes of memory\n",

                        MAINSTONE_RAM + MAINSTONE_ROM + 2 * MAINSTONE_FLASH +

                        PXA2XX_INTERNAL_SIZE);

        exit(1);

    }

    cpu = pxa270_init(mainstone_binfo.ram_size, cpu_model);

    cpu_register_physical_memory(0, MAINSTONE_ROM,

                    qemu_ram_alloc(MAINSTONE_ROM) | IO_MEM_ROM);

    /* Setup initial (reset) machine state */

    cpu->env->regs[15] = mainstone_binfo.loader_start;

    /* There are two 32MiB flash devices on the board */

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

        index = drive_get_index(IF_PFLASH, 0, i);

        if (index == -1) {

            fprintf(stderr, "Two flash images must be given with the "

                    "'pflash' parameter\n");

            exit(1);

        }

        if (!pflash_cfi01_register(mainstone_flash_base[i],

                                qemu_ram_alloc(MAINSTONE_FLASH),

                                drives_table[index].bdrv, sector_len,

                                MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0)) {

            fprintf(stderr, "qemu: Error registering flash memory.\n");

            exit(1);

        }

    }

    mst_irq = mst_irq_init(cpu, MST_FPGA_PHYS, PXA2XX_PIC_GPIO_0);

    /* setup keypad */

    printf("map addr %p\n", &map);

    pxa27x_register_keypad(cpu->kp, map, 0xe0);

    /* MMC/SD host */

    pxa2xx_mmci_handlers(cpu->mmc, NULL, mst_irq[MMC_IRQ]);

    smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);

    mainstone_binfo.kernel_filename = kernel_filename;

    mainstone_binfo.kernel_cmdline = kernel_cmdline;

    mainstone_binfo.initrd_filename = initrd_filename;

    mainstone_binfo.board_id = arm_id;

    arm_load_kernel(cpu->env, &mainstone_binfo);

}


static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr,

                             bool msix, unsigned req_num)

{

    unsigned i;

    MSIMessage msg = { .address = addr, .data = 0 };

    if (!msix) {

        msi_set_message(pdev, msg);

        trace_spapr_pci_msi_setup(pdev->name, 0, msg.address);

        return;

    }

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

        msg.address = addr | (i << 2);

        msix_set_message(pdev, i, msg);

        trace_spapr_pci_msi_setup(pdev->name, i, msg.address);

    }

}


static SocketAddressLegacy *nbd_build_socket_address(const char *sockpath,

                                               const char *bindto,

                                               const char *port)

{

    SocketAddressLegacy *saddr;

    saddr = g_new0(SocketAddressLegacy, 1);

    if (sockpath) {

        saddr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;

        saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);

        saddr->u.q_unix.data->path = g_strdup(sockpath);

    } else {

        InetSocketAddress *inet;

        saddr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;

        inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);

        inet->host = g_strdup(bindto);

        if (port) {

            inet->port = g_strdup(port);

        } else  {

            inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);

        }

    }

    return saddr;

}


static uint16_t blizzard_reg_read(void *opaque, uint8_t reg)

{

    BlizzardState *s = (BlizzardState *) opaque;

    switch (reg) {

    case 0x00:	/* Revision Code */

        return 0xa5;

    case 0x02:	/* Configuration Readback */

        return 0x83;	/* Macrovision OK, CNF[2:0] = 3 */

    case 0x04:	/* PLL M-Divider */

        return (s->pll - 1) | (1 << 7);

    case 0x06:	/* PLL Lock Range Control */

        return s->pll_range;

    case 0x08:	/* PLL Lock Synthesis Control 0 */

        return s->pll_ctrl & 0xff;

    case 0x0a:	/* PLL Lock Synthesis Control 1 */

        return s->pll_ctrl >> 8;

    case 0x0c:	/* PLL Mode Control 0 */

        return s->pll_mode;

    case 0x0e:	/* Clock-Source Select */

        return s->clksel;

    case 0x10:	/* Memory Controller Activate */

    case 0x14:	/* Memory Controller Bank 0 Status Flag */

        return s->memenable;

    case 0x18:	/* Auto-Refresh Interval Setting 0 */

        return s->memrefresh & 0xff;

    case 0x1a:	/* Auto-Refresh Interval Setting 1 */

        return s->memrefresh >> 8;

    case 0x1c:	/* Power-On Sequence Timing Control */

        return s->timing[0];

    case 0x1e:	/* Timing Control 0 */

        return s->timing[1];

    case 0x20:	/* Timing Control 1 */

        return s->timing[2];

    case 0x24:	/* Arbitration Priority Control */

        return s->priority;

    case 0x28:	/* LCD Panel Configuration */

        return s->lcd_config;

    case 0x2a:	/* LCD Horizontal Display Width */

        return s->x >> 3;

    case 0x2c:	/* LCD Horizontal Non-display Period */

        return s->hndp;

    case 0x2e:	/* LCD Vertical Display Height 0 */

        return s->y & 0xff;

    case 0x30:	/* LCD Vertical Display Height 1 */

        return s->y >> 8;

    case 0x32:	/* LCD Vertical Non-display Period */

        return s->vndp;

    case 0x34:	/* LCD HS Pulse-width */

        return s->hsync;

    case 0x36:	/* LCd HS Pulse Start Position */

        return s->skipx >> 3;

    case 0x38:	/* LCD VS Pulse-width */

        return s->vsync;

    case 0x3a:	/* LCD VS Pulse Start Position */

        return s->skipy;

    case 0x3c:	/* PCLK Polarity */

        return s->pclk;

    case 0x3e:	/* High-speed Serial Interface Tx Configuration Port 0 */

        return s->hssi_config[0];

    case 0x40:	/* High-speed Serial Interface Tx Configuration Port 1 */

        return s->hssi_config[1];

    case 0x42:	/* High-speed Serial Interface Tx Mode */

        return s->hssi_config[2];

    case 0x44:	/* TV Display Configuration */

        return s->tv_config;

    case 0x46 ... 0x4c:	/* TV Vertical Blanking Interval Data bits */

        return s->tv_timing[(reg - 0x46) >> 1];

    case 0x4e:	/* VBI: Closed Caption / XDS Control / Status */

        return s->vbi;

    case 0x50:	/* TV Horizontal Start Position */

        return s->tv_x;

    case 0x52:	/* TV Vertical Start Position */

        return s->tv_y;

    case 0x54:	/* TV Test Pattern Setting */

        return s->tv_test;

    case 0x56:	/* TV Filter Setting */

        return s->tv_filter_config;

    case 0x58:	/* TV Filter Coefficient Index */

        return s->tv_filter_idx;

    case 0x5a:	/* TV Filter Coefficient Data */

        if (s->tv_filter_idx < 0x20)

            return s->tv_filter_coeff[s->tv_filter_idx ++];

        return 0;

    case 0x60:	/* Input YUV/RGB Translate Mode 0 */

        return s->yrc[0];

    case 0x62:	/* Input YUV/RGB Translate Mode 1 */

        return s->yrc[1];

    case 0x64:	/* U Data Fix */

        return s->u;

    case 0x66:	/* V Data Fix */

        return s->v;

    case 0x68:	/* Display Mode */

        return s->mode;

    case 0x6a:	/* Special Effects */

        return s->effect;

    case 0x6c:	/* Input Window X Start Position 0 */

        return s->ix[0] & 0xff;

    case 0x6e:	/* Input Window X Start Position 1 */

        return s->ix[0] >> 3;

    case 0x70:	/* Input Window Y Start Position 0 */

        return s->ix[0] & 0xff;

    case 0x72:	/* Input Window Y Start Position 1 */

        return s->ix[0] >> 3;

    case 0x74:	/* Input Window X End Position 0 */

        return s->ix[1] & 0xff;

    case 0x76:	/* Input Window X End Position 1 */

        return s->ix[1] >> 3;

    case 0x78:	/* Input Window Y End Position 0 */

        return s->ix[1] & 0xff;

    case 0x7a:	/* Input Window Y End Position 1 */

        return s->ix[1] >> 3;

    case 0x7c:	/* Output Window X Start Position 0 */

        return s->ox[0] & 0xff;

    case 0x7e:	/* Output Window X Start Position 1 */

        return s->ox[0] >> 3;

    case 0x80:	/* Output Window Y Start Position 0 */

        return s->oy[0] & 0xff;

    case 0x82:	/* Output Window Y Start Position 1 */

        return s->oy[0] >> 3;

    case 0x84:	/* Output Window X End Position 0 */

        return s->ox[1] & 0xff;

    case 0x86:	/* Output Window X End Position 1 */

        return s->ox[1] >> 3;

    case 0x88:	/* Output Window Y End Position 0 */

        return s->oy[1] & 0xff;

    case 0x8a:	/* Output Window Y End Position 1 */

        return s->oy[1] >> 3;

    case 0x8c:	/* Input Data Format */

        return s->iformat;

    case 0x8e:	/* Data Source Select */

        return s->source;

    case 0x90:	/* Display Memory Data Port */

        return 0;

    case 0xa8:	/* Border Color 0 */

        return s->border_r;

    case 0xaa:	/* Border Color 1 */

        return s->border_g;

    case 0xac:	/* Border Color 2 */

        return s->border_b;

    case 0xb4:	/* Gamma Correction Enable */

        return s->gamma_config;

    case 0xb6:	/* Gamma Correction Table Index */

        return s->gamma_idx;

    case 0xb8:	/* Gamma Correction Table Data */

        return s->gamma_lut[s->gamma_idx ++];

    case 0xba:	/* 3x3 Matrix Enable */

        return s->matrix_ena;

    case 0xbc ... 0xde:	/* Coefficient Registers */

        return s->matrix_coeff[(reg - 0xbc) >> 1];

    case 0xe0:	/* 3x3 Matrix Red Offset */

        return s->matrix_r;

    case 0xe2:	/* 3x3 Matrix Green Offset */

        return s->matrix_g;

    case 0xe4:	/* 3x3 Matrix Blue Offset */

        return s->matrix_b;

    case 0xe6:	/* Power-save */

        return s->pm;

    case 0xe8:	/* Non-display Period Control / Status */

        return s->status | (1 << 5);

    case 0xea:	/* RGB Interface Control */

        return s->rgbgpio_dir;

    case 0xec:	/* RGB Interface Status */

        return s->rgbgpio;

    case 0xee:	/* General-purpose IO Pins Configuration */

        return s->gpio_dir;

    case 0xf0:	/* General-purpose IO Pins Status / Control */

        return s->gpio;

    case 0xf2:	/* GPIO Positive Edge Interrupt Trigger */

        return s->gpio_edge[0];

    case 0xf4:	/* GPIO Negative Edge Interrupt Trigger */

        return s->gpio_edge[1];

    case 0xf6:	/* GPIO Interrupt Status */

        return s->gpio_irq;

    case 0xf8:	/* GPIO Pull-down Control */

        return s->gpio_pdown;

    default:

        fprintf(stderr, "%s: unknown register %02x\n", __FUNCTION__, reg);

        return 0;

    }

}


void tcg_gen_brcond_i32(TCGCond cond, TCGv_i32 arg1, TCGv_i32 arg2, int label)

{

    if (cond == TCG_COND_ALWAYS) {

        tcg_gen_br(label);

    } else if (cond != TCG_COND_NEVER) {

        tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label);

    }

}


AioContext *bdrv_get_aio_context(BlockDriverState *bs)

{

    /* Currently BlockDriverState always uses the main loop AioContext */

    return qemu_get_aio_context();

}


static int video_get_buffer(AVCodecContext *s, AVFrame *pic)

{

    FramePool *pool = s->internal->pool;

    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);

    int i;

    if (pic->data[0]) {

        av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");

        return -1;

    }

    if (!desc) {

        av_log(s, AV_LOG_ERROR,

            "Unable to get pixel format descriptor for format %s\n",

            av_get_pix_fmt_name(pic->format));

        return AVERROR(EINVAL);

    }

    memset(pic->data, 0, sizeof(pic->data));

    pic->extended_data = pic->data;

    for (i = 0; i < 4 && pool->pools[i]; i++) {

        pic->linesize[i] = pool->linesize[i];

        pic->buf[i] = av_buffer_pool_get(pool->pools[i]);

        if (!pic->buf[i])

            goto fail;

        pic->data[i] = pic->buf[i]->data;

    }

    for (; i < AV_NUM_DATA_POINTERS; i++) {

        pic->data[i] = NULL;

        pic->linesize[i] = 0;

    }

    if (desc->flags & AV_PIX_FMT_FLAG_PAL ||

        desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL)

        avpriv_set_systematic_pal2((uint32_t *)pic->data[1], pic->format);

    if (s->debug & FF_DEBUG_BUFFERS)

        av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic);

    return 0;

fail:

    av_frame_unref(pic);

    return AVERROR(ENOMEM);

}


static int qio_dns_resolver_lookup_sync_nop(QIODNSResolver *resolver,

                                            SocketAddress *addr,

                                            size_t *naddrs,

                                            SocketAddress ***addrs,

                                            Error **errp)

{

    *naddrs = 1;

    *addrs = g_new0(SocketAddress *, 1);

    (*addrs)[0] = QAPI_CLONE(SocketAddress, addr);

    return 0;

}


static int nvdimm_plugged_device_list(Object *obj, void *opaque)

{

    GSList **list = opaque;

    if (object_dynamic_cast(obj, TYPE_NVDIMM)) {

        *list = g_slist_append(*list, DEVICE(obj));

    }

    object_child_foreach(obj, nvdimm_plugged_device_list, opaque);

    return 0;

}


AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,

                      const char *opaque, Error **errp)

{

    int fd;

    Monitor *mon = cur_mon;

    MonFdset *mon_fdset = NULL;

    MonFdsetFd *mon_fdset_fd;

    AddfdInfo *fdinfo;

    fd = qemu_chr_fe_get_msgfd(mon->chr);

    if (fd == -1) {

        error_set(errp, QERR_FD_NOT_SUPPLIED);

        goto error;

    }

    if (has_fdset_id) {

        QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {

            /* Break if match found or match impossible due to ordering by ID */

            if (fdset_id <= mon_fdset->id) {

                if (fdset_id < mon_fdset->id) {

                    mon_fdset = NULL;

                }

                break;

            }

        }

    }

    if (mon_fdset == NULL) {

        int64_t fdset_id_prev = -1;

        MonFdset *mon_fdset_cur = QLIST_FIRST(&mon_fdsets);

        if (has_fdset_id) {

            if (fdset_id < 0) {

                error_set(errp, QERR_INVALID_PARAMETER_VALUE, "fdset-id",

                          "a non-negative value");

                goto error;

            }

            /* Use specified fdset ID */

            QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {

                mon_fdset_cur = mon_fdset;

                if (fdset_id < mon_fdset_cur->id) {

                    break;

                }

            }

        } else {

            /* Use first available fdset ID */

            QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {

                mon_fdset_cur = mon_fdset;

                if (fdset_id_prev == mon_fdset_cur->id - 1) {

                    fdset_id_prev = mon_fdset_cur->id;

                    continue;

                }

                break;

            }

        }

        mon_fdset = g_malloc0(sizeof(*mon_fdset));

        if (has_fdset_id) {

            mon_fdset->id = fdset_id;

        } else {

            mon_fdset->id = fdset_id_prev + 1;

        }

        /* The fdset list is ordered by fdset ID */

        if (!mon_fdset_cur) {

            QLIST_INSERT_HEAD(&mon_fdsets, mon_fdset, next);

        } else if (mon_fdset->id < mon_fdset_cur->id) {

            QLIST_INSERT_BEFORE(mon_fdset_cur, mon_fdset, next);

        } else {

            QLIST_INSERT_AFTER(mon_fdset_cur, mon_fdset, next);

        }

    }

    mon_fdset_fd = g_malloc0(sizeof(*mon_fdset_fd));

    mon_fdset_fd->fd = fd;

    mon_fdset_fd->removed = false;

    if (has_opaque) {

        mon_fdset_fd->opaque = g_strdup(opaque);

    }

    QLIST_INSERT_HEAD(&mon_fdset->fds, mon_fdset_fd, next);

    fdinfo = g_malloc0(sizeof(*fdinfo));

    fdinfo->fdset_id = mon_fdset->id;

    fdinfo->fd = mon_fdset_fd->fd;

    return fdinfo;

error:

    if (fd != -1) {

        close(fd);

    }

    return NULL;

}


static BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,

        unsigned long int req, void *buf,

        BlockDriverCompletionFunc *cb, void *opaque)

{

    RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);

    acb->bs = bs;

    acb->aio_type = QEMU_AIO_IOCTL;

    acb->aio_fildes = fd;

    acb->aio_offset = 0;

    acb->aio_ioctl_buf = buf;

    acb->aio_ioctl_cmd = req;

    return thread_pool_submit_aio(aio_worker, acb, cb, opaque);

}


static int readv_f(BlockBackend *blk, int argc, char **argv)

{

    struct timeval t1, t2;

    int Cflag = 0, qflag = 0, vflag = 0;

    int c, cnt;

    char *buf;

    int64_t offset;

    /* Some compilers get confused and warn if this is not initialized.  */

    int total = 0;

    int nr_iov;

    QEMUIOVector qiov;

    int pattern = 0;

    int Pflag = 0;

    while ((c = getopt(argc, argv, "CP:qv")) != EOF) {

        switch (c) {

        case 'C':

            Cflag = 1;

            break;

        case 'P':

            Pflag = 1;

            pattern = parse_pattern(optarg);

            if (pattern < 0) {

                return 0;

            }

            break;

        case 'q':

            qflag = 1;

            break;

        case 'v':

            vflag = 1;

            break;

        default:

            return qemuio_command_usage(&readv_cmd);

        }

    }

    if (optind > argc - 2) {

        return qemuio_command_usage(&readv_cmd);

    }

    offset = cvtnum(argv[optind]);

    if (offset < 0) {

        printf("non-numeric length argument -- %s\n", argv[optind]);

        return 0;

    }

    optind++;

    if (offset & 0x1ff) {

        printf("offset %" PRId64 " is not sector aligned\n",

               offset);

        return 0;

    }

    nr_iov = argc - optind;

    buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);

    if (buf == NULL) {

        return 0;

    }

    gettimeofday(&t1, NULL);

    cnt = do_aio_readv(blk, &qiov, offset, &total);

    gettimeofday(&t2, NULL);

    if (cnt < 0) {

        printf("readv failed: %s\n", strerror(-cnt));

        goto out;

    }

    if (Pflag) {

        void *cmp_buf = g_malloc(qiov.size);

        memset(cmp_buf, pattern, qiov.size);

        if (memcmp(buf, cmp_buf, qiov.size)) {

            printf("Pattern verification failed at offset %"

                   PRId64 ", %zd bytes\n", offset, qiov.size);

        }

        g_free(cmp_buf);

    }

    if (qflag) {

        goto out;

    }

    if (vflag) {

        dump_buffer(buf, offset, qiov.size);

    }

    /* Finally, report back -- -C gives a parsable format */

    t2 = tsub(t2, t1);

    print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);

out:

    qemu_iovec_destroy(&qiov);

    qemu_io_free(buf);

    return 0;

}


static void iter_func(QObject *obj, void *opaque)

{

    QInt *qi;

    fail_unless(opaque == NULL);

    qi = qobject_to_qint(obj);

    fail_unless(qi != NULL);

    fail_unless((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));

    iter_called++;

}


int avfilter_init_str(AVFilterContext *filter, const char *args)

{

    return avfilter_init_filter(filter, args, NULL);

}


SerialState *serial_mm_init(MemoryRegion *address_space,

                            hwaddr base, int it_shift,

                            qemu_irq irq, int baudbase,

                            CharDriverState *chr, enum device_endian end)

{

    SerialState *s;

    Error *err = NULL;

    s = g_malloc0(sizeof(SerialState));

    s->it_shift = it_shift;

    s->irq = irq;

    s->baudbase = baudbase;

    s->chr = chr;

    serial_realize_core(s, &err);

    if (err != NULL) {

        error_report("%s", error_get_pretty(err));

        error_free(err);

        exit(1);

    }

    vmstate_register(NULL, base, &vmstate_serial, s);

    memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s,

                          "serial", 8 << it_shift);

    memory_region_add_subregion(address_space, base, &s->io);

    serial_update_msl(s);

    return s;

}


static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f)

{

    VirtIONet *n = VIRTIO_NET(vdev);

    int i;

    qemu_put_buffer(f, n->mac, ETH_ALEN);

    qemu_put_be32(f, n->vqs[0].tx_waiting);

    qemu_put_be32(f, n->mergeable_rx_bufs);

    qemu_put_be16(f, n->status);

    qemu_put_byte(f, n->promisc);

    qemu_put_byte(f, n->allmulti);

    qemu_put_be32(f, n->mac_table.in_use);

    qemu_put_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN);

    qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3);

    qemu_put_be32(f, n->has_vnet_hdr);

    qemu_put_byte(f, n->mac_table.multi_overflow);

    qemu_put_byte(f, n->mac_table.uni_overflow);

    qemu_put_byte(f, n->alluni);

    qemu_put_byte(f, n->nomulti);

    qemu_put_byte(f, n->nouni);

    qemu_put_byte(f, n->nobcast);

    qemu_put_byte(f, n->has_ufo);

    if (n->max_queues > 1) {

        qemu_put_be16(f, n->max_queues);

        qemu_put_be16(f, n->curr_queues);

        for (i = 1; i < n->curr_queues; i++) {

            qemu_put_be32(f, n->vqs[i].tx_waiting);

        }

    }

    if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {

        qemu_put_be64(f, n->curr_guest_offloads);

    }

}


udp_listen(port, laddr, lport, flags)

	u_int port;

	u_int32_t laddr;

	u_int lport;

	int flags;

{

	struct sockaddr_in addr;

	struct socket *so;

	int addrlen = sizeof(struct sockaddr_in), opt = 1;

	if ((so = socreate()) == NULL) {

		free(so);

		return NULL;

	}

	so->s = socket(AF_INET,SOCK_DGRAM,0);

	so->so_expire = curtime + SO_EXPIRE;

	insque(so,&udb);

	addr.sin_family = AF_INET;

	addr.sin_addr.s_addr = INADDR_ANY;

	addr.sin_port = port;

	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {

		udp_detach(so);

		return NULL;

	}

	setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));

/*	setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */

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

	so->so_fport = addr.sin_port;

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

	   so->so_faddr = alias_addr;

	else

	   so->so_faddr = addr.sin_addr;

	so->so_lport = lport;

	so->so_laddr.s_addr = laddr;

	if (flags != SS_FACCEPTONCE)

	   so->so_expire = 0;

	so->so_state = SS_ISFCONNECTED;

	return so;

}


void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,

                        uint64_t status, uint64_t mcg_status, uint64_t addr,

                        uint64_t misc, int flags)

{

    unsigned bank_num = cenv->mcg_cap & 0xff;

    CPUState *env;

    int flag = 0;

    if (!cenv->mcg_cap) {

        monitor_printf(mon, "MCE injection not supported\n");

        return;

    }

    if (bank >= bank_num) {

        monitor_printf(mon, "Invalid MCE bank number\n");

        return;

    }

    if (!(status & MCI_STATUS_VAL)) {

        monitor_printf(mon, "Invalid MCE status code\n");

        return;

    }

    if ((flags & MCE_INJECT_BROADCAST)

        && !cpu_x86_support_mca_broadcast(cenv)) {

        monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");

        return;

    }

    if (kvm_enabled()) {

        if (flags & MCE_INJECT_BROADCAST) {

            flag |= MCE_BROADCAST;

        }

        kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);

    } else {

        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc,

                            flags);

        if (flags & MCE_INJECT_BROADCAST) {

            for (env = first_cpu; env != NULL; env = env->next_cpu) {

                if (cenv == env) {

                    continue;

                }

                qemu_inject_x86_mce(mon, env, 1,

                                    MCI_STATUS_VAL | MCI_STATUS_UC,

                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,

                                    flags);

            }

        }

    }

}


static void piix3_set_irq(void *opaque, int irq_num, int level)

{

    int i, pic_irq, pic_level;

    PIIX3State *piix3 = opaque;

    /* now we change the pic irq level according to the piix irq mappings */

    /* XXX: optimize */

    pic_irq = piix3->dev.config[0x60 + irq_num];

    if (pic_irq < 16) {

        /* The pic level is the logical OR of all the PCI irqs mapped

           to it */

        pic_level = 0;

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

            if (pic_irq == piix3->dev.config[0x60 + i]) {

                pic_level |= pci_bus_get_irq_level(piix3->dev.bus, i);

            }

        }

        qemu_set_irq(piix3->pic[pic_irq], pic_level);

    }

}


static void mirror_iteration_done(MirrorOp *op, int ret)

{

    MirrorBlockJob *s = op->s;

    struct iovec *iov;

    int64_t chunk_num;

    int i, nb_chunks, sectors_per_chunk;

    trace_mirror_iteration_done(s, op->sector_num * BDRV_SECTOR_SIZE,

                                op->nb_sectors * BDRV_SECTOR_SIZE, ret);

    s->in_flight--;

    s->sectors_in_flight -= op->nb_sectors;

    iov = op->qiov.iov;

    for (i = 0; i < op->qiov.niov; i++) {

        MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base;

        QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next);

        s->buf_free_count++;

    }

    sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS;

    chunk_num = op->sector_num / sectors_per_chunk;

    nb_chunks = DIV_ROUND_UP(op->nb_sectors, sectors_per_chunk);

    bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks);

    if (ret >= 0) {

        if (s->cow_bitmap) {

            bitmap_set(s->cow_bitmap, chunk_num, nb_chunks);

        }

        if (!s->initial_zeroing_ongoing) {

            s->common.offset += (uint64_t)op->nb_sectors * BDRV_SECTOR_SIZE;

        }

    }

    qemu_iovec_destroy(&op->qiov);

    g_free(op);

    if (s->waiting_for_io) {

        qemu_coroutine_enter(s->common.co);

    }

}


static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,

                                  size_t size)

{

    VIOsPAPRDevice *sdev = DO_UPCAST(NICState, nc, nc)->opaque;

    VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;

    vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);

    vlan_bd_t bd;

    int buf_ptr = dev->use_buf_ptr;

    uint64_t handle;

    uint8_t control;

    dprintf("spapr_vlan_receive() [%s] rx_bufs=%d\n", sdev->qdev.id,

            dev->rx_bufs);

    if (!dev->isopen) {

        return -1;

    }

    if (!dev->rx_bufs) {

        return -1;

    }

    do {

        buf_ptr += 8;

        if (buf_ptr >= SPAPR_TCE_PAGE_SIZE) {

            buf_ptr = VLAN_RX_BDS_OFF;

        }

        bd = vio_ldq(sdev, dev->buf_list + buf_ptr);

        dprintf("use_buf_ptr=%d bd=0x%016llx\n",

                buf_ptr, (unsigned long long)bd);

    } while ((!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8)))

             && (buf_ptr != dev->use_buf_ptr));

    if (!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8))) {

        /* Failed to find a suitable buffer */

        return -1;

    }

    /* Remove the buffer from the pool */

    dev->rx_bufs--;

    dev->use_buf_ptr = buf_ptr;

    vio_stq(sdev, dev->buf_list + dev->use_buf_ptr, 0);

    dprintf("Found buffer: ptr=%d num=%d\n", dev->use_buf_ptr, dev->rx_bufs);

    /* Transfer the packet data */

    if (spapr_vio_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) {

        return -1;

    }

    dprintf("spapr_vlan_receive: DMA write completed\n");

    /* Update the receive queue */

    control = VLAN_RXQC_TOGGLE | VLAN_RXQC_VALID;

    if (rxq_bd & VLAN_BD_TOGGLE) {

        control ^= VLAN_RXQC_TOGGLE;

    }

    handle = vio_ldq(sdev, VLAN_BD_ADDR(bd));

    vio_stq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle);

    vio_stl(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size);

    vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8);

    vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control);

    dprintf("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n",

            (unsigned long long)dev->rxq_ptr,

            (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +

                                        dev->rxq_ptr),

            (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +

                                        dev->rxq_ptr + 8));

    dev->rxq_ptr += 16;

    if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) {

        dev->rxq_ptr = 0;

        vio_stq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE);

    }

    if (sdev->signal_state & 1) {

        qemu_irq_pulse(sdev->qirq);

    }

    return size;

}


int av_write_frame(AVFormatContext *s, AVPacket *pkt)

{

    int ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);

    if(ret<0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))

        return ret;

    ret= s->oformat->write_packet(s, pkt);

    if(!ret)

        ret= url_ferror(s->pb);

    return ret;

}


av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)

{

    int i, j, n;

    if (nbits < 2 || nbits > 16)

        goto fail;

    s->nbits = nbits;

    n = 1 << nbits;

    s->revtab = av_malloc(n * sizeof(uint16_t));

    if (!s->revtab)

        goto fail;

    s->tmp_buf = av_malloc(n * sizeof(FFTComplex));

    if (!s->tmp_buf)

        goto fail;

    s->inverse = inverse;

    s->fft_permute = ff_fft_permute_c;

    s->fft_calc    = ff_fft_calc_c;

#if CONFIG_MDCT

    s->imdct_calc  = ff_imdct_calc_c;

    s->imdct_half  = ff_imdct_half_c;

    s->mdct_calc   = ff_mdct_calc_c;

#endif

    if (ARCH_ARM)     ff_fft_init_arm(s);

    if (HAVE_ALTIVEC) ff_fft_init_altivec(s);

    if (HAVE_MMX)     ff_fft_init_mmx(s);

    for(j=4; j<=nbits; j++) {

        ff_init_ff_cos_tabs(j);

    }

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

        s->revtab[-split_radix_permutation(i, n, s->inverse) & (n-1)] = i;

    return 0;

 fail:

    av_freep(&s->revtab);

    av_freep(&s->tmp_buf);

    return -1;

}


DisplaySurface *qemu_create_displaysurface_guestmem(int width, int height,

                                                    pixman_format_code_t format,

                                                    int linesize, uint64_t addr)

{

    DisplaySurface *surface;

    hwaddr size;

    void *data;

    if (linesize == 0) {

        linesize = width * PIXMAN_FORMAT_BPP(format) / 8;

    }

    size = linesize * height;

    data = cpu_physical_memory_map(addr, &size, 0);

    if (size != linesize * height) {

        cpu_physical_memory_unmap(data, size, 0, 0);

        return NULL;

    }

    surface = qemu_create_displaysurface_from

        (width, height, format, linesize, data);

    pixman_image_set_destroy_function

        (surface->image, qemu_unmap_displaysurface_guestmem, NULL);

    return surface;

}


static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)

{

    AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);

    AVFilterContext *ctx = inlink->dst;

    OverlayContext *over = ctx->priv;

    av_unused AVFilterLink *outlink = ctx->outputs[0];

    inlink->dst->outputs[0]->out_buf = outpicref;

    outpicref->pts = av_rescale_q(outpicref->pts, ctx->inputs[MAIN]->time_base,

                                  ctx->outputs[0]->time_base);

    if (!over->overpicref || over->overpicref->pts < outpicref->pts) {

        if (!over->overpicref_next)

            avfilter_request_frame(ctx->inputs[OVERLAY]);

        if (over->overpicref && over->overpicref_next &&

            over->overpicref_next->pts <= outpicref->pts) {

            avfilter_unref_buffer(over->overpicref);

            over->overpicref = over->overpicref_next;

            over->overpicref_next = NULL;

        }

    }

    av_dlog(ctx, "main_pts:%s main_pts_time:%s",

            av_ts2str(outpicref->pts), av_ts2timestr(outpicref->pts, &outlink->time_base));

    if (over->overpicref)

        av_dlog(ctx, " over_pts:%s over_pts_time:%s",

                av_ts2str(over->overpicref->pts), av_ts2timestr(over->overpicref->pts, &outlink->time_base));

    av_dlog(ctx, "\n");

    avfilter_start_frame(inlink->dst->outputs[0], outpicref);

}


static void monitor_puts(Monitor *mon, const char *str)

{

    char c;

    for(;;) {

        assert(mon->outbuf_index < sizeof(mon->outbuf) - 1);

        c = *str++;

        if (c == '\0')

            break;

        if (c == '\n')

            mon->outbuf[mon->outbuf_index++] = '\r';

        mon->outbuf[mon->outbuf_index++] = c;

        if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)

            || c == '\n')

            monitor_flush(mon);

    }

}


void timer_del(QEMUTimer *ts)

{

    QEMUTimerList *timer_list = ts->timer_list;

    qemu_mutex_lock(&timer_list->active_timers_lock);

    timer_del_locked(timer_list, ts);

    qemu_mutex_unlock(&timer_list->active_timers_lock);

}


static void put_bitmap(QEMUFile *f, void *pv, size_t size)

{

    unsigned long *bmp = pv;

    int i, idx = 0;

    for (i = 0; i < BITS_TO_U64S(size); i++) {

        uint64_t w = bmp[idx++];

        if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {

            w |= ((uint64_t)bmp[idx++]) << 32;

        }

        qemu_put_be64(f, w);

    }

}


void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)

{

    func(data);

}


static int dirac_decode_picture_header(DiracContext *s)

{

    unsigned retire, picnum;

    int i, j, ret;

    int64_t refdist, refnum;

    GetBitContext *gb = &s->gb;

    /* [DIRAC_STD] 11.1.1 Picture Header. picture_header() PICTURE_NUM */

    picnum = s->current_picture->avframe->display_picture_number = get_bits_long(gb, 32);

    av_log(s->avctx,AV_LOG_DEBUG,"PICTURE_NUM: %d\n",picnum);

    /* if this is the first keyframe after a sequence header, start our

       reordering from here */

    if (s->frame_number < 0)

        s->frame_number = picnum;

    s->ref_pics[0] = s->ref_pics[1] = NULL;

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

        refnum = (picnum + dirac_get_se_golomb(gb)) & 0xFFFFFFFF;

        refdist = INT64_MAX;

        /* find the closest reference to the one we want */

        /* Jordi: this is needed if the referenced picture hasn't yet arrived */

        for (j = 0; j < MAX_REFERENCE_FRAMES && refdist; j++)

            if (s->ref_frames[j]

                && FFABS(s->ref_frames[j]->avframe->display_picture_number - refnum) < refdist) {

                s->ref_pics[i] = s->ref_frames[j];

                refdist = FFABS(s->ref_frames[j]->avframe->display_picture_number - refnum);

            }

        if (!s->ref_pics[i] || refdist)

            av_log(s->avctx, AV_LOG_DEBUG, "Reference not found\n");

        /* if there were no references at all, allocate one */

        if (!s->ref_pics[i])

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

                if (!s->all_frames[j].avframe->data[0]) {

                    s->ref_pics[i] = &s->all_frames[j];

                    get_buffer_with_edge(s->avctx, s->ref_pics[i]->avframe, AV_GET_BUFFER_FLAG_REF);

                    break;

                }

        if (!s->ref_pics[i]) {

            av_log(s->avctx, AV_LOG_ERROR, "Reference could not be allocated\n");

            return AVERROR_INVALIDDATA;

        }

    }

    /* retire the reference frames that are not used anymore */

    if (s->current_picture->reference) {

        retire = (picnum + dirac_get_se_golomb(gb)) & 0xFFFFFFFF;

        if (retire != picnum) {

            DiracFrame *retire_pic = remove_frame(s->ref_frames, retire);

            if (retire_pic)

                retire_pic->reference &= DELAYED_PIC_REF;

            else

                av_log(s->avctx, AV_LOG_DEBUG, "Frame to retire not found\n");

        }

        /* if reference array is full, remove the oldest as per the spec */

        while (add_frame(s->ref_frames, MAX_REFERENCE_FRAMES, s->current_picture)) {

            av_log(s->avctx, AV_LOG_ERROR, "Reference frame overflow\n");

            remove_frame(s->ref_frames, s->ref_frames[0]->avframe->display_picture_number)->reference &= DELAYED_PIC_REF;

        }

    }

    if (s->num_refs) {

        ret = dirac_unpack_prediction_parameters(s);  /* [DIRAC_STD] 11.2 Picture Prediction Data. picture_prediction() */

        if (ret < 0)

            return ret;

        ret = dirac_unpack_block_motion_data(s);      /* [DIRAC_STD] 12. Block motion data syntax                       */

        if (ret < 0)

            return ret;

    }

    ret = dirac_unpack_idwt_params(s);                /* [DIRAC_STD] 11.3 Wavelet transform data                        */

    if (ret < 0)

        return ret;

    init_planes(s);

    return 0;

}