int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)

{

    int pending;

    int index;

    assert(!qemu_file_is_writable(f));

    index = f->buf_index + offset;

    pending = f->buf_size - index;

    if (pending < size) {

        qemu_fill_buffer(f);

        index = f->buf_index + offset;

        pending = f->buf_size - index;

    }

    if (pending <= 0) {

        return 0;

    }

    if (size > pending) {

        size = pending;

    }

    memcpy(buf, f->buf + index, size);

    return size;

}


static int ahci_dma_rw_buf(IDEDMA *dma, int is_write)

{

    AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);

    IDEState *s = &ad->port.ifs[0];

    uint8_t *p = s->io_buffer + s->io_buffer_index;

    int l = s->io_buffer_size - s->io_buffer_index;

    if (ahci_populate_sglist(ad, &s->sg)) {

        return 0;

    }

    if (is_write) {

        dma_buf_read(p, l, &s->sg);

    } else {

        dma_buf_write(p, l, &s->sg);

    }

    /* update number of transferred bytes */

    ad->cur_cmd->status = cpu_to_le32(le32_to_cpu(ad->cur_cmd->status) + l);

    s->io_buffer_index += l;

    DPRINTF(ad->port_no, "len=%#x\n", l);

    return 1;

}


void cpu_save(QEMUFile *f, void *opaque)

{

    CPUState *env = (CPUState *)opaque;

    unsigned int i, j;

    cpu_synchronize_state(env);

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

        qemu_put_betls(f, &env->gpr[i]);

#if !defined(TARGET_PPC64)

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

        qemu_put_betls(f, &env->gprh[i]);

#endif

    qemu_put_betls(f, &env->lr);

    qemu_put_betls(f, &env->ctr);

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

        qemu_put_be32s(f, &env->crf[i]);

    qemu_put_betls(f, &env->xer);

    qemu_put_betls(f, &env->reserve_addr);

    qemu_put_betls(f, &env->msr);

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

        qemu_put_betls(f, &env->tgpr[i]);

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

        union {

            float64 d;

            uint64_t l;

        } u;

        u.d = env->fpr[i];

        qemu_put_be64(f, u.l);

    }

    qemu_put_be32s(f, &env->fpscr);

    qemu_put_sbe32s(f, &env->access_type);

#if !defined(CONFIG_USER_ONLY)

#if defined(TARGET_PPC64)

    qemu_put_betls(f, &env->asr);

    qemu_put_sbe32s(f, &env->slb_nr);

#endif

    qemu_put_betls(f, &env->sdr1);

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

        qemu_put_betls(f, &env->sr[i]);

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

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

            qemu_put_betls(f, &env->DBAT[i][j]);

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

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

            qemu_put_betls(f, &env->IBAT[i][j]);

    qemu_put_sbe32s(f, &env->nb_tlb);

    qemu_put_sbe32s(f, &env->tlb_per_way);

    qemu_put_sbe32s(f, &env->nb_ways);

    qemu_put_sbe32s(f, &env->last_way);

    qemu_put_sbe32s(f, &env->id_tlbs);

    qemu_put_sbe32s(f, &env->nb_pids);

    if (env->tlb) {

        // XXX assumes 6xx

        for (i = 0; i < env->nb_tlb; i++) {

            qemu_put_betls(f, &env->tlb[i].tlb6.pte0);

            qemu_put_betls(f, &env->tlb[i].tlb6.pte1);

            qemu_put_betls(f, &env->tlb[i].tlb6.EPN);

        }

    }

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

        qemu_put_betls(f, &env->pb[i]);

#endif

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

        qemu_put_betls(f, &env->spr[i]);

    qemu_put_be32s(f, &env->vscr);

    qemu_put_be64s(f, &env->spe_acc);

    qemu_put_be32s(f, &env->spe_fscr);

    qemu_put_betls(f, &env->msr_mask);

    qemu_put_be32s(f, &env->flags);

    qemu_put_sbe32s(f, &env->error_code);

    qemu_put_be32s(f, &env->pending_interrupts);

#if !defined(CONFIG_USER_ONLY)

    qemu_put_be32s(f, &env->irq_input_state);

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

        qemu_put_betls(f, &env->excp_vectors[i]);

    qemu_put_betls(f, &env->excp_prefix);

    qemu_put_betls(f, &env->hreset_excp_prefix);

    qemu_put_betls(f, &env->ivor_mask);

    qemu_put_betls(f, &env->ivpr_mask);

    qemu_put_betls(f, &env->hreset_vector);

#endif

    qemu_put_betls(f, &env->nip);

    qemu_put_betls(f, &env->hflags);

    qemu_put_betls(f, &env->hflags_nmsr);

    qemu_put_sbe32s(f, &env->mmu_idx);

    qemu_put_sbe32s(f, &env->power_mode);

}


static DeviceState *sun4c_intctl_init(target_phys_addr_t addr,

                                      qemu_irq *parent_irq)

{

    DeviceState *dev;

    SysBusDevice *s;

    unsigned int i;

    dev = qdev_create(NULL, "sun4c_intctl");

    qdev_init(dev);

    s = sysbus_from_qdev(dev);

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

        sysbus_connect_irq(s, i, parent_irq[i]);

    }

    sysbus_mmio_map(s, 0, addr);

    return dev;

}


static int gif_image_write_header(AVFormatContext *s, int width, int height,

                                  int loop_count, uint32_t *palette)

{

    AVIOContext *pb = s->pb;

    AVRational sar = s->streams[0]->codec->sample_aspect_ratio;

    int i, aspect = 0;

    if (sar.num > 0 && sar.den > 0) {

        aspect = sar.num * 64 / sar.den - 15;

        if (aspect < 0 || aspect > 255)

            aspect = 0;

    }

    avio_write(pb, "GIF", 3);

    avio_write(pb, "89a", 3);

    avio_wl16(pb, width);

    avio_wl16(pb, height);

    if (palette) {

        avio_w8(pb, 0xf7); /* flags: global clut, 256 entries */

        avio_w8(pb, 0x1f); /* background color index */

        avio_w8(pb, aspect);

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

            const uint32_t v = palette[i] & 0xffffff;

            avio_wb24(pb, v);

        }

    } else {

        avio_w8(pb, 0); /* flags */

        avio_w8(pb, 0); /* background color index */

        avio_w8(pb, aspect);

    }

    if (loop_count >= 0 ) {

        /* "NETSCAPE EXTENSION" for looped animation GIF */

        avio_w8(pb, 0x21); /* GIF Extension code */

        avio_w8(pb, 0xff); /* Application Extension Label */

        avio_w8(pb, 0x0b); /* Length of Application Block */

        avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1);

        avio_w8(pb, 0x03); /* Length of Data Sub-Block */

        avio_w8(pb, 0x01);

        avio_wl16(pb, (uint16_t)loop_count);

        avio_w8(pb, 0x00); /* Data Sub-block Terminator */

    }

    return 0;

}


static int ipvideo_decode_block_opcode_0xA(IpvideoContext *s)

{

    int x, y;

    unsigned char P[4];

    int flags = 0;

    /* 4-color encoding for each 4x4 quadrant, or 4-color encoding on

     * either top and bottom or left and right halves */

    CHECK_STREAM_PTR(24);

    if (s->stream_ptr[0] <= s->stream_ptr[1]) {

        /* 4-color encoding for each quadrant; need 32 bytes */

        CHECK_STREAM_PTR(32);

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

            // new values for each 4x4 block

            if (!(y & 3)) {

                memcpy(P, s->stream_ptr, 4);

                s->stream_ptr += 4;

                flags = bytestream_get_le32(&s->stream_ptr);

            }

            for (x = 0; x < 4; x++, flags >>= 2)

                *s->pixel_ptr++ = P[flags & 0x03];

            s->pixel_ptr += s->stride - 4;

            // switch to right half

            if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;

        }

    } else {

        // vertical split?

        int vert = s->stream_ptr[12] <= s->stream_ptr[13];

        uint64_t flags = 0;

        /* 4-color encoding for either left and right or top and bottom

         * halves */

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

            // load values for each half

            if (!(y & 7)) {

                memcpy(P, s->stream_ptr, 4);

                s->stream_ptr += 4;

                flags = bytestream_get_le64(&s->stream_ptr);

            }

            for (x = 0; x < 4; x++, flags >>= 2)

                *s->pixel_ptr++ = P[flags & 0x03];

            if (vert) {

                s->pixel_ptr += s->stride - 4;

                // switch to right half

                if (y == 7) s->pixel_ptr -= 8 * s->stride - 4;

            } else if (y & 1) s->pixel_ptr += s->line_inc;

        }

    }

    /* report success */

    return 0;

}


static inline void dv_decode_video_segment(DVVideoContext *s,

                                           const uint8_t *buf_ptr1,

                                           const uint16_t *mb_pos_ptr)

{

    int quant, dc, dct_mode, class1, j;

    int mb_index, mb_x, mb_y, v, last_index;

    int y_stride, i;

    DCTELEM *block, *block1;

    int c_offset;

    uint8_t *y_ptr;

    const uint8_t *buf_ptr;

    PutBitContext pb, vs_pb;

    GetBitContext gb;

    BlockInfo mb_data[5 * DV_MAX_BPM], *mb, *mb1;

    DECLARE_ALIGNED_16(DCTELEM, sblock[5*DV_MAX_BPM][64]);

    DECLARE_ALIGNED_8(uint8_t, mb_bit_buffer[80 + 4]); /* allow some slack */

    DECLARE_ALIGNED_8(uint8_t, vs_bit_buffer[5 * 80 + 4]); /* allow some slack */

    const int log2_blocksize= 3-s->avctx->lowres;

    int is_field_mode[5];

    assert((((int)mb_bit_buffer)&7)==0);

    assert((((int)vs_bit_buffer)&7)==0);

    memset(sblock, 0, sizeof(sblock));

    /* pass 1 : read DC and AC coefficients in blocks */

    buf_ptr = buf_ptr1;

    block1 = &sblock[0][0];

    mb1 = mb_data;

    init_put_bits(&vs_pb, vs_bit_buffer, 5 * 80);

    for(mb_index = 0; mb_index < 5; mb_index++, mb1 += s->sys->bpm, block1 += s->sys->bpm * 64) {

        /* skip header */

        quant = buf_ptr[3] & 0x0f;

        buf_ptr += 4;

        init_put_bits(&pb, mb_bit_buffer, 80);

        mb = mb1;

        block = block1;

        is_field_mode[mb_index] = 0;

        for(j = 0;j < s->sys->bpm; j++) {

            last_index = s->sys->block_sizes[j];

            init_get_bits(&gb, buf_ptr, last_index);

            /* get the dc */

            dc = get_sbits(&gb, 9);

            dct_mode = get_bits1(&gb);

            class1 = get_bits(&gb, 2);

            if (DV_PROFILE_IS_HD(s->sys)) {

                mb->idct_put = s->idct_put[0];

                mb->scan_table = s->dv_zigzag[0];

                mb->factor_table = s->dv100_idct_factor[((s->sys->height == 720)<<1)|(j >= 4)][class1][quant];

                is_field_mode[mb_index] |= !j && dct_mode;

            } else {

                mb->idct_put = s->idct_put[dct_mode && log2_blocksize==3];

                mb->scan_table = s->dv_zigzag[dct_mode];

                mb->factor_table = s->dv_idct_factor[class1 == 3][dct_mode]

                    [quant + dv_quant_offset[class1]];

            }

            dc = dc << 2;

            /* convert to unsigned because 128 is not added in the

               standard IDCT */

            dc += 1024;

            block[0] = dc;

            buf_ptr += last_index >> 3;

            mb->pos = 0;

            mb->partial_bit_count = 0;

#ifdef VLC_DEBUG

            printf("MB block: %d, %d ", mb_index, j);

#endif

            dv_decode_ac(&gb, mb, block);

            /* write the remaining bits  in a new buffer only if the

               block is finished */

            if (mb->pos >= 64)

                bit_copy(&pb, &gb);

            block += 64;

            mb++;

        }

        /* pass 2 : we can do it just after */

#ifdef VLC_DEBUG

        printf("***pass 2 size=%d MB#=%d\n", put_bits_count(&pb), mb_index);

#endif

        block = block1;

        mb = mb1;

        init_get_bits(&gb, mb_bit_buffer, put_bits_count(&pb));

        flush_put_bits(&pb);

        for(j = 0;j < s->sys->bpm; j++, block += 64, mb++) {

            if (mb->pos < 64 && get_bits_left(&gb) > 0) {

                dv_decode_ac(&gb, mb, block);

                /* if still not finished, no need to parse other blocks */

                if (mb->pos < 64)

                    break;

            }

        }

        /* all blocks are finished, so the extra bytes can be used at

           the video segment level */

        if (j >= s->sys->bpm)

            bit_copy(&vs_pb, &gb);

    }

    /* we need a pass other the whole video segment */

#ifdef VLC_DEBUG

    printf("***pass 3 size=%d\n", put_bits_count(&vs_pb));

#endif

    block = &sblock[0][0];

    mb = mb_data;

    init_get_bits(&gb, vs_bit_buffer, put_bits_count(&vs_pb));

    flush_put_bits(&vs_pb);

    for(mb_index = 0; mb_index < 5; mb_index++) {

        for(j = 0;j < s->sys->bpm; j++) {

            if (mb->pos < 64) {

#ifdef VLC_DEBUG

                printf("start %d:%d\n", mb_index, j);

#endif

                dv_decode_ac(&gb, mb, block);

            }

            if (mb->pos >= 64 && mb->pos < 127)

                av_log(NULL, AV_LOG_ERROR, "AC EOB marker is absent pos=%d\n", mb->pos);

            block += 64;

            mb++;

        }

    }

    /* compute idct and place blocks */

    block = &sblock[0][0];

    mb = mb_data;

    for(mb_index = 0; mb_index < 5; mb_index++) {

        v = *mb_pos_ptr++;

        mb_x = v & 0xff;

        mb_y = v >> 8;

        /* We work with 720p frames split in half. The odd half-frame (chan==2,3) is displaced :-( */

        if (s->sys->height == 720 && !(s->buf[1]&0x0C)) {

               mb_y -= (mb_y>17)?18:-72; /* shifting the Y coordinate down by 72/2 macroblocks */

        }

        /* idct_put'ting luminance */

        if ((s->sys->pix_fmt == PIX_FMT_YUV420P) ||

            (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) ||

            (s->sys->height >= 720 && mb_y != 134)) {

            y_stride = (s->picture.linesize[0]<<((!is_field_mode[mb_index])*log2_blocksize)) - (2<<log2_blocksize);

        } else {

            y_stride = 0;

        }

        y_ptr = s->picture.data[0] + ((mb_y * s->picture.linesize[0] + mb_x)<<log2_blocksize);

        for(j = 0; j < 2; j++, y_ptr += y_stride) {

            for (i=0; i<2; i++, block += 64, mb++, y_ptr += (1<<log2_blocksize))

                 if (s->sys->pix_fmt == PIX_FMT_YUV422P && s->sys->width == 720 && i)

                     y_ptr -= (1<<log2_blocksize);

                 else

                     mb->idct_put(y_ptr, s->picture.linesize[0]<<is_field_mode[mb_index], block);

        }

        /* idct_put'ting chrominance */

        c_offset = (((mb_y>>(s->sys->pix_fmt == PIX_FMT_YUV420P)) * s->picture.linesize[1] +

                     (mb_x>>((s->sys->pix_fmt == PIX_FMT_YUV411P)?2:1)))<<log2_blocksize);

        for(j=2; j; j--) {

            uint8_t *c_ptr = s->picture.data[j] + c_offset;

            if (s->sys->pix_fmt == PIX_FMT_YUV411P && mb_x >= (704 / 8)) {

                  uint64_t aligned_pixels[64/8];

                  uint8_t *pixels = (uint8_t*)aligned_pixels;

                  uint8_t *c_ptr1, *ptr1;

                  int x, y;

                  mb->idct_put(pixels, 8, block);

                  for(y = 0; y < (1<<log2_blocksize); y++, c_ptr += s->picture.linesize[j], pixels += 8) {

                      ptr1= pixels + (1<<(log2_blocksize-1));

                      c_ptr1 = c_ptr + (s->picture.linesize[j]<<log2_blocksize);

                      for(x=0; x < (1<<(log2_blocksize-1)); x++) {

                          c_ptr[x]= pixels[x];

                          c_ptr1[x]= ptr1[x];

                      }

                  }

                  block += 64; mb++;

            } else {

                  y_stride = (mb_y == 134) ? (1<<log2_blocksize) :

                                             s->picture.linesize[j]<<((!is_field_mode[mb_index])*log2_blocksize);

                  for (i=0; i<(1<<(s->sys->bpm==8)); i++, block += 64, mb++, c_ptr += y_stride)

                       mb->idct_put(c_ptr, s->picture.linesize[j]<<is_field_mode[mb_index], block);

            }

        }

    }

}


static bool adding_first_cpu(void)

{

    CPUState *cpu;

    size_t count = 0;

    CPU_FOREACH(cpu) {

        count++;

        if (count > 1) {

            return false;

        }

    }

    return true;

}


static void imc_get_coeffs(AVCodecContext *avctx,

                           IMCContext *q, IMCChannel *chctx)

{

    int i, j, cw_len, cw;

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

        if (!chctx->sumLenArr[i])

            continue;

        if (chctx->bandFlagsBuf[i] || chctx->bandWidthT[i]) {

            for (j = band_tab[i]; j < band_tab[i + 1]; j++) {

                cw_len = chctx->CWlengthT[j];

                cw = 0;

                if (cw_len && (!chctx->bandFlagsBuf[i] || !chctx->skipFlags[j])) {

                    if (get_bits_count(&q->gb) + cw_len > 512) {

                        av_log(avctx, AV_LOG_WARNING,

                            "Potential problem on band %i, coefficient %i"

                            ": cw_len=%i\n", i, j, cw_len);

                    }

                    cw = get_bits(&q->gb, cw_len);

                }

                chctx->codewords[j] = cw;

            }

        }

    }

}


static int aio_write_f(int argc, char **argv)

{

    int nr_iov, c;

    int pattern = 0xcd;

    struct aio_ctx *ctx = calloc(1, sizeof(struct aio_ctx));

    BlockDriverAIOCB *acb;

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

        switch (c) {

        case 'C':

            ctx->Cflag = 1;

            break;

        case 'q':

            ctx->qflag = 1;

            break;

        case 'P':

            pattern = parse_pattern(optarg);

            if (pattern < 0) {

                return 0;

            }

            break;

        default:

            return command_usage(&aio_write_cmd);

        }

    }

    if (optind > argc - 2) {

        return command_usage(&aio_write_cmd);

    }

    ctx->offset = cvtnum(argv[optind]);

    if (ctx->offset < 0) {

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

        return 0;

    }

    optind++;

    if (ctx->offset & 0x1ff) {

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

               ctx->offset);

        return 0;

    }

    nr_iov = argc - optind;

    ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern);

    gettimeofday(&ctx->t1, NULL);

    acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,

                          ctx->qiov.size >> 9, aio_write_done, ctx);

    if (!acb) {

        free(ctx->buf);

        return -EIO;

    }

    return 0;

}


static coroutine_fn int quorum_co_flush(BlockDriverState *bs)

{

    BDRVQuorumState *s = bs->opaque;

    QuorumVoteVersion *winner = NULL;

    QuorumVotes error_votes;

    QuorumVoteValue result_value;

    int i;

    int result = 0;

    QLIST_INIT(&error_votes.vote_list);

    error_votes.compare = quorum_64bits_compare;

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

        result = bdrv_co_flush(s->children[i]->bs);

        result_value.l = result;

        quorum_count_vote(&error_votes, &result_value, i);

    }

    winner = quorum_get_vote_winner(&error_votes);

    result = winner->value.l;

    quorum_free_vote_list(&error_votes);

    return result;

}


static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,

                            TCGMemOpIdx oi)

{

    TCGMemOp memop = get_memop(oi);

#ifdef CONFIG_SOFTMMU

    unsigned memi = get_mmuidx(oi);

    TCGReg addrz, param;

    tcg_insn_unit *func;

    tcg_insn_unit *label_ptr;

    addrz = tcg_out_tlb_load(s, addr, memi, memop & MO_SIZE,

                             offsetof(CPUTLBEntry, addr_write));

    /* The fast path is exactly one insn.  Thus we can perform the entire

       TLB Hit in the (annulled) delay slot of the branch over TLB Miss.  */

    /* beq,a,pt %[xi]cc, label0 */

    label_ptr = s->code_ptr;

    tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT

                  | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);

    /* delay slot */

    tcg_out_ldst_rr(s, data, addrz, TCG_REG_O1,

                    qemu_st_opc[memop & (MO_BSWAP | MO_SIZE)]);

    /* TLB Miss.  */

    param = TCG_REG_O1;

    if (!SPARC64 && TARGET_LONG_BITS == 64) {

        /* Skip the high-part; we'll perform the extract in the trampoline.  */

        param++;

    }

    tcg_out_mov(s, TCG_TYPE_REG, param++, addr);

    if (!SPARC64 && (memop & MO_SIZE) == MO_64) {

        /* Skip the high-part; we'll perform the extract in the trampoline.  */

        param++;

    }

    tcg_out_mov(s, TCG_TYPE_REG, param++, data);

    func = qemu_st_trampoline[memop & (MO_BSWAP | MO_SIZE)];

    assert(func != NULL);

    tcg_out_call_nodelay(s, func);

    /* delay slot */

    tcg_out_movi(s, TCG_TYPE_I32, param, oi);

    *label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));

#else

    if (SPARC64 && TARGET_LONG_BITS == 32) {

        tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);

        addr = TCG_REG_T1;

    }

    tcg_out_ldst_rr(s, data, addr,

                    (guest_base ? TCG_GUEST_BASE_REG : TCG_REG_G0),

                    qemu_st_opc[memop & (MO_BSWAP | MO_SIZE)]);

#endif /* CONFIG_SOFTMMU */

}


void r4k_helper_tlbr(CPUMIPSState *env)

{

    r4k_tlb_t *tlb;

    uint8_t ASID;

    int idx;

    ASID = env->CP0_EntryHi & 0xFF;

    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;

    tlb = &env->tlb->mmu.r4k.tlb[idx];

    /* If this will change the current ASID, flush qemu's TLB.  */

    if (ASID != tlb->ASID)

        cpu_mips_tlb_flush (env, 1);

    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);

    env->CP0_EntryHi = tlb->VPN | tlb->ASID;

    env->CP0_PageMask = tlb->PageMask;

    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |

                        ((target_ulong)tlb->RI0 << CP0EnLo_RI) |

                        ((target_ulong)tlb->XI0 << CP0EnLo_XI) |

                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);

    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |

                        ((target_ulong)tlb->RI1 << CP0EnLo_RI) |

                        ((target_ulong)tlb->XI1 << CP0EnLo_XI) |

                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);

}


static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb)

{

    int i;

    int dc_y_table;

    int dc_c_table;

    int ac_y_table;

    int ac_c_table;

    int residual_eob_run = 0;

    /* fetch the DC table indexes */

    dc_y_table = get_bits(gb, 4);

    dc_c_table = get_bits(gb, 4);

    /* unpack the Y plane DC coefficients */

    residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_y_table], 0,

        1, residual_eob_run);

    /* reverse prediction of the Y-plane DC coefficients */

    reverse_dc_prediction(s, 0, s->fragment_width, s->fragment_height);

    /* unpack the C plane DC coefficients */

    residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0,

        0, residual_eob_run);

    /* reverse prediction of the C-plane DC coefficients */

    if (!(s->avctx->flags & CODEC_FLAG_GRAY))

    {

        reverse_dc_prediction(s, s->fragment_start[1],

            s->fragment_width / 2, s->fragment_height / 2);

        reverse_dc_prediction(s, s->fragment_start[2],

            s->fragment_width / 2, s->fragment_height / 2);

    }

    /* fetch the AC table indexes */

    ac_y_table = get_bits(gb, 4);

    ac_c_table = get_bits(gb, 4);

    /* unpack the group 1 AC coefficients (coeffs 1-5) */

    for (i = 1; i <= 5; i++) {

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_1[ac_y_table], i,

            1, residual_eob_run);

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_1[ac_c_table], i,

            0, residual_eob_run);

    }

    /* unpack the group 2 AC coefficients (coeffs 6-14) */

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

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_2[ac_y_table], i,

            1, residual_eob_run);

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_2[ac_c_table], i,

            0, residual_eob_run);

    }

    /* unpack the group 3 AC coefficients (coeffs 15-27) */

    for (i = 15; i <= 27; i++) {

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_3[ac_y_table], i,

            1, residual_eob_run);

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_3[ac_c_table], i,

            0, residual_eob_run);

    }

    /* unpack the group 4 AC coefficients (coeffs 28-63) */

    for (i = 28; i <= 63; i++) {

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_y_table], i,

            1, residual_eob_run);

        residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_c_table], i,

            0, residual_eob_run);

    }

    return 0;

}


int kvmppc_fixup_cpu(PowerPCCPU *cpu)

{

    CPUState *cs = CPU(cpu);

    int smt;

    /* Adjust cpu index for SMT */

    smt = kvmppc_smt_threads();

    cs->cpu_index = (cs->cpu_index / smp_threads) * smt

        + (cs->cpu_index % smp_threads);

    return 0;

}


static void *spapr_create_fdt_skel(const char *cpu_model,

                                   hwaddr initrd_base,

                                   hwaddr initrd_size,

                                   hwaddr kernel_size,

                                   const char *boot_device,

                                   const char *kernel_cmdline,

                                   uint32_t epow_irq)

{

    void *fdt;

    CPUPPCState *env;

    uint32_t start_prop = cpu_to_be32(initrd_base);

    uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);

    char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"

        "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";

    char qemu_hypertas_prop[] = "hcall-memop1";

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

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

    char *modelname;

    int i, smt = kvmppc_smt_threads();

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

    fdt = g_malloc0(FDT_MAX_SIZE);

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

    if (kernel_size) {

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

    }

    if (initrd_size) {

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

    }

    _FDT((fdt_finish_reservemap(fdt)));

    /* Root node */

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

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

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

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

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

    /* /chosen */

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

    /* Set Form1_affinity */

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

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

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

                       &start_prop, sizeof(start_prop))));

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

                       &end_prop, sizeof(end_prop))));

    if (kernel_size) {

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

                              cpu_to_be64(kernel_size) };

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

    }

    _FDT((fdt_property_string(fdt, "qemu,boot-device", boot_device)));

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

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

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

    _FDT((fdt_end_node(fdt)));

    /* cpus */

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

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

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

    modelname = g_strdup(cpu_model);

    for (i = 0; i < strlen(modelname); i++) {

        modelname[i] = toupper(modelname[i]);

    }

    /* This is needed during FDT finalization */

    spapr->cpu_model = g_strdup(modelname);

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

        CPUState *cpu = CPU(ppc_env_get_cpu(env));

        int index = cpu->cpu_index;

        uint32_t servers_prop[smp_threads];

        uint32_t gservers_prop[smp_threads * 2];

        char *nodename;

        uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),

                           0xffffffff, 0xffffffff};

        uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ;

        uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;

        uint32_t page_sizes_prop[64];

        size_t page_sizes_prop_size;

        if ((index % smt) != 0) {

            continue;

        }

        if (asprintf(&nodename, "%s@%x", modelname, index) < 0) {

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

            exit(1);

        }

        _FDT((fdt_begin_node(fdt, nodename)));

        free(nodename);

        _FDT((fdt_property_cell(fdt, "reg", index)));

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

        _FDT((fdt_property_cell(fdt, "cpu-version", env->spr[SPR_PVR])));

        _FDT((fdt_property_cell(fdt, "dcache-block-size",

                                env->dcache_line_size)));

        _FDT((fdt_property_cell(fdt, "icache-block-size",

                                env->icache_line_size)));

        _FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));

        _FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));

        _FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));

        _FDT((fdt_property_string(fdt, "status", "okay")));

        _FDT((fdt_property(fdt, "64-bit", NULL, 0)));

        /* Build interrupt servers and gservers properties */

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

            servers_prop[i] = cpu_to_be32(index + i);

            /* Hack, direct the group queues back to cpu 0 */

            gservers_prop[i*2] = cpu_to_be32(index + i);

            gservers_prop[i*2 + 1] = 0;

        }

        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-server#s",

                           servers_prop, sizeof(servers_prop))));

        _FDT((fdt_property(fdt, "ibm,ppc-interrupt-gserver#s",

                           gservers_prop, sizeof(gservers_prop))));

        if (env->mmu_model & POWERPC_MMU_1TSEG) {

            _FDT((fdt_property(fdt, "ibm,processor-segment-sizes",

                               segs, sizeof(segs))));

        }

        /* Advertise VMX/VSX (vector extensions) if available

         *   0 / no property == no vector extensions

         *   1               == VMX / Altivec available

         *   2               == VSX available */

        if (env->insns_flags & PPC_ALTIVEC) {

            uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;

            _FDT((fdt_property_cell(fdt, "ibm,vmx", vmx)));

        }

        /* Advertise DFP (Decimal Floating Point) if available

         *   0 / no property == no DFP

         *   1               == DFP available */

        if (env->insns_flags2 & PPC2_DFP) {

            _FDT((fdt_property_cell(fdt, "ibm,dfp", 1)));

        }

        page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop,

                                                      sizeof(page_sizes_prop));

        if (page_sizes_prop_size) {

            _FDT((fdt_property(fdt, "ibm,segment-page-sizes",

                               page_sizes_prop, page_sizes_prop_size)));

        }

        _FDT((fdt_end_node(fdt)));

    }

    g_free(modelname);

    _FDT((fdt_end_node(fdt)));

    /* RTAS */

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

    _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,

                       sizeof(hypertas_prop))));

    _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,

                       sizeof(qemu_hypertas_prop))));

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

        refpoints, sizeof(refpoints))));

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

    _FDT((fdt_end_node(fdt)));

    /* interrupt controller */

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

    _FDT((fdt_property_string(fdt, "device_type",

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

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

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

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

                       interrupt_server_ranges_prop,

                       sizeof(interrupt_server_ranges_prop))));

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

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

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

    _FDT((fdt_end_node(fdt)));

    /* vdevice */

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

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

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

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

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

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

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

    _FDT((fdt_end_node(fdt)));

    /* event-sources */

    spapr_events_fdt_skel(fdt, epow_irq);

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

    _FDT((fdt_finish(fdt)));

    return fdt;

}


static int create_header64(DumpState *s)

{

    int ret = 0;

    DiskDumpHeader64 *dh = NULL;

    KdumpSubHeader64 *kh = NULL;

    size_t size;

    int endian = s->dump_info.d_endian;

    uint32_t block_size;

    uint32_t sub_hdr_size;

    uint32_t bitmap_blocks;

    uint32_t status = 0;

    uint64_t offset_note;

    /* write common header, the version of kdump-compressed format is 6th */

    size = sizeof(DiskDumpHeader64);

    dh = g_malloc0(size);

    strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));

    dh->header_version = cpu_convert_to_target32(6, endian);

    block_size = s->page_size;

    dh->block_size = cpu_convert_to_target32(block_size, endian);

    sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size;

    sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);

    dh->sub_hdr_size = cpu_convert_to_target32(sub_hdr_size, endian);

    /* dh->max_mapnr may be truncated, full 64bit is in kh.max_mapnr_64 */

    dh->max_mapnr = cpu_convert_to_target32(MIN(s->max_mapnr, UINT_MAX),

                                            endian);

    dh->nr_cpus = cpu_convert_to_target32(s->nr_cpus, endian);

    bitmap_blocks = DIV_ROUND_UP(s->len_dump_bitmap, block_size) * 2;

    dh->bitmap_blocks = cpu_convert_to_target32(bitmap_blocks, endian);

    strncpy(dh->utsname.machine, ELF_MACHINE_UNAME, sizeof(dh->utsname.machine));

    if (s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) {

        status |= DUMP_DH_COMPRESSED_ZLIB;

    }

#ifdef CONFIG_LZO

    if (s->flag_compress & DUMP_DH_COMPRESSED_LZO) {

        status |= DUMP_DH_COMPRESSED_LZO;

    }

#endif

#ifdef CONFIG_SNAPPY

    if (s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) {

        status |= DUMP_DH_COMPRESSED_SNAPPY;

    }

#endif

    dh->status = cpu_convert_to_target32(status, endian);

    if (write_buffer(s->fd, 0, dh, size) < 0) {

        dump_error(s, "dump: failed to write disk dump header.\n");

        ret = -1;

        goto out;

    }

    /* write sub header */

    size = sizeof(KdumpSubHeader64);

    kh = g_malloc0(size);

    /* 64bit max_mapnr_64 */

    kh->max_mapnr_64 = cpu_convert_to_target64(s->max_mapnr, endian);

    kh->phys_base = cpu_convert_to_target64(PHYS_BASE, endian);

    kh->dump_level = cpu_convert_to_target32(DUMP_LEVEL, endian);

    offset_note = DISKDUMP_HEADER_BLOCKS * block_size + size;

    kh->offset_note = cpu_convert_to_target64(offset_note, endian);

    kh->note_size = cpu_convert_to_target64(s->note_size, endian);

    if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS *

                     block_size, kh, size) < 0) {

        dump_error(s, "dump: failed to write kdump sub header.\n");

        ret = -1;

        goto out;

    }

    /* write note */

    s->note_buf = g_malloc0(s->note_size);

    s->note_buf_offset = 0;

    /* use s->note_buf to store notes temporarily */

    if (write_elf64_notes(buf_write_note, s) < 0) {

        ret = -1;

        goto out;

    }

    if (write_buffer(s->fd, offset_note, s->note_buf,

                     s->note_size) < 0) {

        dump_error(s, "dump: failed to write notes");

        ret = -1;

        goto out;

    }

    /* get offset of dump_bitmap */

    s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size) *

                             block_size;

    /* get offset of page */

    s->offset_page = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size + bitmap_blocks) *

                     block_size;

out:

    g_free(dh);

    g_free(kh);

    g_free(s->note_buf);

    return ret;

}


unsigned int SingleCPDO(const unsigned int opcode)

{

   FPA11 *fpa11 = GET_FPA11();

   float32 rFm, rFn = 0;

   unsigned int Fd, Fm, Fn, nRc = 1;

   Fm = getFm(opcode);

   if (CONSTANT_FM(opcode))

   {

     rFm = getSingleConstant(Fm);

   }

   else

   {

     switch (fpa11->fType[Fm])

     {

        case typeSingle:

          rFm = fpa11->fpreg[Fm].fSingle;

        break;

        default: return 0;

     }

   }

   if (!MONADIC_INSTRUCTION(opcode))

   {

      Fn = getFn(opcode);

      switch (fpa11->fType[Fn])

      {

        case typeSingle:

          rFn = fpa11->fpreg[Fn].fSingle;

        break;

        default: return 0;

      }

   }

   Fd = getFd(opcode);

   switch (opcode & MASK_ARITHMETIC_OPCODE)

   {

      /* dyadic opcodes */

      case ADF_CODE:

         fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm, &fpa11->fp_status);

      break;

      case MUF_CODE:

      case FML_CODE:

        fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm, &fpa11->fp_status);

      break;

      case SUF_CODE:

         fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm, &fpa11->fp_status);

      break;

      case RSF_CODE:

         fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn, &fpa11->fp_status);

      break;

      case DVF_CODE:

      case FDV_CODE:

         fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm, &fpa11->fp_status);

      break;

      case RDF_CODE:

      case FRD_CODE:

         fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn, &fpa11->fp_status);

      break;

#if 0

      case POW_CODE:

         fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm);

      break;

      case RPW_CODE:

         fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn);

      break;

#endif

      case RMF_CODE:

         fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm, &fpa11->fp_status);

      break;

#if 0

      case POL_CODE:

         fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm);

      break;

#endif

      /* monadic opcodes */

      case MVF_CODE:

         fpa11->fpreg[Fd].fSingle = rFm;

      break;

      case MNF_CODE:

         rFm ^= 0x80000000;

         fpa11->fpreg[Fd].fSingle = rFm;

      break;

      case ABS_CODE:

         rFm &= 0x7fffffff;

         fpa11->fpreg[Fd].fSingle = rFm;

      break;

      case RND_CODE:

      case URD_CODE:

         fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm, &fpa11->fp_status);

      break;

      case SQT_CODE:

         fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm, &fpa11->fp_status);

      break;

#if 0

      case LOG_CODE:

         fpa11->fpreg[Fd].fSingle = float32_log(rFm);

      break;

      case LGN_CODE:

         fpa11->fpreg[Fd].fSingle = float32_ln(rFm);

      break;

      case EXP_CODE:

         fpa11->fpreg[Fd].fSingle = float32_exp(rFm);

      break;

      case SIN_CODE:

         fpa11->fpreg[Fd].fSingle = float32_sin(rFm);

      break;

      case COS_CODE:

         fpa11->fpreg[Fd].fSingle = float32_cos(rFm);

      break;

      case TAN_CODE:

         fpa11->fpreg[Fd].fSingle = float32_tan(rFm);

      break;

      case ASN_CODE:

         fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm);

      break;

      case ACS_CODE:

         fpa11->fpreg[Fd].fSingle = float32_arccos(rFm);

      break;

      case ATN_CODE:

         fpa11->fpreg[Fd].fSingle = float32_arctan(rFm);

      break;

#endif

      case NRM_CODE:

      break;

      default:

      {

        nRc = 0;

      }

   }

   if (0 != nRc) fpa11->fType[Fd] = typeSingle;

   return nRc;

}


static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,

                             const char *replaces,

                             int64_t speed, uint32_t granularity,

                             int64_t buf_size,

                             BlockdevOnError on_source_error,

                             BlockdevOnError on_target_error,

                             BlockCompletionFunc *cb,

                             void *opaque, Error **errp,

                             const BlockJobDriver *driver,

                             bool is_none_mode, BlockDriverState *base)

{

    MirrorBlockJob *s;

    if (granularity == 0) {

        /* Choose the default granularity based on the target file's cluster

         * size, clamped between 4k and 64k.  */

        BlockDriverInfo bdi;

        if (bdrv_get_info(target, &bdi) >= 0 && bdi.cluster_size != 0) {

            granularity = MAX(4096, bdi.cluster_size);

            granularity = MIN(65536, granularity);

        } else {

            granularity = 65536;

        }

    }

    assert ((granularity & (granularity - 1)) == 0);

    if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||

         on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&

        !bdrv_iostatus_is_enabled(bs)) {

        error_set(errp, QERR_INVALID_PARAMETER, "on-source-error");

        return;

    }

    s = block_job_create(driver, bs, speed, cb, opaque, errp);

    if (!s) {

        return;

    }

    s->replaces = g_strdup(replaces);

    s->on_source_error = on_source_error;

    s->on_target_error = on_target_error;

    s->target = target;

    s->is_none_mode = is_none_mode;

    s->base = base;

    s->granularity = granularity;

    s->buf_size = MAX(buf_size, granularity);

    s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);

    if (!s->dirty_bitmap) {

        return;

    }

    bdrv_set_enable_write_cache(s->target, true);

    bdrv_set_on_error(s->target, on_target_error, on_target_error);

    bdrv_iostatus_enable(s->target);

    s->common.co = qemu_coroutine_create(mirror_run);

    trace_mirror_start(bs, s, s->common.co, opaque);

    qemu_coroutine_enter(s->common.co, s);

}


static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,

                            AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    AC3DecodeContext *s = avctx->priv_data;

    int16_t *out_samples = (int16_t *)data;

    int blk, ch, err;

    const uint8_t *channel_map;

    const float *output[AC3_MAX_CHANNELS];

    /* initialize the GetBitContext with the start of valid AC-3 Frame */

    if (s->input_buffer) {

        /* copy input buffer to decoder context to avoid reading past the end

           of the buffer, which can be caused by a damaged input stream. */

        memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));

        init_get_bits(&s->gbc, s->input_buffer, buf_size * 8);

    } else {

        init_get_bits(&s->gbc, buf, buf_size * 8);

    }

    /* parse the syncinfo */

    *data_size = 0;

    err = parse_frame_header(s);

    if (err) {

        switch(err) {

            case AAC_AC3_PARSE_ERROR_SYNC:

                av_log(avctx, AV_LOG_ERROR, "frame sync error\n");

                return -1;

            case AAC_AC3_PARSE_ERROR_BSID:

                av_log(avctx, AV_LOG_ERROR, "invalid bitstream id\n");

                break;

            case AAC_AC3_PARSE_ERROR_SAMPLE_RATE:

                av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n");

                break;

            case AAC_AC3_PARSE_ERROR_FRAME_SIZE:

                av_log(avctx, AV_LOG_ERROR, "invalid frame size\n");

                break;

            case AAC_AC3_PARSE_ERROR_FRAME_TYPE:

                /* skip frame if CRC is ok. otherwise use error concealment. */

                /* TODO: add support for substreams and dependent frames */

                if(s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) {

                    av_log(avctx, AV_LOG_ERROR, "unsupported frame type : skipping frame\n");

                    return s->frame_size;

                } else {

                    av_log(avctx, AV_LOG_ERROR, "invalid frame type\n");

                }

                break;

            default:

                av_log(avctx, AV_LOG_ERROR, "invalid header\n");

                break;

        }

    } else {

        /* check that reported frame size fits in input buffer */

        if (s->frame_size > buf_size) {

            av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");

            err = AAC_AC3_PARSE_ERROR_FRAME_SIZE;

        } else if (avctx->error_recognition >= FF_ER_CAREFUL) {

            /* check for crc mismatch */

            if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &buf[2], s->frame_size-2)) {

                av_log(avctx, AV_LOG_ERROR, "frame CRC mismatch\n");

                err = AAC_AC3_PARSE_ERROR_CRC;

            }

        }

    }

    /* if frame is ok, set audio parameters */

    if (!err) {

        avctx->sample_rate = s->sample_rate;

        avctx->bit_rate = s->bit_rate;

        /* channel config */

        s->out_channels = s->channels;

        s->output_mode = s->channel_mode;

        if(s->lfe_on)

            s->output_mode |= AC3_OUTPUT_LFEON;

        if (avctx->request_channels > 0 && avctx->request_channels <= 2 &&

                avctx->request_channels < s->channels) {

            s->out_channels = avctx->request_channels;

            s->output_mode  = avctx->request_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO;

            s->channel_layout = ff_ac3_channel_layout_tab[s->output_mode];

        }

        avctx->channels = s->out_channels;

        avctx->channel_layout = s->channel_layout;

        /* set downmixing coefficients if needed */

        if(s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) &&

                s->fbw_channels == s->out_channels)) {

            set_downmix_coeffs(s);

        }

    } else if (!s->out_channels) {

        s->out_channels = avctx->channels;

        if(s->out_channels < s->channels)

            s->output_mode  = s->out_channels == 1 ? AC3_CHMODE_MONO : AC3_CHMODE_STEREO;

    }

    /* decode the audio blocks */

    channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];

    for (ch = 0; ch < s->out_channels; ch++)

        output[ch] = s->output[channel_map[ch]];

    for (blk = 0; blk < s->num_blocks; blk++) {

        if (!err && decode_audio_block(s, blk)) {

            av_log(avctx, AV_LOG_ERROR, "error decoding the audio block\n");

            err = 1;

        }

        s->fmt_conv.float_to_int16_interleave(out_samples, output, 256, s->out_channels);

        out_samples += 256 * s->out_channels;

    }

    *data_size = s->num_blocks * 256 * avctx->channels * sizeof (int16_t);

    return FFMIN(buf_size, s->frame_size);

}


static void v9fs_flush(void *opaque)

{

    int16_t tag;

    size_t offset = 7;

    V9fsPDU *cancel_pdu;

    V9fsPDU *pdu = opaque;

    V9fsState *s = pdu->s;

    pdu_unmarshal(pdu, offset, "w", &tag);

    QLIST_FOREACH(cancel_pdu, &s->active_list, next) {

        if (cancel_pdu->tag == tag) {

            break;

        }

    }

    if (cancel_pdu) {

        cancel_pdu->cancelled = 1;

        /*

         * Wait for pdu to complete.

         */

        qemu_co_queue_wait(&cancel_pdu->complete);

        cancel_pdu->cancelled = 0;

        free_pdu(pdu->s, cancel_pdu);

    }

    complete_pdu(s, pdu, 7);

    return;

}


void qemu_savevm_send_postcopy_advise(QEMUFile *f)

{

    uint64_t tmp[2];

    tmp[0] = cpu_to_be64(getpagesize());

    tmp[1] = cpu_to_be64(1ul << qemu_target_page_bits());

    trace_qemu_savevm_send_postcopy_advise();

    qemu_savevm_command_send(f, MIG_CMD_POSTCOPY_ADVISE, 16, (uint8_t *)tmp);

}


static void add_qemu_cpu_model_features(S390FeatBitmap fbm)

{

    static const int feats[] = {

        S390_FEAT_DAT_ENH,

        S390_FEAT_IDTE_SEGMENT,

        S390_FEAT_STFLE,

        S390_FEAT_SENSE_RUNNING_STATUS,

        S390_FEAT_EXTENDED_IMMEDIATE,

        S390_FEAT_EXTENDED_TRANSLATION_2,

        S390_FEAT_MSA,

        S390_FEAT_EXTENDED_TRANSLATION_3,

        S390_FEAT_LONG_DISPLACEMENT,

        S390_FEAT_LONG_DISPLACEMENT_FAST,

        S390_FEAT_ETF2_ENH,

        S390_FEAT_STORE_CLOCK_FAST,

        S390_FEAT_MOVE_WITH_OPTIONAL_SPEC,

        S390_FEAT_ETF3_ENH,

        S390_FEAT_COMPARE_AND_SWAP_AND_STORE,

        S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2,

        S390_FEAT_GENERAL_INSTRUCTIONS_EXT,

        S390_FEAT_EXECUTE_EXT,

        S390_FEAT_FLOATING_POINT_SUPPPORT_ENH,

        S390_FEAT_STFLE_45,

        S390_FEAT_STFLE_49,

        S390_FEAT_LOCAL_TLB_CLEARING,

        S390_FEAT_INTERLOCKED_ACCESS_2,

        S390_FEAT_STFLE_53,

        S390_FEAT_MSA_EXT_5,

        S390_FEAT_MSA_EXT_3,

        S390_FEAT_MSA_EXT_4,

    };

    int i;

    for (i = 0; i < ARRAY_SIZE(feats); i++) {

        set_bit(feats[i], fbm);

    }

}


static target_long monitor_get_decr (const struct MonitorDef *md, int val)

{

    CPUState *env = mon_get_cpu();

    if (!env)

        return 0;

    return cpu_ppc_load_decr(env);

}


START_TEST(qobject_to_qlist_test)

{

    QList *qlist;

    qlist = qlist_new();

    fail_unless(qobject_to_qlist(QOBJECT(qlist)) == qlist);

    // destroy doesn't exist yet

    g_free(qlist);

}


CharDriverState *qemu_chr_find(const char *name)

{

    CharDriverState *chr;

    TAILQ_FOREACH(chr, &chardevs, next) {

        if (strcmp(chr->label, name) != 0)

            continue;

        return chr;

    }

    return NULL;

}


static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt,

                                 const AVFrame *pict, int *got_packet)

{

    A64Context *c = avctx->priv_data;

    AVFrame *const p = avctx->coded_frame;

    int frame;

    int x, y;

    int b_height;

    int b_width;

    int req_size, ret;

    uint8_t *buf;

    int *charmap     = c->mc_charmap;

    uint8_t *colram  = c->mc_colram;

    uint8_t *charset = c->mc_charset;

    int *meta        = c->mc_meta_charset;

    int *best_cb     = c->mc_best_cb;

    int charset_size = 0x800 * (INTERLACED + 1);

    int colram_size  = 0x100 * c->mc_use_5col;

    int screen_size;

    if(CROP_SCREENS) {

        b_height = FFMIN(avctx->height,C64YRES) >> 3;

        b_width  = FFMIN(avctx->width ,C64XRES) >> 3;

        screen_size = b_width * b_height;

    } else {

        b_height = C64YRES >> 3;

        b_width  = C64XRES >> 3;

        screen_size = 0x400;

    }

    /* no data, means end encoding asap */

    if (!pict) {

        /* all done, end encoding */

        if (!c->mc_lifetime) return 0;

        /* no more frames in queue, prepare to flush remaining frames */

        if (!c->mc_frame_counter) {

            c->mc_lifetime = 0;

        }

        /* still frames in queue so limit lifetime to remaining frames */

        else c->mc_lifetime = c->mc_frame_counter;

    /* still new data available */

    } else {

        /* fill up mc_meta_charset with data until lifetime exceeds */

        if (c->mc_frame_counter < c->mc_lifetime) {

            *p = *pict;

            p->pict_type = AV_PICTURE_TYPE_I;

            p->key_frame = 1;

            to_meta_with_crop(avctx, p, meta + 32000 * c->mc_frame_counter);

            c->mc_frame_counter++;

            if (c->next_pts == AV_NOPTS_VALUE)

                c->next_pts = pict->pts;

            /* lifetime is not reached so wait for next frame first */

            return 0;

        }

    }

    /* lifetime reached so now convert X frames at once */

    if (c->mc_frame_counter == c->mc_lifetime) {

        req_size = 0;

        /* any frames to encode? */

        if (c->mc_lifetime) {

            req_size = charset_size + c->mc_lifetime*(screen_size + colram_size);

            if ((ret = ff_alloc_packet(pkt, req_size)) < 0) {

                av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", req_size);

                return ret;

            }

            buf = pkt->data;

            /* calc optimal new charset + charmaps */

            ret = ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb,

                               CHARSET_CHARS, 50, charmap, &c->randctx);

            if (ret < 0)

                return ret;

            ret = ff_do_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb,

                             CHARSET_CHARS, 50, charmap, &c->randctx);

            if (ret < 0)

                return ret;

            /* create colorram map and a c64 readable charset */

            render_charset(avctx, charset, colram);

            /* copy charset to buf */

            memcpy(buf, charset, charset_size);

            /* advance pointers */

            buf      += charset_size;

            charset  += charset_size;

        }

        /* write x frames to buf */

        for (frame = 0; frame < c->mc_lifetime; frame++) {

            /* copy charmap to buf. buf is uchar*, charmap is int*, so no memcpy here, sorry */

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

                for (x = 0; x < b_width; x++) {

                    buf[y * b_width + x] = charmap[y * b_width + x];

                }

            }

            /* advance pointers */

            buf += screen_size;

            req_size += screen_size;

            /* compress and copy colram to buf */

            if (c->mc_use_5col) {

                a64_compress_colram(buf, charmap, colram);

                /* advance pointers */

                buf += colram_size;

                req_size += colram_size;

            }

            /* advance to next charmap */

            charmap += 1000;

        }

        AV_WB32(avctx->extradata + 4,  c->mc_frame_counter);

        AV_WB32(avctx->extradata + 8,  charset_size);

        AV_WB32(avctx->extradata + 12, screen_size + colram_size);

        /* reset counter */

        c->mc_frame_counter = 0;

        pkt->pts = pkt->dts = c->next_pts;

        c->next_pts         = AV_NOPTS_VALUE;

        pkt->size   = req_size;

        pkt->flags |= AV_PKT_FLAG_KEY;

        *got_packet = !!req_size;

    }

    return 0;

}


static void vm_completion(ReadLineState *rs, const char *str)

{

    size_t len;

    BlockDriverState *bs;

    BdrvNextIterator *it = NULL;

    len = strlen(str);

    readline_set_completion_index(rs, len);

    while ((it = bdrv_next(it, &bs))) {

        SnapshotInfoList *snapshots, *snapshot;

        AioContext *ctx = bdrv_get_aio_context(bs);

        bool ok = false;

        aio_context_acquire(ctx);

        if (bdrv_can_snapshot(bs)) {

            ok = bdrv_query_snapshot_info_list(bs, &snapshots, NULL) == 0;

        }

        aio_context_release(ctx);

        if (!ok) {

            continue;

        }

        snapshot = snapshots;

        while (snapshot) {

            char *completion = snapshot->value->name;

            if (!strncmp(str, completion, len)) {

                readline_add_completion(rs, completion);

            }

            completion = snapshot->value->id;

            if (!strncmp(str, completion, len)) {

                readline_add_completion(rs, completion);

            }

            snapshot = snapshot->next;

        }

        qapi_free_SnapshotInfoList(snapshots);

    }

}


static int mpegps_read_packet(AVFormatContext *s,

                              AVPacket *pkt)

{

    AVStream *st;

    int len, startcode, i, type, codec_id;

    int64_t pts, dts;

 redo:

    len = mpegps_read_pes_header(s, NULL, &startcode, &pts, &dts, 1);

    if (len < 0)

        return len;

    /* now find stream */

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

        st = s->streams[i];

        if (st->id == startcode)

            goto found;

    }

    if (startcode >= 0x1e0 && startcode <= 0x1ef) {

        type = CODEC_TYPE_VIDEO;

        codec_id = CODEC_ID_MPEG1VIDEO;

    } else if (startcode >= 0x1c0 && startcode <= 0x1df) {

        type = CODEC_TYPE_AUDIO;

        codec_id = CODEC_ID_MP2;

    } else if (startcode >= 0x80 && startcode <= 0x9f) {

        type = CODEC_TYPE_AUDIO;

        codec_id = CODEC_ID_AC3;

    } else if (startcode >= 0xa0 && startcode <= 0xbf) {

        type = CODEC_TYPE_AUDIO;

        codec_id = CODEC_ID_PCM_S16BE;

    } else {

    skip:

        /* skip packet */

        url_fskip(&s->pb, len);

        goto redo;

    }

    /* no stream found: add a new stream */

    st = av_new_stream(s, startcode);

    if (!st)

        goto skip;

    st->codec.codec_type = type;

    st->codec.codec_id = codec_id;

    if (codec_id != CODEC_ID_PCM_S16BE)

        st->need_parsing = 1;

 found:

    if (startcode >= 0xa0 && startcode <= 0xbf) {

        int b1, freq;

        static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 };

        /* for LPCM, we just skip the header and consider it is raw

           audio data */

        if (len <= 3)

            goto skip;

        get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */

        b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */

        get_byte(&s->pb); /* dynamic range control (0x80 = off) */

        len -= 3;

        freq = (b1 >> 4) & 3;

        st->codec.sample_rate = lpcm_freq_tab[freq];

        st->codec.channels = 1 + (b1 & 7);

        st->codec.bit_rate = st->codec.channels * st->codec.sample_rate * 2;

    }

    av_new_packet(pkt, len);

    get_buffer(&s->pb, pkt->data, pkt->size);

    pkt->pts = pts;

    pkt->dts = dts;

    pkt->stream_index = st->index;

#if 0

    printf("%d: pts=%0.3f dts=%0.3f\n",

           pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0);

#endif

    return 0;

}


static int check_for_evdev(void)

{

    SDL_SysWMinfo info;

    XkbDescPtr desc;

    int has_evdev = 0;

    const char *keycodes;

    SDL_VERSION(&info.version);

    if (!SDL_GetWMInfo(&info))

        return 0;

    desc = XkbGetKeyboard(info.info.x11.display,

                          XkbGBN_AllComponentsMask,

                          XkbUseCoreKbd);

    if (desc == NULL || desc->names == NULL)

        return 0;

    keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);

    if (keycodes == NULL)

        fprintf(stderr, "could not lookup keycode name\n");

    else if (strstart(keycodes, "evdev", NULL))

        has_evdev = 1;

    else if (!strstart(keycodes, "xfree86", NULL))

        fprintf(stderr,

                "unknown keycodes `%s', please report to qemu-devel@nongnu.org\n",

                keycodes);

    XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);

    return has_evdev;

}


static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,

                                                       hwaddr addr,

                                                       uint64_t *value,

                                                       unsigned size,

                                                       unsigned shift,

                                                       uint64_t mask,

                                                       MemTxAttrs attrs)

{

    uint64_t tmp;

    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);

    if (mr->subpage) {

        trace_memory_region_subpage_read(get_cpu_index(), mr, addr, tmp, size);

    } else if (TRACE_MEMORY_REGION_OPS_READ_ENABLED) {

        hwaddr abs_addr = memory_region_to_absolute_addr(mr, addr);

        trace_memory_region_ops_read(get_cpu_index(), mr, abs_addr, tmp, size);

    }

    *value |= (tmp & mask) << shift;

    return MEMTX_OK;

}


static int flic_decode_frame_8BPP(AVCodecContext *avctx,

                                  void *data, int *data_size,

                                  const uint8_t *buf, int buf_size)

{

    FlicDecodeContext *s = avctx->priv_data;

    int stream_ptr = 0;

    int pixel_ptr;

    int palette_ptr;

    unsigned char palette_idx1;

    unsigned char palette_idx2;

    unsigned int frame_size;

    int num_chunks;

    unsigned int chunk_size;

    int chunk_type;

    int i, j;

    int color_packets;

    int color_changes;

    int color_shift;

    unsigned char r, g, b;

    int lines;

    int compressed_lines;

    int starting_line;

    signed short line_packets;

    int y_ptr;

    int byte_run;

    int pixel_skip;

    int pixel_countdown;

    unsigned char *pixels;

    unsigned int pixel_limit;

    s->frame.reference = 3;

    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;

    if (avctx->reget_buffer(avctx, &s->frame) < 0) {

        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");

        return -1;

    }

    pixels = s->frame.data[0];

    pixel_limit = s->avctx->height * s->frame.linesize[0];

    if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE))

        return AVERROR_INVALIDDATA;

    frame_size = AV_RL32(&buf[stream_ptr]);

    if (frame_size > buf_size)

        frame_size = buf_size;

    stream_ptr += 6;  /* skip the magic number */

    num_chunks = AV_RL16(&buf[stream_ptr]);

    stream_ptr += 10;  /* skip padding */

    frame_size -= 16;

    /* iterate through the chunks */

    while ((frame_size >= 6) && (num_chunks > 0)) {

        int stream_ptr_after_chunk;

        chunk_size = AV_RL32(&buf[stream_ptr]);

        if (chunk_size > frame_size) {

            av_log(avctx, AV_LOG_WARNING,

                   "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);

            chunk_size = frame_size;

        }

        stream_ptr_after_chunk = stream_ptr + chunk_size;

        stream_ptr += 4;

        chunk_type = AV_RL16(&buf[stream_ptr]);

        stream_ptr += 2;

        switch (chunk_type) {

        case FLI_256_COLOR:

        case FLI_COLOR:

            /* check special case: If this file is from the Magic Carpet

             * game and uses 6-bit colors even though it reports 256-color

             * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during

             * initialization) */

            if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))

                color_shift = 0;

            else

                color_shift = 2;

            /* set up the palette */

            color_packets = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            palette_ptr = 0;

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

                /* first byte is how many colors to skip */

                palette_ptr += buf[stream_ptr++];

                /* next byte indicates how many entries to change */

                color_changes = buf[stream_ptr++];

                /* if there are 0 color changes, there are actually 256 */

                if (color_changes == 0)

                    color_changes = 256;

                if (stream_ptr + color_changes * 3 > stream_ptr_after_chunk)

                    break;

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

                    unsigned int entry;

                    /* wrap around, for good measure */

                    if ((unsigned)palette_ptr >= 256)

                        palette_ptr = 0;

                    r = buf[stream_ptr++] << color_shift;

                    g = buf[stream_ptr++] << color_shift;

                    b = buf[stream_ptr++] << color_shift;

                    entry = 0xFF << 24 | r << 16 | g << 8 | b;

                    if (color_shift == 2)

                        entry |= entry >> 6 & 0x30303;

                    if (s->palette[palette_ptr] != entry)

                        s->new_palette = 1;

                    s->palette[palette_ptr++] = entry;

                }

            }

            break;

        case FLI_DELTA:

            y_ptr = 0;

            compressed_lines = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            while (compressed_lines > 0) {

                if (stream_ptr + 2 > stream_ptr_after_chunk)

                    break;

                line_packets = AV_RL16(&buf[stream_ptr]);

                stream_ptr += 2;

                if ((line_packets & 0xC000) == 0xC000) {

                    // line skip opcode

                    line_packets = -line_packets;

                    y_ptr += line_packets * s->frame.linesize[0];

                } else if ((line_packets & 0xC000) == 0x4000) {

                    av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);

                } else if ((line_packets & 0xC000) == 0x8000) {

                    // "last byte" opcode

                    pixel_ptr= y_ptr + s->frame.linesize[0] - 1;

                    CHECK_PIXEL_PTR(0);

                    pixels[pixel_ptr] = line_packets & 0xff;

                } else {

                    compressed_lines--;

                    pixel_ptr = y_ptr;

                    CHECK_PIXEL_PTR(0);

                    pixel_countdown = s->avctx->width;

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

                        if (stream_ptr + 2 > stream_ptr_after_chunk)

                            break;

                        /* account for the skip bytes */

                        pixel_skip = buf[stream_ptr++];

                        pixel_ptr += pixel_skip;

                        pixel_countdown -= pixel_skip;

                        byte_run = (signed char)(buf[stream_ptr++]);

                        if (byte_run < 0) {

                            byte_run = -byte_run;

                            palette_idx1 = buf[stream_ptr++];

                            palette_idx2 = buf[stream_ptr++];

                            CHECK_PIXEL_PTR(byte_run * 2);

                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {

                                pixels[pixel_ptr++] = palette_idx1;

                                pixels[pixel_ptr++] = palette_idx2;

                            }

                        } else {

                            CHECK_PIXEL_PTR(byte_run * 2);

                            if (stream_ptr + byte_run * 2 > stream_ptr_after_chunk)

                                break;

                            for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {

                                palette_idx1 = buf[stream_ptr++];

                                pixels[pixel_ptr++] = palette_idx1;

                            }

                        }

                    }

                    y_ptr += s->frame.linesize[0];

                }

            }

            break;

        case FLI_LC:

            /* line compressed */

            starting_line = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            y_ptr = 0;

            y_ptr += starting_line * s->frame.linesize[0];

            compressed_lines = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            while (compressed_lines > 0) {

                pixel_ptr = y_ptr;

                CHECK_PIXEL_PTR(0);

                pixel_countdown = s->avctx->width;

                line_packets = buf[stream_ptr++];

                if (stream_ptr + 2 * line_packets > stream_ptr_after_chunk)

                    break;

                if (line_packets > 0) {

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

                        /* account for the skip bytes */

                        pixel_skip = buf[stream_ptr++];

                        pixel_ptr += pixel_skip;

                        pixel_countdown -= pixel_skip;

                        byte_run = (signed char)(buf[stream_ptr++]);

                        if (byte_run > 0) {

                            CHECK_PIXEL_PTR(byte_run);

                            if (stream_ptr + byte_run > stream_ptr_after_chunk)

                                break;

                            for (j = 0; j < byte_run; j++, pixel_countdown--) {

                                palette_idx1 = buf[stream_ptr++];

                                pixels[pixel_ptr++] = palette_idx1;

                            }

                        } else if (byte_run < 0) {

                            byte_run = -byte_run;

                            palette_idx1 = buf[stream_ptr++];

                            CHECK_PIXEL_PTR(byte_run);

                            for (j = 0; j < byte_run; j++, pixel_countdown--) {

                                pixels[pixel_ptr++] = palette_idx1;

                            }

                        }

                    }

                }

                y_ptr += s->frame.linesize[0];

                compressed_lines--;

            }

            break;

        case FLI_BLACK:

            /* set the whole frame to color 0 (which is usually black) */

            memset(pixels, 0,

                s->frame.linesize[0] * s->avctx->height);

            break;

        case FLI_BRUN:

            /* Byte run compression: This chunk type only occurs in the first

             * FLI frame and it will update the entire frame. */

            y_ptr = 0;

            for (lines = 0; lines < s->avctx->height; lines++) {

                pixel_ptr = y_ptr;

                /* disregard the line packets; instead, iterate through all

                 * pixels on a row */

                stream_ptr++;

                pixel_countdown = s->avctx->width;

                while (pixel_countdown > 0) {

                    if (stream_ptr + 1 > stream_ptr_after_chunk)

                        break;

                    byte_run = (signed char)(buf[stream_ptr++]);

                    if (byte_run > 0) {

                        palette_idx1 = buf[stream_ptr++];

                        CHECK_PIXEL_PTR(byte_run);

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

                            pixels[pixel_ptr++] = palette_idx1;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",

                                       pixel_countdown, lines);

                        }

                    } else {  /* copy bytes if byte_run < 0 */

                        byte_run = -byte_run;

                        CHECK_PIXEL_PTR(byte_run);

                        if (stream_ptr + byte_run > stream_ptr_after_chunk)

                            break;

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

                            palette_idx1 = buf[stream_ptr++];

                            pixels[pixel_ptr++] = palette_idx1;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",

                                       pixel_countdown, lines);

                        }

                    }

                }

                y_ptr += s->frame.linesize[0];

            }

            break;

        case FLI_COPY:

            /* copy the chunk (uncompressed frame) */

            if (chunk_size - 6 != s->avctx->width * s->avctx->height) {

                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \

                       "has incorrect size, skipping chunk\n", chunk_size - 6);

            } else {

                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;

                     y_ptr += s->frame.linesize[0]) {

                    memcpy(&pixels[y_ptr], &buf[stream_ptr],

                        s->avctx->width);

                    stream_ptr += s->avctx->width;

                }

            }

            break;

        case FLI_MINI:

            /* some sort of a thumbnail? disregard this chunk... */

            break;

        default:

            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);

            break;

        }

        stream_ptr = stream_ptr_after_chunk;

        frame_size -= chunk_size;

        num_chunks--;

    }

    /* by the end of the chunk, the stream ptr should equal the frame

     * size (minus 1, possibly); if it doesn't, issue a warning */

    if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))

        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \

               "and final chunk ptr = %d\n", buf_size, stream_ptr);

    /* make the palette available on the way out */

    memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);

    if (s->new_palette) {

        s->frame.palette_has_changed = 1;

        s->new_palette = 0;

    }

    *data_size=sizeof(AVFrame);

    *(AVFrame*)data = s->frame;

    return buf_size;

}


static int dcstr_read_header(AVFormatContext *s)

{

    unsigned codec, align;

    AVStream *st;

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;

    st->codecpar->channels    = avio_rl32(s->pb);

    st->codecpar->sample_rate = avio_rl32(s->pb);

    codec                  = avio_rl32(s->pb);

    align                  = avio_rl32(s->pb);

    avio_skip(s->pb, 4);

    st->duration           = avio_rl32(s->pb);

    st->codecpar->channels   *= avio_rl32(s->pb);

    if (!align || align > INT_MAX / st->codecpar->channels)

        return AVERROR_INVALIDDATA;

    st->codecpar->block_align = align * st->codecpar->channels;

    switch (codec) {

    case  4: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;

    case 16: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break;

    default: avpriv_request_sample(s, "codec %X", codec);

             return AVERROR_PATCHWELCOME;

    }

    avio_skip(s->pb, 0x800 - avio_tell(s->pb));

    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);

    return 0;

}


int ff_oss_audio_open(AVFormatContext *s1, int is_output,

                      const char *audio_device)

{

    OSSAudioData *s = s1->priv_data;

    int audio_fd;

    int tmp, err;

    char *flip = getenv("AUDIO_FLIP_LEFT");

    if (is_output)

        audio_fd = avpriv_open(audio_device, O_WRONLY);

    else

        audio_fd = avpriv_open(audio_device, O_RDONLY);

    if (audio_fd < 0) {

        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));

        return AVERROR(EIO);

    }

    if (flip && *flip == '1') {

        s->flip_left = 1;

    }

    /* non blocking mode */

    if (!is_output)

        fcntl(audio_fd, F_SETFL, O_NONBLOCK);

    s->frame_size = OSS_AUDIO_BLOCK_SIZE;

    /* select format : favour native format */

    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);

#if HAVE_BIGENDIAN

    if (tmp & AFMT_S16_BE) {

        tmp = AFMT_S16_BE;

    } else if (tmp & AFMT_S16_LE) {

        tmp = AFMT_S16_LE;

    } else {

        tmp = 0;

    }

#else

    if (tmp & AFMT_S16_LE) {

        tmp = AFMT_S16_LE;

    } else if (tmp & AFMT_S16_BE) {

        tmp = AFMT_S16_BE;

    } else {

        tmp = 0;

    }

#endif

    switch(tmp) {

    case AFMT_S16_LE:

        s->codec_id = AV_CODEC_ID_PCM_S16LE;

        break;

    case AFMT_S16_BE:

        s->codec_id = AV_CODEC_ID_PCM_S16BE;

        break;

    default:

        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");

        close(audio_fd);

        return AVERROR(EIO);

    }

    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);

    if (err < 0) {

        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SETFMT: %s\n", strerror(errno));

        goto fail;

    }

    tmp = (s->channels == 2);

    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);

    if (err < 0) {

        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_STEREO: %s\n", strerror(errno));

        goto fail;

    }

    tmp = s->sample_rate;

    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);

    if (err < 0) {

        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SPEED: %s\n", strerror(errno));

        goto fail;

    }

    s->sample_rate = tmp; /* store real sample rate */

    s->fd = audio_fd;

    return 0;

 fail:

    close(audio_fd);

    return AVERROR(EIO);

}


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

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

{

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

    const int srcW= c->srcW;

    const int dstW= c->dstW;

    const int dstH= c->dstH;

    const int chrDstW= c->chrDstW;

    const int chrSrcW= c->chrSrcW;

    const int lumXInc= c->lumXInc;

    const int chrXInc= c->chrXInc;

    const enum PixelFormat dstFormat= c->dstFormat;

    const enum PixelFormat srcFormat= c->srcFormat;

    const int flags= c->flags;

    int16_t *vLumFilterPos= c->vLumFilterPos;

    int16_t *vChrFilterPos= c->vChrFilterPos;

    int16_t *hLumFilterPos= c->hLumFilterPos;

    int16_t *hChrFilterPos= c->hChrFilterPos;

    int16_t *vLumFilter= c->vLumFilter;

    int16_t *vChrFilter= c->vChrFilter;

    int16_t *hLumFilter= c->hLumFilter;

    int16_t *hChrFilter= c->hChrFilter;

    int32_t *lumMmxFilter= c->lumMmxFilter;

    int32_t *chrMmxFilter= c->chrMmxFilter;

    int32_t *alpMmxFilter= c->alpMmxFilter;

    const int vLumFilterSize= c->vLumFilterSize;

    const int vChrFilterSize= c->vChrFilterSize;

    const int hLumFilterSize= c->hLumFilterSize;

    const int hChrFilterSize= c->hChrFilterSize;

    int16_t **lumPixBuf= c->lumPixBuf;

    int16_t **chrPixBuf= c->chrPixBuf;

    int16_t **alpPixBuf= c->alpPixBuf;

    const int vLumBufSize= c->vLumBufSize;

    const int vChrBufSize= c->vChrBufSize;

    uint8_t *formatConvBuffer= c->formatConvBuffer;

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

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

    int lastDstY;

    uint32_t *pal=c->pal_yuv;

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

    int dstY= c->dstY;

    int lumBufIndex= c->lumBufIndex;

    int chrBufIndex= c->chrBufIndex;

    int lastInLumBuf= c->lastInLumBuf;

    int lastInChrBuf= c->lastInChrBuf;

    if (isPacked(c->srcFormat)) {

        src[0]=

        src[1]=

        src[2]=

        src[3]= src[0];

        srcStride[0]=

        srcStride[1]=

        srcStride[2]=

        srcStride[3]= srcStride[0];

    }

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

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

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

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

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

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

                   srcSliceY,    srcSliceH,    dstY,    dstH);

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

                   vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);

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

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

        if (flags & SWS_PRINT_INFO && !warnedAlready) {

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

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

            warnedAlready=1;

        }

    }

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

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

       currently, so people might do it. */

    if (srcSliceY ==0) {

        lumBufIndex=0;

        chrBufIndex=0;

        dstY=0;

        lastInLumBuf= -1;

        lastInChrBuf= -1;

    }

    lastDstY= dstY;

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

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

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

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

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

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

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

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

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

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

        int enough_lines;

        //handle holes (FAST_BILINEAR & weird filters)

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

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

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

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

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

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

        if (!enough_lines) {

            lastLumSrcY = srcSliceY + srcSliceH - 1;

            lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;

        }

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

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

                         firstLumSrcY,    lastLumSrcY,    lastInLumBuf);

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

                         firstChrSrcY,    lastChrSrcY,    lastInChrBuf);

        //Do horizontal scaling

        while(lastInLumBuf < lastLumSrcY) {

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

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

            lumBufIndex++;

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

                               lumBufIndex,    lastInLumBuf);

            assert(lumBufIndex < 2*vLumBufSize);

            assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);

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

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

                            flags, hLumFilter, hLumFilterPos, hLumFilterSize,

                            c->srcFormat, formatConvBuffer,

                            pal, 0);

            if (CONFIG_SWSCALE_ALPHA && alpPixBuf)

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

                                flags, hLumFilter, hLumFilterPos, hLumFilterSize,

                                c->srcFormat, formatConvBuffer,

                                pal, 1);

            lastInLumBuf++;

        }

        while(lastInChrBuf < lastChrSrcY) {

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

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

            chrBufIndex++;

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

                               chrBufIndex,    lastInChrBuf);

            assert(chrBufIndex < 2*vChrBufSize);

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

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

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

            if (!(isGray(srcFormat) || isGray(dstFormat)))

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

                                flags, hChrFilter, hChrFilterPos, hChrFilterSize,

                                c->srcFormat, formatConvBuffer,

                                pal);

            lastInChrBuf++;

        }

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

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

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

        if (!enough_lines)

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

#if COMPILE_TEMPLATE_MMX

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

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

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

        else

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

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

#endif

        if (dstY < dstH-2) {

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

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

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

#if COMPILE_TEMPLATE_MMX

            int i;

            if (flags & SWS_ACCURATE_RND) {

                int s= APCK_SIZE / 8;

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

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

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

                              lumMmxFilter[s*i+APCK_COEF/4  ]=

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

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

                    if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {

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

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

                                  alpMmxFilter[s*i+APCK_COEF/4  ]=

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

                    }

                }

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

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

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

                              chrMmxFilter[s*i+APCK_COEF/4  ]=

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

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

                }

            } else {

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

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

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

                    lumMmxFilter[4*i+2]=

                    lumMmxFilter[4*i+3]=

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

                    if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {

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

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

                        alpMmxFilter[4*i+2]=

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

                    }

                }

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

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

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

                    chrMmxFilter[4*i+2]=

                    chrMmxFilter[4*i+3]=

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

                }

            }

#endif

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

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

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

                c->yuv2nv12X(c,

                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                             vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                             dest, uDest, dstW, chrDstW, dstFormat);

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

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

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

                if (is16BPS(dstFormat)) {

                    yuv2yuvX16inC(

                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                  vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

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

                                  dstFormat);

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

                    int16_t *lumBuf = lumSrcPtr[0];

                    int16_t *chrBuf= chrSrcPtr[0];

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

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

                } else { //General YV12

                    c->yuv2yuvX(c,

                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

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

                }

            } else {

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

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

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

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

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c, //FIXME write a packed1_full function

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

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

                                       alpPixBuf ? *alpSrcPtr : NULL,

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

                    }

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

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

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

                    lumMmxFilter[2]=

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

                    chrMmxFilter[2]=

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

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c, //FIXME write a packed2_full function

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

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

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

                                       dest, dstW, lumAlpha, chrAlpha, dstY);

                    }

                } else { //general RGB

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c,

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packedX(c,

                                       vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                       vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                       alpSrcPtr, dest, dstW, dstY);

                    }

                }

            }

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

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

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

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

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

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

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

                yuv2nv12XinC(

                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                             vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                             dest, uDest, dstW, chrDstW, dstFormat);

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

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

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

                if (is16BPS(dstFormat)) {

                    yuv2yuvX16inC(

                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                  vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

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

                                  dstFormat);

                } else {

                    yuv2yuvXinC(

                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

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

                }

            } else {

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

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

                if(flags & SWS_FULL_CHR_H_INT) {

                    yuv2rgbXinC_full(c,

                                     vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                     vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                     alpSrcPtr, dest, dstW, dstY);

                } else {

                    yuv2packedXinC(c,

                                   vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                   vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                   alpSrcPtr, dest, dstW, dstY);

                }

            }

        }

    }

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

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

#if COMPILE_TEMPLATE_MMX

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

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

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

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

#endif

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

    c->dstY= dstY;

    c->lumBufIndex= lumBufIndex;

    c->chrBufIndex= chrBufIndex;

    c->lastInLumBuf= lastInLumBuf;

    c->lastInChrBuf= lastInChrBuf;

    return dstY - lastDstY;

}


static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr)

{

    PCIBonitoState *s = opaque;

    uint32_t pciaddr;

    uint16_t status;

    DPRINTF("bonito_spciconf_readb "TARGET_FMT_plx"  \n", addr);

    pciaddr = bonito_sbridge_pciaddr(s, addr);

    if (pciaddr == 0xffffffff) {

        return 0xff;

    }

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

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

    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */

    status = pci_get_word(s->dev.config + PCI_STATUS);

    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);

    pci_set_word(s->dev.config + PCI_STATUS, status);

    return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 1);

}


static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,

                                     const char *name, Error **errp)

{

    Property *prop = opaque;

    if (prop->info->print) {

        char buffer[1024];

        char *ptr = buffer;

        prop->info->print(dev, prop, buffer, sizeof(buffer));

        visit_type_str(v, &ptr, name, errp);

    } else {

        error_set(errp, QERR_PERMISSION_DENIED);

    }

}