static inline void RENAME(hyscale_fast)(SwsContext *c, int16_t *dst,

                                        long dstWidth, const uint8_t *src, int srcW,

                                        int xInc)

{

    int32_t *filterPos = c->hLumFilterPos;

    int16_t *filter    = c->hLumFilter;

    int     canMMX2BeUsed  = c->canMMX2BeUsed;

    void    *mmx2FilterCode= c->lumMmx2FilterCode;

    int i;

#if defined(PIC)

    DECLARE_ALIGNED(8, uint64_t, ebxsave);

#endif

    __asm__ volatile(

#if defined(PIC)

        "mov               %%"REG_b", %5        \n\t"

#endif

        "pxor                  %%mm7, %%mm7     \n\t"

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

        "mov                      %1, %%"REG_D" \n\t"

        "mov                      %2, %%"REG_d" \n\t"

        "mov                      %3, %%"REG_b" \n\t"

        "xor               %%"REG_a", %%"REG_a" \n\t" // i

        PREFETCH"        (%%"REG_c")            \n\t"

        PREFETCH"      32(%%"REG_c")            \n\t"

        PREFETCH"      64(%%"REG_c")            \n\t"

#if ARCH_X86_64

#define CALL_MMX2_FILTER_CODE \

        "movl            (%%"REG_b"), %%esi     \n\t"\

        "call                    *%4            \n\t"\

        "movl (%%"REG_b", %%"REG_a"), %%esi     \n\t"\

        "add               %%"REG_S", %%"REG_c" \n\t"\

        "add               %%"REG_a", %%"REG_D" \n\t"\

        "xor               %%"REG_a", %%"REG_a" \n\t"\

#else

#define CALL_MMX2_FILTER_CODE \

        "movl (%%"REG_b"), %%esi        \n\t"\

        "call         *%4                       \n\t"\

        "addl (%%"REG_b", %%"REG_a"), %%"REG_c" \n\t"\

        "add               %%"REG_a", %%"REG_D" \n\t"\

        "xor               %%"REG_a", %%"REG_a" \n\t"\

#endif /* ARCH_X86_64 */

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

        CALL_MMX2_FILTER_CODE

#if defined(PIC)

        "mov                      %5, %%"REG_b" \n\t"

#endif

        :: "m" (src), "m" (dst), "m" (filter), "m" (filterPos),

           "m" (mmx2FilterCode)

#if defined(PIC)

          ,"m" (ebxsave)

#endif

        : "%"REG_a, "%"REG_c, "%"REG_d, "%"REG_S, "%"REG_D

#if !defined(PIC)

         ,"%"REG_b

#endif

    );

    for (i=dstWidth-1; (i*xInc)>>16 >=srcW-1; i--)

        dst[i] = src[srcW-1]*128;

}


static uint64_t imx_serial_read(void *opaque, hwaddr offset,

                                unsigned size)

{

    IMXSerialState *s = (IMXSerialState *)opaque;

    uint32_t c;

    DPRINTF("read(offset=%x)\n", offset >> 2);

    switch (offset >> 2) {

    case 0x0: /* URXD */

        c = s->readbuff;

        if (!(s->uts1 & UTS1_RXEMPTY)) {

            /* Character is valid */

            c |= URXD_CHARRDY;

            s->usr1 &= ~USR1_RRDY;

            s->usr2 &= ~USR2_RDR;

            s->uts1 |= UTS1_RXEMPTY;

            imx_update(s);

            qemu_chr_accept_input(s->chr);

        }

        return c;

    case 0x20: /* UCR1 */

        return s->ucr1;

    case 0x21: /* UCR2 */

        return s->ucr2;

    case 0x25: /* USR1 */

        return s->usr1;

    case 0x26: /* USR2 */

        return s->usr2;

    case 0x2A: /* BRM Modulator */

        return s->ubmr;

    case 0x2B: /* Baud Rate Count */

        return s->ubrc;

    case 0x2d: /* Test register */

        return s->uts1;

    case 0x24: /* UFCR */

        return s->ufcr;

    case 0x2c:

        return s->onems;

    case 0x22: /* UCR3 */

        return s->ucr3;

    case 0x23: /* UCR4 */

    case 0x29: /* BRM Incremental */

        return 0x0; /* TODO */

    default:

        IPRINTF("%s: bad offset: 0x%x\n", __func__, (int)offset);

        return 0;

    }

}


static int display_end_segment(AVCodecContext *avctx, void *data,

                               const uint8_t *buf, int buf_size)

{

    AVSubtitle    *sub = data;

    PGSSubContext *ctx = avctx->priv_data;

    /*

     *      The end display time is a timeout value and is only reached

     *      if the next subtitle is later then timeout or subtitle has

     *      not been cleared by a subsequent empty display command.

     */

    memset(sub, 0, sizeof(*sub));

    // Blank if last object_number was 0.

    // Note that this may be wrong for more complex subtitles.

    if (!ctx->presentation.object_number)

        return 1;

    sub->start_display_time = 0;

    sub->end_display_time   = 20000;

    sub->format             = 0;

    sub->rects     = av_mallocz(sizeof(*sub->rects));

    sub->rects[0]  = av_mallocz(sizeof(*sub->rects[0]));

    sub->num_rects = 1;

    sub->rects[0]->x    = ctx->presentation.x;

    sub->rects[0]->y    = ctx->presentation.y;

    sub->rects[0]->w    = ctx->picture.w;

    sub->rects[0]->h    = ctx->picture.h;

    sub->rects[0]->type = SUBTITLE_BITMAP;

    /* Process bitmap */

    sub->rects[0]->pict.linesize[0] = ctx->picture.w;

    if (ctx->picture.rle) {

        if (ctx->picture.rle_remaining_len)

            av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n",

                   ctx->picture.rle_data_len, ctx->picture.rle_remaining_len);

        if(decode_rle(avctx, sub, ctx->picture.rle, ctx->picture.rle_data_len) < 0)

            return 0;

    }

    /* Allocate memory for colors */

    sub->rects[0]->nb_colors    = 256;

    sub->rects[0]->pict.data[1] = av_mallocz(AVPALETTE_SIZE);

    memcpy(sub->rects[0]->pict.data[1], ctx->clut, sub->rects[0]->nb_colors * sizeof(uint32_t));

    return 1;

}


static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,

                              MOVTrack *track, AVStream *st)

{

    int64_t duration = av_rescale_rnd(track->track_duration, MOV_TIMESCALE,

                                      track->timescale, AV_ROUND_UP);

    int version = duration < INT32_MAX ? 0 : 1;

    int flags   = MOV_TKHD_FLAG_IN_MOVIE;

    int rotation = 0;

    int group   = 0;

    uint32_t *display_matrix = NULL;

    int      display_matrix_size, i;

    if (st) {

        if (mov->per_stream_grouping)

            group = st->index;

        else

            group = st->codec->codec_type;

        display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX,

                                                            &display_matrix_size);

        if (display_matrix && display_matrix_size < 9 * sizeof(*display_matrix))

            display_matrix = NULL;

    }

    if (track->flags & MOV_TRACK_ENABLED)

        flags |= MOV_TKHD_FLAG_ENABLED;

    if (track->mode == MODE_ISM)

        version = 1;

    (version == 1) ? avio_wb32(pb, 104) : avio_wb32(pb, 92); /* size */

    ffio_wfourcc(pb, "tkhd");

    avio_w8(pb, version);

    avio_wb24(pb, flags);

    if (version == 1) {

        avio_wb64(pb, track->time);

        avio_wb64(pb, track->time);

    } else {

        avio_wb32(pb, track->time); /* creation time */

        avio_wb32(pb, track->time); /* modification time */

    }

    avio_wb32(pb, track->track_id); /* track-id */

    avio_wb32(pb, 0); /* reserved */

    if (!track->entry && mov->mode == MODE_ISM)

        (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);

    else if (!track->entry)

        (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);

    else

        (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);

    avio_wb32(pb, 0); /* reserved */

    avio_wb32(pb, 0); /* reserved */

    avio_wb16(pb, 0); /* layer */

    avio_wb16(pb, group); /* alternate group) */

    /* Volume, only for audio */

    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)

        avio_wb16(pb, 0x0100);

    else

        avio_wb16(pb, 0);

    avio_wb16(pb, 0); /* reserved */

    /* Matrix structure */

    if (st && st->metadata) {

        AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0);

        rotation = (rot && rot->value) ? atoi(rot->value) : 0;

    }

    if (display_matrix) {

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

            avio_wb32(pb, display_matrix[i]);

    } else if (rotation == 90) {

        write_matrix(pb,  0,  1, -1,  0, track->enc->height, 0);

    } else if (rotation == 180) {

        write_matrix(pb, -1,  0,  0, -1, track->enc->width, track->enc->height);

    } else if (rotation == 270) {

        write_matrix(pb,  0, -1,  1,  0, 0, track->enc->width);

    } else {

        write_matrix(pb,  1,  0,  0,  1, 0, 0);

    }

    /* Track width and height, for visual only */

    if (st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||

               track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {

        if (track->mode == MODE_MOV) {

            avio_wb32(pb, track->enc->width << 16);

            avio_wb32(pb, track->height << 16);

        } else {

            int64_t track_width_1616 = av_rescale(st->sample_aspect_ratio.num,

                                                  track->enc->width * 0x10000LL,

                                                  st->sample_aspect_ratio.den);

            if (!track_width_1616 || track->height != track->enc->height)

                track_width_1616 = track->enc->width * 0x10000;

            avio_wb32(pb, track_width_1616);

            avio_wb32(pb, track->height * 0x10000);

        }

    } else {

        avio_wb32(pb, 0);

        avio_wb32(pb, 0);

    }

    return 0x5c;

}


static int decode_type1(GetByteContext *gb, PutByteContext *pb)

{

    unsigned opcode, len;

    int high = 0;

    int i, pos;

    while (bytestream2_get_bytes_left(gb) > 0) {

        GetByteContext gbc;

        while (bytestream2_get_bytes_left(gb) > 0) {

            while (bytestream2_get_bytes_left(gb) > 0) {

                opcode = bytestream2_get_byte(gb);

                high = opcode >= 0x20;

                if (high)

                    break;

                if (opcode)

                    break;

                opcode = bytestream2_get_byte(gb);

                if (opcode < 0xF8) {

                    opcode = opcode + 32;

                    break;

                }

                i = opcode - 0xF8;

                if (i) {

                    len = 256;

                    do {

                        len *= 2;

                        --i;

                    } while (i);

                } else {

                    len = 280;

                }

                do {

                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));

                    bytestream2_put_le32(pb, bytestream2_get_le32(gb));

                    len -= 8;

                } while (len && bytestream2_get_bytes_left(gb) > 0);

            }

            if (!high) {

                do {

                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));

                    --opcode;

                } while (opcode && bytestream2_get_bytes_left(gb) > 0);

                while (bytestream2_get_bytes_left(gb) > 0) {

                    GetByteContext gbc;

                    opcode = bytestream2_get_byte(gb);

                    if (opcode >= 0x20)

                        break;

                    bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);

                    pos = -(opcode | 32 * bytestream2_get_byte(gb)) - 1;

                    bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);

                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

                    bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

                    bytestream2_put_byte(pb, bytestream2_get_byte(gb));

                }

            }

            high = 0;

            if (opcode < 0x40)

                break;

            bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);

            pos = (-((opcode & 0x1F) | 32 * bytestream2_get_byte(gb)) - 1);

            bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos, SEEK_SET);

            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

            len = (opcode >> 5) - 1;

            do {

                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

                --len;

            } while (len && bytestream2_get_bytes_left(&gbc) > 0);

        }

        len = opcode & 0x1F;

        if (!len) {

            if (!bytestream2_peek_byte(gb)) {

                do {

                    bytestream2_skip(gb, 1);

                    len += 255;

                } while (!bytestream2_peek_byte(gb) && bytestream2_get_bytes_left(gb) > 0);

            }

            len += bytestream2_get_byte(gb) + 31;

        }

        pos = -bytestream2_get_byte(gb);

        bytestream2_init(&gbc, pb->buffer_start, pb->buffer_end - pb->buffer_start);

        bytestream2_seek(&gbc, bytestream2_tell_p(pb) + pos - (bytestream2_get_byte(gb) << 8), SEEK_SET);

        if (bytestream2_tell_p(pb) == bytestream2_tell(&gbc))

            break;

        if (len < 5 || bytestream2_tell_p(pb) - bytestream2_tell(&gbc) < 4) {

            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

            bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

            do {

                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

                --len;

            } while (len && bytestream2_get_bytes_left(&gbc) > 0);

        } else {

            bytestream2_put_le32(pb, bytestream2_get_le32(&gbc));

            len--;

            do {

                bytestream2_put_byte(pb, bytestream2_get_byte(&gbc));

                len--;

            } while (len && bytestream2_get_bytes_left(&gbc) > 0);

        }

    }

    return 0;

}


void ff_avg_h264_qpel8_mc33_msa(uint8_t *dst, const uint8_t *src,

                                ptrdiff_t stride)

{

    avc_luma_hv_qrt_and_aver_dst_8x8_msa(src + stride - 2,

                                         src - (stride * 2) +

                                         sizeof(uint8_t), stride, dst, stride);

}


static int check_recording_time(OutputStream *ost)

{

    OutputFile *of = output_files[ost->file_index];

    if (of->recording_time != INT64_MAX &&

        av_compare_ts(ost->sync_opts - ost->first_pts, ost->st->codec->time_base, of->recording_time,

                      AV_TIME_BASE_Q) >= 0) {

        ost->is_past_recording_time = 1;

        return 0;

    }

    return 1;

}


static void chs_filter_band_data(DCAXllDecoder *s, DCAXllChSet *c, int band)

{

    DCAXllBand *b = &c->bands[band];

    int nsamples = s->nframesamples;

    int i, j, k;

    // Inverse adaptive or fixed prediction

    for (i = 0; i < c->nchannels; i++) {

        int32_t *buf = b->msb_sample_buffer[i];

        int order = b->adapt_pred_order[i];

        if (order > 0) {

            int coeff[DCA_XLL_ADAPT_PRED_ORDER_MAX];

            // Conversion from reflection coefficients to direct form coefficients

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

                int rc = b->adapt_refl_coeff[i][j];

                for (k = 0; k < (j + 1) / 2; k++) {

                    int tmp1 = coeff[    k    ];

                    int tmp2 = coeff[j - k - 1];

                    coeff[    k    ] = tmp1 + mul16(rc, tmp2);

                    coeff[j - k - 1] = tmp2 + mul16(rc, tmp1);

                }

                coeff[j] = rc;

            }

            // Inverse adaptive prediction

            for (j = 0; j < nsamples - order; j++) {

                int64_t err = 0;

                for (k = 0; k < order; k++)

                    err += (int64_t)buf[j + k] * coeff[order - k - 1];

                buf[j + k] -= (SUINT)clip23(norm16(err));

            }

        } else {

            // Inverse fixed coefficient prediction

            for (j = 0; j < b->fixed_pred_order[i]; j++)

                for (k = 1; k < nsamples; k++)

                    buf[k] += buf[k - 1];

        }

    }

    // Inverse pairwise channel decorrellation

    if (b->decor_enabled) {

        int32_t *tmp[DCA_XLL_CHANNELS_MAX];

        for (i = 0; i < c->nchannels / 2; i++) {

            int coeff = b->decor_coeff[i];

            if (coeff) {

                s->dcadsp->decor(b->msb_sample_buffer[i * 2 + 1],

                                 b->msb_sample_buffer[i * 2    ],

                                 coeff, nsamples);

            }

        }

        // Reorder channel pointers to the original order

        for (i = 0; i < c->nchannels; i++)

            tmp[i] = b->msb_sample_buffer[i];

        for (i = 0; i < c->nchannels; i++)

            b->msb_sample_buffer[b->orig_order[i]] = tmp[i];

    }

    // Map output channel pointers for frequency band 0

    if (c->nfreqbands == 1)

        for (i = 0; i < c->nchannels; i++)

            s->output_samples[c->ch_remap[i]] = b->msb_sample_buffer[i];

}


void ff_ivi_recompose53(const IVIPlaneDesc *plane, uint8_t *dst,
                        const int dst_pitch, const int num_bands)
{
    int             x, y, indx;
    int32_t         p0, p1, p2, p3, tmp0, tmp1, tmp2;
    int32_t         b0_1, b0_2, b1_1, b1_2, b1_3, b2_1, b2_2, b2_3, b2_4, b2_5, b2_6;
    int32_t         b3_1, b3_2, b3_3, b3_4, b3_5, b3_6, b3_7, b3_8, b3_9;
    int32_t         pitch, back_pitch;
    const IDWTELEM *b0_ptr, *b1_ptr, *b2_ptr, *b3_ptr;
    /* all bands should have the same pitch */
    pitch = plane->bands[0].pitch;
    /* pixels at the position "y-1" will be set to pixels at the "y" for the 1st iteration */
    back_pitch = 0;
    /* get pointers to the wavelet bands */
    b0_ptr = plane->bands[0].buf;
    b1_ptr = plane->bands[1].buf;
    b2_ptr = plane->bands[2].buf;
    b3_ptr = plane->bands[3].buf;
    for (y = 0; y < plane->height; y += 2) {
        /* load storage variables with values */
        if (num_bands > 0) {
            b0_1 = b0_ptr[0];
            b0_2 = b0_ptr[pitch];
        }
        if (num_bands > 1) {
            b1_1 = b1_ptr[back_pitch];
            b1_2 = b1_ptr[0];
            b1_3 = b1_1 - b1_2*6 + b1_ptr[pitch];
        }
        if (num_bands > 2) {
            b2_2 = b2_ptr[0];     // b2[x,  y  ]
            b2_3 = b2_2;          // b2[x+1,y  ] = b2[x,y]
            b2_5 = b2_ptr[pitch]; // b2[x  ,y+1]
            b2_6 = b2_5;          // b2[x+1,y+1] = b2[x,y+1]
        }
        if (num_bands > 3) {
            b3_2 = b3_ptr[back_pitch]; // b3[x  ,y-1]
            b3_3 = b3_2;               // b3[x+1,y-1] = b3[x  ,y-1]
            b3_5 = b3_ptr[0];          // b3[x  ,y  ]
            b3_6 = b3_5;               // b3[x+1,y  ] = b3[x  ,y  ]
            b3_8 = b3_2 - b3_5*6 + b3_ptr[pitch];
            b3_9 = b3_8;
        }
        for (x = 0, indx = 0; x < plane->width; x+=2, indx++) {
            /* some values calculated in the previous iterations can */
            /* be reused in the next ones, so do appropriate copying */
            b2_1 = b2_2; // b2[x-1,y  ] = b2[x,  y  ]
            b2_2 = b2_3; // b2[x  ,y  ] = b2[x+1,y  ]
            b2_4 = b2_5; // b2[x-1,y+1] = b2[x  ,y+1]
            b2_5 = b2_6; // b2[x  ,y+1] = b2[x+1,y+1]
            b3_1 = b3_2; // b3[x-1,y-1] = b3[x  ,y-1]
            b3_2 = b3_3; // b3[x  ,y-1] = b3[x+1,y-1]
            b3_4 = b3_5; // b3[x-1,y  ] = b3[x  ,y  ]
            b3_5 = b3_6; // b3[x  ,y  ] = b3[x+1,y  ]
            b3_7 = b3_8; // vert_HPF(x-1)
            b3_8 = b3_9; // vert_HPF(x  )
            p0 = p1 = p2 = p3 = 0;
            /* process the LL-band by applying LPF both vertically and horizontally */
            if (num_bands > 0) {
                tmp0 = b0_1;
                tmp2 = b0_2;
                b0_1 = b0_ptr[indx+1];
                b0_2 = b0_ptr[pitch+indx+1];
                tmp1 = tmp0 + b0_1;
                p0 =  tmp0 << 4;
                p1 =  tmp1 << 3;
                p2 = (tmp0 + tmp2) << 3;
                p3 = (tmp1 + tmp2 + b0_2) << 2;
            }
            /* process the HL-band by applying HPF vertically and LPF horizontally */
            if (num_bands > 1) {
                tmp0 = b1_2;
                tmp1 = b1_1;
                b1_2 = b1_ptr[indx+1];
                b1_1 = b1_ptr[back_pitch+indx+1];
                tmp2 = tmp1 - tmp0*6 + b1_3;
                b1_3 = b1_1 - b1_2*6 + b1_ptr[pitch+indx+1];
                p0 += (tmp0 + tmp1) << 3;
                p1 += (tmp0 + tmp1 + b1_1 + b1_2) << 2;
                p2 +=  tmp2 << 2;
                p3 += (tmp2 + b1_3) << 1;
            }
            /* process the LH-band by applying LPF vertically and HPF horizontally */
            if (num_bands > 2) {
                b2_3 = b2_ptr[indx+1];
                b2_6 = b2_ptr[pitch+indx+1];
                tmp0 = b2_1 + b2_2;
                tmp1 = b2_1 - b2_2*6 + b2_3;
                p0 += tmp0 << 3;
                p1 += tmp1 << 2;
                p2 += (tmp0 + b2_4 + b2_5) << 2;
                p3 += (tmp1 + b2_4 - b2_5*6 + b2_6) << 1;
            }
            /* process the HH-band by applying HPF both vertically and horizontally */
            if (num_bands > 3) {
                b3_6 = b3_ptr[indx+1];            // b3[x+1,y  ]
                b3_3 = b3_ptr[back_pitch+indx+1]; // b3[x+1,y-1]
                tmp0 = b3_1 + b3_4;
                tmp1 = b3_2 + b3_5;
                tmp2 = b3_3 + b3_6;
                b3_9 = b3_3 - b3_6*6 + b3_ptr[pitch+indx+1];
                p0 += (tmp0 + tmp1) << 2;
                p1 += (tmp0 - tmp1*6 + tmp2) << 1;
                p2 += (b3_7 + b3_8) << 1;
                p3 +=  b3_7 - b3_8*6 + b3_9;
            }
            /* output four pixels */
            dst[x]             = av_clip_uint8((p0 >> 6) + 128);
            dst[x+1]           = av_clip_uint8((p1 >> 6) + 128);
            dst[dst_pitch+x]   = av_clip_uint8((p2 >> 6) + 128);
            dst[dst_pitch+x+1] = av_clip_uint8((p3 >> 6) + 128);
        }// for x
        dst += dst_pitch << 1;
        back_pitch = -pitch;
        b0_ptr += pitch;
        b1_ptr += pitch;
        b2_ptr += pitch;
        b3_ptr += pitch;
    }
}


static void megasas_mmio_write(void *opaque, hwaddr addr,

                               uint64_t val, unsigned size)

{

    MegasasState *s = opaque;

    PCIDevice *pci_dev = PCI_DEVICE(s);

    uint64_t frame_addr;

    uint32_t frame_count;

    int i;

    switch (addr) {

    case MFI_IDB:

        trace_megasas_mmio_writel("MFI_IDB", val);

        if (val & MFI_FWINIT_ABORT) {

            /* Abort all pending cmds */

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

                megasas_abort_command(&s->frames[i]);

            }

        }

        if (val & MFI_FWINIT_READY) {

            /* move to FW READY */

            megasas_soft_reset(s);

        }

        if (val & MFI_FWINIT_MFIMODE) {

            /* discard MFIs */

        }

        if (val & MFI_FWINIT_STOP_ADP) {

            /* Terminal error, stop processing */

            s->fw_state = MFI_FWSTATE_FAULT;

        }

        break;

    case MFI_OMSK:

        trace_megasas_mmio_writel("MFI_OMSK", val);

        s->intr_mask = val;

        if (!megasas_intr_enabled(s) &&

            !msi_enabled(pci_dev) &&

            !msix_enabled(pci_dev)) {

            trace_megasas_irq_lower();

            pci_irq_deassert(pci_dev);

        }

        if (megasas_intr_enabled(s)) {

            if (msix_enabled(pci_dev)) {

                trace_megasas_msix_enabled(0);

            } else if (msi_enabled(pci_dev)) {

                trace_megasas_msi_enabled(0);

            } else {

                trace_megasas_intr_enabled();

            }

        } else {

            trace_megasas_intr_disabled();

            megasas_soft_reset(s);

        }

        break;

    case MFI_ODCR0:

        trace_megasas_mmio_writel("MFI_ODCR0", val);

        s->doorbell = 0;

        if (megasas_intr_enabled(s)) {

            if (!msix_enabled(pci_dev) && !msi_enabled(pci_dev)) {

                trace_megasas_irq_lower();

                pci_irq_deassert(pci_dev);

            }

        }

        break;

    case MFI_IQPH:

        trace_megasas_mmio_writel("MFI_IQPH", val);

        /* Received high 32 bits of a 64 bit MFI frame address */

        s->frame_hi = val;

        break;

    case MFI_IQPL:

        trace_megasas_mmio_writel("MFI_IQPL", val);

        /* Received low 32 bits of a 64 bit MFI frame address */

        /* Fallthrough */

    case MFI_IQP:

        if (addr == MFI_IQP) {

            trace_megasas_mmio_writel("MFI_IQP", val);

            /* Received 64 bit MFI frame address */

            s->frame_hi = 0;

        }

        frame_addr = (val & ~0x1F);

        /* Add possible 64 bit offset */

        frame_addr |= ((uint64_t)s->frame_hi << 32);

        s->frame_hi = 0;

        frame_count = (val >> 1) & 0xF;

        megasas_handle_frame(s, frame_addr, frame_count);

        break;

    case MFI_SEQ:

        trace_megasas_mmio_writel("MFI_SEQ", val);

        /* Magic sequence to start ADP reset */

        if (adp_reset_seq[s->adp_reset] == val) {

            s->adp_reset++;

        } else {

            s->adp_reset = 0;

            s->diag = 0;

        }

        if (s->adp_reset == 6) {

            s->diag = MFI_DIAG_WRITE_ENABLE;

        }

        break;

    case MFI_DIAG:

        trace_megasas_mmio_writel("MFI_DIAG", val);

        /* ADP reset */

        if ((s->diag & MFI_DIAG_WRITE_ENABLE) &&

            (val & MFI_DIAG_RESET_ADP)) {

            s->diag |= MFI_DIAG_RESET_ADP;

            megasas_soft_reset(s);

            s->adp_reset = 0;

            s->diag = 0;

        }

        break;

    default:

        trace_megasas_mmio_invalid_writel(addr, val);

        break;

    }

}


static void decode_mode(AVCodecContext *ctx)

{

    static const uint8_t left_ctx[N_BS_SIZES] = {

        0x0, 0x8, 0x0, 0x8, 0xc, 0x8, 0xc, 0xe, 0xc, 0xe, 0xf, 0xe, 0xf

    };

    static const uint8_t above_ctx[N_BS_SIZES] = {

        0x0, 0x0, 0x8, 0x8, 0x8, 0xc, 0xc, 0xc, 0xe, 0xe, 0xe, 0xf, 0xf

    };

    static const uint8_t max_tx_for_bl_bp[N_BS_SIZES] = {

        TX_32X32, TX_32X32, TX_32X32, TX_32X32, TX_16X16, TX_16X16,

        TX_16X16, TX_8X8, TX_8X8, TX_8X8, TX_4X4, TX_4X4, TX_4X4

    };

    VP9Context *s = ctx->priv_data;

    VP9Block *b = s->b;

    int row = s->row, col = s->col, row7 = s->row7;

    enum TxfmMode max_tx = max_tx_for_bl_bp[b->bs];

    int w4 = FFMIN(s->cols - col, bwh_tab[1][b->bs][0]);

    int h4 = FFMIN(s->rows - row, bwh_tab[1][b->bs][1]), y;

    int have_a = row > 0, have_l = col > s->tiling.tile_col_start;

    if (!s->segmentation.enabled) {

        b->seg_id = 0;

    } else if (s->keyframe || s->intraonly) {

        b->seg_id = s->segmentation.update_map ?

            vp8_rac_get_tree(&s->c, vp9_segmentation_tree, s->prob.seg) : 0;

    } else if (!s->segmentation.update_map ||

               (s->segmentation.temporal &&

                vp56_rac_get_prob_branchy(&s->c,

                    s->prob.segpred[s->above_segpred_ctx[col] +

                                    s->left_segpred_ctx[row7]]))) {

        int pred = 8, x;

        uint8_t *refsegmap = s->frames[LAST_FRAME].segmentation_map;

        if (!s->last_uses_2pass)

            ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0);

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

            for (x = 0; x < w4; x++)

                pred = FFMIN(pred, refsegmap[(y + row) * 8 * s->sb_cols + x + col]);

        av_assert1(pred < 8);

        b->seg_id = pred;

        memset(&s->above_segpred_ctx[col], 1, w4);

        memset(&s->left_segpred_ctx[row7], 1, h4);

    } else {

        b->seg_id = vp8_rac_get_tree(&s->c, vp9_segmentation_tree,

                                     s->prob.seg);

        memset(&s->above_segpred_ctx[col], 0, w4);

        memset(&s->left_segpred_ctx[row7], 0, h4);

    }

    if ((s->segmentation.enabled && s->segmentation.update_map) || s->keyframe) {

        uint8_t *segmap = s->frames[CUR_FRAME].segmentation_map;

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

            memset(&segmap[(y + row) * 8 * s->sb_cols + col], b->seg_id, w4);

    }

    b->skip = s->segmentation.enabled &&

        s->segmentation.feat[b->seg_id].skip_enabled;

    if (!b->skip) {

        int c = s->left_skip_ctx[row7] + s->above_skip_ctx[col];

        b->skip = vp56_rac_get_prob(&s->c, s->prob.p.skip[c]);

        s->counts.skip[c][b->skip]++;

    }

    if (s->keyframe || s->intraonly) {

        b->intra = 1;

    } else if (s->segmentation.feat[b->seg_id].ref_enabled) {

        b->intra = !s->segmentation.feat[b->seg_id].ref_val;

    } else {

        int c, bit;

        if (have_a && have_l) {

            c = s->above_intra_ctx[col] + s->left_intra_ctx[row7];

            c += (c == 2);

        } else {

            c = have_a ? 2 * s->above_intra_ctx[col] :

                have_l ? 2 * s->left_intra_ctx[row7] : 0;

        }

        bit = vp56_rac_get_prob(&s->c, s->prob.p.intra[c]);

        s->counts.intra[c][bit]++;

        b->intra = !bit;

    }

    if ((b->intra || !b->skip) && s->txfmmode == TX_SWITCHABLE) {

        int c;

        if (have_a) {

            if (have_l) {

                c = (s->above_skip_ctx[col] ? max_tx :

                     s->above_txfm_ctx[col]) +

                    (s->left_skip_ctx[row7] ? max_tx :

                     s->left_txfm_ctx[row7]) > max_tx;

            } else {

                c = s->above_skip_ctx[col] ? 1 :

                    (s->above_txfm_ctx[col] * 2 > max_tx);

            }

        } else if (have_l) {

            c = s->left_skip_ctx[row7] ? 1 :

                (s->left_txfm_ctx[row7] * 2 > max_tx);

        } else {

            c = 1;

        }

        switch (max_tx) {

        case TX_32X32:

            b->tx = vp56_rac_get_prob(&s->c, s->prob.p.tx32p[c][0]);

            if (b->tx) {

                b->tx += vp56_rac_get_prob(&s->c, s->prob.p.tx32p[c][1]);

                if (b->tx == 2)

                    b->tx += vp56_rac_get_prob(&s->c, s->prob.p.tx32p[c][2]);

            }

            s->counts.tx32p[c][b->tx]++;

            break;

        case TX_16X16:

            b->tx = vp56_rac_get_prob(&s->c, s->prob.p.tx16p[c][0]);

            if (b->tx)

                b->tx += vp56_rac_get_prob(&s->c, s->prob.p.tx16p[c][1]);

            s->counts.tx16p[c][b->tx]++;

            break;

        case TX_8X8:

            b->tx = vp56_rac_get_prob(&s->c, s->prob.p.tx8p[c]);

            s->counts.tx8p[c][b->tx]++;

            break;

        case TX_4X4:

            b->tx = TX_4X4;

            break;

        }

    } else {

        b->tx = FFMIN(max_tx, s->txfmmode);

    }

    if (s->keyframe || s->intraonly) {

        uint8_t *a = &s->above_mode_ctx[col * 2];

        uint8_t *l = &s->left_mode_ctx[(row7) << 1];

        b->comp = 0;

        if (b->bs > BS_8x8) {

            // FIXME the memory storage intermediates here aren't really

            // necessary, they're just there to make the code slightly

            // simpler for now

            b->mode[0] = a[0] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                    vp9_default_kf_ymode_probs[a[0]][l[0]]);

            if (b->bs != BS_8x4) {

                b->mode[1] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                 vp9_default_kf_ymode_probs[a[1]][b->mode[0]]);

                l[0] = a[1] = b->mode[1];

            } else {

                l[0] = a[1] = b->mode[1] = b->mode[0];

            }

            if (b->bs != BS_4x8) {

                b->mode[2] = a[0] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                        vp9_default_kf_ymode_probs[a[0]][l[1]]);

                if (b->bs != BS_8x4) {

                    b->mode[3] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                  vp9_default_kf_ymode_probs[a[1]][b->mode[2]]);

                    l[1] = a[1] = b->mode[3];

                } else {

                    l[1] = a[1] = b->mode[3] = b->mode[2];

                }

            } else {

                b->mode[2] = b->mode[0];

                l[1] = a[1] = b->mode[3] = b->mode[1];

            }

        } else {

            b->mode[0] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                          vp9_default_kf_ymode_probs[*a][*l]);

            b->mode[3] = b->mode[2] = b->mode[1] = b->mode[0];

            // FIXME this can probably be optimized

            memset(a, b->mode[0], bwh_tab[0][b->bs][0]);

            memset(l, b->mode[0], bwh_tab[0][b->bs][1]);

        }

        b->uvmode = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                     vp9_default_kf_uvmode_probs[b->mode[3]]);

    } else if (b->intra) {

        b->comp = 0;

        if (b->bs > BS_8x8) {

            b->mode[0] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                          s->prob.p.y_mode[0]);

            s->counts.y_mode[0][b->mode[0]]++;

            if (b->bs != BS_8x4) {

                b->mode[1] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                              s->prob.p.y_mode[0]);

                s->counts.y_mode[0][b->mode[1]]++;

            } else {

                b->mode[1] = b->mode[0];

            }

            if (b->bs != BS_4x8) {

                b->mode[2] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                              s->prob.p.y_mode[0]);

                s->counts.y_mode[0][b->mode[2]]++;

                if (b->bs != BS_8x4) {

                    b->mode[3] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                                  s->prob.p.y_mode[0]);

                    s->counts.y_mode[0][b->mode[3]]++;

                } else {

                    b->mode[3] = b->mode[2];

                }

            } else {

                b->mode[2] = b->mode[0];

                b->mode[3] = b->mode[1];

            }

        } else {

            static const uint8_t size_group[10] = {

                3, 3, 3, 3, 2, 2, 2, 1, 1, 1

            };

            int sz = size_group[b->bs];

            b->mode[0] = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                          s->prob.p.y_mode[sz]);

            b->mode[1] = b->mode[2] = b->mode[3] = b->mode[0];

            s->counts.y_mode[sz][b->mode[3]]++;

        }

        b->uvmode = vp8_rac_get_tree(&s->c, vp9_intramode_tree,

                                     s->prob.p.uv_mode[b->mode[3]]);

        s->counts.uv_mode[b->mode[3]][b->uvmode]++;

    } else {

        static const uint8_t inter_mode_ctx_lut[14][14] = {

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5 },

            { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 1, 3 },

            { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 1, 3 },

            { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 0, 3 },

            { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 4 },

        };

        if (s->segmentation.feat[b->seg_id].ref_enabled) {

            av_assert2(s->segmentation.feat[b->seg_id].ref_val != 0);

            b->comp = 0;

            b->ref[0] = s->segmentation.feat[b->seg_id].ref_val - 1;

        } else {

            // read comp_pred flag

            if (s->comppredmode != PRED_SWITCHABLE) {

                b->comp = s->comppredmode == PRED_COMPREF;

            } else {

                int c;

                // FIXME add intra as ref=0xff (or -1) to make these easier?

                if (have_a) {

                    if (have_l) {

                        if (s->above_comp_ctx[col] && s->left_comp_ctx[row7]) {

                            c = 4;

                        } else if (s->above_comp_ctx[col]) {

                            c = 2 + (s->left_intra_ctx[row7] ||

                                     s->left_ref_ctx[row7] == s->fixcompref);

                        } else if (s->left_comp_ctx[row7]) {

                            c = 2 + (s->above_intra_ctx[col] ||

                                     s->above_ref_ctx[col] == s->fixcompref);

                        } else {

                            c = (!s->above_intra_ctx[col] &&

                                 s->above_ref_ctx[col] == s->fixcompref) ^

                            (!s->left_intra_ctx[row7] &&

                             s->left_ref_ctx[row & 7] == s->fixcompref);

                        }

                    } else {

                        c = s->above_comp_ctx[col] ? 3 :

                        (!s->above_intra_ctx[col] && s->above_ref_ctx[col] == s->fixcompref);

                    }

                } else if (have_l) {

                    c = s->left_comp_ctx[row7] ? 3 :

                    (!s->left_intra_ctx[row7] && s->left_ref_ctx[row7] == s->fixcompref);

                } else {

                    c = 1;

                }

                b->comp = vp56_rac_get_prob(&s->c, s->prob.p.comp[c]);

                s->counts.comp[c][b->comp]++;

            }

            // read actual references

            // FIXME probably cache a few variables here to prevent repetitive

            // memory accesses below

            if (b->comp) /* two references */ {

                int fix_idx = s->signbias[s->fixcompref], var_idx = !fix_idx, c, bit;

                b->ref[fix_idx] = s->fixcompref;

                // FIXME can this codeblob be replaced by some sort of LUT?

                if (have_a) {

                    if (have_l) {

                        if (s->above_intra_ctx[col]) {

                            if (s->left_intra_ctx[row7]) {

                                c = 2;

                            } else {

                                c = 1 + 2 * (s->left_ref_ctx[row7] != s->varcompref[1]);

                            }

                        } else if (s->left_intra_ctx[row7]) {

                            c = 1 + 2 * (s->above_ref_ctx[col] != s->varcompref[1]);

                        } else {

                            int refl = s->left_ref_ctx[row7], refa = s->above_ref_ctx[col];

                            if (refl == refa && refa == s->varcompref[1]) {

                                c = 0;

                            } else if (!s->left_comp_ctx[row7] && !s->above_comp_ctx[col]) {

                                if ((refa == s->fixcompref && refl == s->varcompref[0]) ||

                                    (refl == s->fixcompref && refa == s->varcompref[0])) {

                                    c = 4;

                                } else {

                                    c = (refa == refl) ? 3 : 1;

                                }

                            } else if (!s->left_comp_ctx[row7]) {

                                if (refa == s->varcompref[1] && refl != s->varcompref[1]) {

                                    c = 1;

                                } else {

                                    c = (refl == s->varcompref[1] &&

                                         refa != s->varcompref[1]) ? 2 : 4;

                                }

                            } else if (!s->above_comp_ctx[col]) {

                                if (refl == s->varcompref[1] && refa != s->varcompref[1]) {

                                    c = 1;

                                } else {

                                    c = (refa == s->varcompref[1] &&

                                         refl != s->varcompref[1]) ? 2 : 4;

                                }

                            } else {

                                c = (refl == refa) ? 4 : 2;

                            }

                        }

                    } else {

                        if (s->above_intra_ctx[col]) {

                            c = 2;

                        } else if (s->above_comp_ctx[col]) {

                            c = 4 * (s->above_ref_ctx[col] != s->varcompref[1]);

                        } else {

                            c = 3 * (s->above_ref_ctx[col] != s->varcompref[1]);

                        }

                    }

                } else if (have_l) {

                    if (s->left_intra_ctx[row7]) {

                        c = 2;

                    } else if (s->left_comp_ctx[row7]) {

                        c = 4 * (s->left_ref_ctx[row7] != s->varcompref[1]);

                    } else {

                        c = 3 * (s->left_ref_ctx[row7] != s->varcompref[1]);

                    }

                } else {

                    c = 2;

                }

                bit = vp56_rac_get_prob(&s->c, s->prob.p.comp_ref[c]);

                b->ref[var_idx] = s->varcompref[bit];

                s->counts.comp_ref[c][bit]++;

            } else /* single reference */ {

                int bit, c;

                if (have_a && !s->above_intra_ctx[col]) {

                    if (have_l && !s->left_intra_ctx[row7]) {

                        if (s->left_comp_ctx[row7]) {

                            if (s->above_comp_ctx[col]) {

                                c = 1 + (!s->fixcompref || !s->left_ref_ctx[row7] ||

                                         !s->above_ref_ctx[col]);

                            } else {

                                c = (3 * !s->above_ref_ctx[col]) +

                                    (!s->fixcompref || !s->left_ref_ctx[row7]);

                            }

                        } else if (s->above_comp_ctx[col]) {

                            c = (3 * !s->left_ref_ctx[row7]) +

                                (!s->fixcompref || !s->above_ref_ctx[col]);

                        } else {

                            c = 2 * !s->left_ref_ctx[row7] + 2 * !s->above_ref_ctx[col];

                        }

                    } else if (s->above_intra_ctx[col]) {

                        c = 2;

                    } else if (s->above_comp_ctx[col]) {

                        c = 1 + (!s->fixcompref || !s->above_ref_ctx[col]);

                    } else {

                        c = 4 * (!s->above_ref_ctx[col]);

                    }

                } else if (have_l && !s->left_intra_ctx[row7]) {

                    if (s->left_intra_ctx[row7]) {

                        c = 2;

                    } else if (s->left_comp_ctx[row7]) {

                        c = 1 + (!s->fixcompref || !s->left_ref_ctx[row7]);

                    } else {

                        c = 4 * (!s->left_ref_ctx[row7]);

                    }

                } else {

                    c = 2;

                }

                bit = vp56_rac_get_prob(&s->c, s->prob.p.single_ref[c][0]);

                s->counts.single_ref[c][0][bit]++;

                if (!bit) {

                    b->ref[0] = 0;

                } else {

                    // FIXME can this codeblob be replaced by some sort of LUT?

                    if (have_a) {

                        if (have_l) {

                            if (s->left_intra_ctx[row7]) {

                                if (s->above_intra_ctx[col]) {

                                    c = 2;

                                } else if (s->above_comp_ctx[col]) {

                                    c = 1 + 2 * (s->fixcompref == 1 ||

                                                 s->above_ref_ctx[col] == 1);

                                } else if (!s->above_ref_ctx[col]) {

                                    c = 3;

                                } else {

                                    c = 4 * (s->above_ref_ctx[col] == 1);

                                }

                            } else if (s->above_intra_ctx[col]) {

                                if (s->left_intra_ctx[row7]) {

                                    c = 2;

                                } else if (s->left_comp_ctx[row7]) {

                                    c = 1 + 2 * (s->fixcompref == 1 ||

                                                 s->left_ref_ctx[row7] == 1);

                                } else if (!s->left_ref_ctx[row7]) {

                                    c = 3;

                                } else {

                                    c = 4 * (s->left_ref_ctx[row7] == 1);

                                }

                            } else if (s->above_comp_ctx[col]) {

                                if (s->left_comp_ctx[row7]) {

                                    if (s->left_ref_ctx[row7] == s->above_ref_ctx[col]) {

                                        c = 3 * (s->fixcompref == 1 ||

                                                 s->left_ref_ctx[row7] == 1);

                                    } else {

                                        c = 2;

                                    }

                                } else if (!s->left_ref_ctx[row7]) {

                                    c = 1 + 2 * (s->fixcompref == 1 ||

                                                 s->above_ref_ctx[col] == 1);

                                } else {

                                    c = 3 * (s->left_ref_ctx[row7] == 1) +

                                    (s->fixcompref == 1 || s->above_ref_ctx[col] == 1);

                                }

                            } else if (s->left_comp_ctx[row7]) {

                                if (!s->above_ref_ctx[col]) {

                                    c = 1 + 2 * (s->fixcompref == 1 ||

                                                 s->left_ref_ctx[row7] == 1);

                                } else {

                                    c = 3 * (s->above_ref_ctx[col] == 1) +

                                    (s->fixcompref == 1 || s->left_ref_ctx[row7] == 1);

                                }

                            } else if (!s->above_ref_ctx[col]) {

                                if (!s->left_ref_ctx[row7]) {

                                    c = 3;

                                } else {

                                    c = 4 * (s->left_ref_ctx[row7] == 1);

                                }

                            } else if (!s->left_ref_ctx[row7]) {

                                c = 4 * (s->above_ref_ctx[col] == 1);

                            } else {

                                c = 2 * (s->left_ref_ctx[row7] == 1) +

                                2 * (s->above_ref_ctx[col] == 1);

                            }

                        } else {

                            if (s->above_intra_ctx[col] ||

                                (!s->above_comp_ctx[col] && !s->above_ref_ctx[col])) {

                                c = 2;

                            } else if (s->above_comp_ctx[col]) {

                                c = 3 * (s->fixcompref == 1 || s->above_ref_ctx[col] == 1);

                            } else {

                                c = 4 * (s->above_ref_ctx[col] == 1);

                            }

                        }

                    } else if (have_l) {

                        if (s->left_intra_ctx[row7] ||

                            (!s->left_comp_ctx[row7] && !s->left_ref_ctx[row7])) {

                            c = 2;

                        } else if (s->left_comp_ctx[row7]) {

                            c = 3 * (s->fixcompref == 1 || s->left_ref_ctx[row7] == 1);

                        } else {

                            c = 4 * (s->left_ref_ctx[row7] == 1);

                        }

                    } else {

                        c = 2;

                    }

                    bit = vp56_rac_get_prob(&s->c, s->prob.p.single_ref[c][1]);

                    s->counts.single_ref[c][1][bit]++;

                    b->ref[0] = 1 + bit;

                }

            }

        }

        if (b->bs <= BS_8x8) {

            if (s->segmentation.feat[b->seg_id].skip_enabled) {

                b->mode[0] = b->mode[1] = b->mode[2] = b->mode[3] = ZEROMV;

            } else {

                static const uint8_t off[10] = {

                    3, 0, 0, 1, 0, 0, 0, 0, 0, 0

                };

                // FIXME this needs to use the LUT tables from find_ref_mvs

                // because not all are -1,0/0,-1

                int c = inter_mode_ctx_lut[s->above_mode_ctx[col + off[b->bs]]]

                                          [s->left_mode_ctx[row7 + off[b->bs]]];

                b->mode[0] = vp8_rac_get_tree(&s->c, vp9_inter_mode_tree,

                                              s->prob.p.mv_mode[c]);

                b->mode[1] = b->mode[2] = b->mode[3] = b->mode[0];

                s->counts.mv_mode[c][b->mode[0] - 10]++;

            }

        }

        if (s->filtermode == FILTER_SWITCHABLE) {

            int c;

            if (have_a && s->above_mode_ctx[col] >= NEARESTMV) {

                if (have_l && s->left_mode_ctx[row7] >= NEARESTMV) {

                    c = s->above_filter_ctx[col] == s->left_filter_ctx[row7] ?

                        s->left_filter_ctx[row7] : 3;

                } else {

                    c = s->above_filter_ctx[col];

                }

            } else if (have_l && s->left_mode_ctx[row7] >= NEARESTMV) {

                c = s->left_filter_ctx[row7];

            } else {

                c = 3;

            }

            b->filter = vp8_rac_get_tree(&s->c, vp9_filter_tree,

                                         s->prob.p.filter[c]);

            s->counts.filter[c][b->filter]++;

        } else {

            b->filter = s->filtermode;

        }

        if (b->bs > BS_8x8) {

            int c = inter_mode_ctx_lut[s->above_mode_ctx[col]][s->left_mode_ctx[row7]];

            b->mode[0] = vp8_rac_get_tree(&s->c, vp9_inter_mode_tree,

                                          s->prob.p.mv_mode[c]);

            s->counts.mv_mode[c][b->mode[0] - 10]++;

            fill_mv(s, b->mv[0], b->mode[0], 0);

            if (b->bs != BS_8x4) {

                b->mode[1] = vp8_rac_get_tree(&s->c, vp9_inter_mode_tree,

                                              s->prob.p.mv_mode[c]);

                s->counts.mv_mode[c][b->mode[1] - 10]++;

                fill_mv(s, b->mv[1], b->mode[1], 1);

            } else {

                b->mode[1] = b->mode[0];

                AV_COPY32(&b->mv[1][0], &b->mv[0][0]);

                AV_COPY32(&b->mv[1][1], &b->mv[0][1]);

            }

            if (b->bs != BS_4x8) {

                b->mode[2] = vp8_rac_get_tree(&s->c, vp9_inter_mode_tree,

                                              s->prob.p.mv_mode[c]);

                s->counts.mv_mode[c][b->mode[2] - 10]++;

                fill_mv(s, b->mv[2], b->mode[2], 2);

                if (b->bs != BS_8x4) {

                    b->mode[3] = vp8_rac_get_tree(&s->c, vp9_inter_mode_tree,

                                                  s->prob.p.mv_mode[c]);

                    s->counts.mv_mode[c][b->mode[3] - 10]++;

                    fill_mv(s, b->mv[3], b->mode[3], 3);

                } else {

                    b->mode[3] = b->mode[2];

                    AV_COPY32(&b->mv[3][0], &b->mv[2][0]);

                    AV_COPY32(&b->mv[3][1], &b->mv[2][1]);

                }

            } else {

                b->mode[2] = b->mode[0];

                AV_COPY32(&b->mv[2][0], &b->mv[0][0]);

                AV_COPY32(&b->mv[2][1], &b->mv[0][1]);

                b->mode[3] = b->mode[1];

                AV_COPY32(&b->mv[3][0], &b->mv[1][0]);

                AV_COPY32(&b->mv[3][1], &b->mv[1][1]);

            }

        } else {

            fill_mv(s, b->mv[0], b->mode[0], -1);

            AV_COPY32(&b->mv[1][0], &b->mv[0][0]);

            AV_COPY32(&b->mv[2][0], &b->mv[0][0]);

            AV_COPY32(&b->mv[3][0], &b->mv[0][0]);

            AV_COPY32(&b->mv[1][1], &b->mv[0][1]);

            AV_COPY32(&b->mv[2][1], &b->mv[0][1]);

            AV_COPY32(&b->mv[3][1], &b->mv[0][1]);

        }

    }

    // FIXME this can probably be optimized

    memset(&s->above_skip_ctx[col], b->skip, w4);

    memset(&s->left_skip_ctx[row7], b->skip, h4);

    memset(&s->above_txfm_ctx[col], b->tx, w4);

    memset(&s->left_txfm_ctx[row7], b->tx, h4);

    memset(&s->above_partition_ctx[col], above_ctx[b->bs], w4);

    memset(&s->left_partition_ctx[row7], left_ctx[b->bs], h4);

    if (!s->keyframe && !s->intraonly) {

        memset(&s->above_intra_ctx[col], b->intra, w4);

        memset(&s->left_intra_ctx[row7], b->intra, h4);

        memset(&s->above_comp_ctx[col], b->comp, w4);

        memset(&s->left_comp_ctx[row7], b->comp, h4);

        memset(&s->above_mode_ctx[col], b->mode[3], w4);

        memset(&s->left_mode_ctx[row7], b->mode[3], h4);

        if (s->filtermode == FILTER_SWITCHABLE && !b->intra ) {

            memset(&s->above_filter_ctx[col], b->filter, w4);

            memset(&s->left_filter_ctx[row7], b->filter, h4);

            b->filter = vp9_filter_lut[b->filter];

        }

        if (b->bs > BS_8x8) {

            int mv0 = AV_RN32A(&b->mv[3][0]), mv1 = AV_RN32A(&b->mv[3][1]);

            AV_COPY32(&s->left_mv_ctx[row7 * 2 + 0][0], &b->mv[1][0]);

            AV_COPY32(&s->left_mv_ctx[row7 * 2 + 0][1], &b->mv[1][1]);

            AV_WN32A(&s->left_mv_ctx[row7 * 2 + 1][0], mv0);

            AV_WN32A(&s->left_mv_ctx[row7 * 2 + 1][1], mv1);

            AV_COPY32(&s->above_mv_ctx[col * 2 + 0][0], &b->mv[2][0]);

            AV_COPY32(&s->above_mv_ctx[col * 2 + 0][1], &b->mv[2][1]);

            AV_WN32A(&s->above_mv_ctx[col * 2 + 1][0], mv0);

            AV_WN32A(&s->above_mv_ctx[col * 2 + 1][1], mv1);

        } else {

            int n, mv0 = AV_RN32A(&b->mv[3][0]), mv1 = AV_RN32A(&b->mv[3][1]);

            for (n = 0; n < w4 * 2; n++) {

                AV_WN32A(&s->above_mv_ctx[col * 2 + n][0], mv0);

                AV_WN32A(&s->above_mv_ctx[col * 2 + n][1], mv1);

            }

            for (n = 0; n < h4 * 2; n++) {

                AV_WN32A(&s->left_mv_ctx[row7 * 2 + n][0], mv0);

                AV_WN32A(&s->left_mv_ctx[row7 * 2 + n][1], mv1);

            }

        }

        if (!b->intra) { // FIXME write 0xff or -1 if intra, so we can use this

                         // as a direct check in above branches

            int vref = b->ref[b->comp ? s->signbias[s->varcompref[0]] : 0];

            memset(&s->above_ref_ctx[col], vref, w4);

            memset(&s->left_ref_ctx[row7], vref, h4);

        }

    }

    // FIXME kinda ugly

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

        int x, o = (row + y) * s->sb_cols * 8 + col;

        struct VP9mvrefPair *mv = &s->frames[CUR_FRAME].mv[o];

        if (b->intra) {

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

                mv[x].ref[0] =

                mv[x].ref[1] = -1;

            }

        } else if (b->comp) {

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

                mv[x].ref[0] = b->ref[0];

                mv[x].ref[1] = b->ref[1];

                AV_COPY32(&mv[x].mv[0], &b->mv[3][0]);

                AV_COPY32(&mv[x].mv[1], &b->mv[3][1]);

            }

        } else {

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

                mv[x].ref[0] = b->ref[0];

                mv[x].ref[1] = -1;

                AV_COPY32(&mv[x].mv[0], &b->mv[3][0]);

            }

        }

    }

}


int do_subchannel_work_virtual(SubchDev *sch)

{

    SCSW *s = &sch->curr_status.scsw;

    if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {

        sch_handle_clear_func(sch);

    } else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {

        sch_handle_halt_func(sch);

    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {

        /* Triggered by both ssch and rsch. */

        sch_handle_start_func_virtual(sch);

    }

    css_inject_io_interrupt(sch);

    return 0;

}


static int seg_write_header(AVFormatContext *s)

{

    SegmentContext *seg = s->priv_data;

    AVFormatContext *oc = NULL;

    int ret, i;

    seg->segment_count = 0;

    if (!seg->write_header_trailer)

        seg->individual_header_trailer = 0;

    if (seg->time_str && seg->times_str) {

        av_log(s, AV_LOG_ERROR,

               "segment_time and segment_times options are mutually exclusive, select just one of them\n");

        return AVERROR(EINVAL);

    }

    if ((seg->list_flags & SEGMENT_LIST_FLAG_LIVE) && seg->times_str) {

        av_log(s, AV_LOG_ERROR,

               "segment_flags +live and segment_times options are mutually exclusive:"

               "specify -segment_time if you want a live-friendly list\n");

        return AVERROR(EINVAL);

    }

    if (seg->times_str) {

        if ((ret = parse_times(s, &seg->times, &seg->nb_times, seg->times_str)) < 0)

            return ret;

    } else {

        /* set default value if not specified */

        if (!seg->time_str)

            seg->time_str = av_strdup("2");

        if ((ret = av_parse_time(&seg->time, seg->time_str, 1)) < 0) {

            av_log(s, AV_LOG_ERROR,

                   "Invalid time duration specification '%s' for segment_time option\n",

                   seg->time_str);

            return ret;

        }

    }

    if (seg->time_delta_str) {

        if ((ret = av_parse_time(&seg->time_delta, seg->time_delta_str, 1)) < 0) {

            av_log(s, AV_LOG_ERROR,

                   "Invalid time duration specification '%s' for delta option\n",

                   seg->time_delta_str);

            return ret;

        }

    }

    if (seg->list) {

        if (seg->list_type == LIST_TYPE_UNDEFINED) {

            if      (av_match_ext(seg->list, "csv" )) seg->list_type = LIST_TYPE_CSV;

            else if (av_match_ext(seg->list, "ext" )) seg->list_type = LIST_TYPE_EXT;

            else if (av_match_ext(seg->list, "m3u8")) seg->list_type = LIST_TYPE_M3U8;

            else                                      seg->list_type = LIST_TYPE_FLAT;

        }

        if ((ret = segment_list_open(s)) < 0)

            goto fail;

    }

    if (seg->list_type == LIST_TYPE_EXT)

        av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n");

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

        seg->has_video +=

            (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO);

    if (seg->has_video > 1)

        av_log(s, AV_LOG_WARNING,

               "More than a single video stream present, "

               "expect issues decoding it.\n");

    seg->oformat = av_guess_format(seg->format, s->filename, NULL);

    if (!seg->oformat) {

        ret = AVERROR_MUXER_NOT_FOUND;

        goto fail;

    }

    if (seg->oformat->flags & AVFMT_NOFILE) {

        av_log(s, AV_LOG_ERROR, "format %s not supported.\n",

               oc->oformat->name);

        ret = AVERROR(EINVAL);

        goto fail;

    }

    if ((ret = segment_mux_init(s)) < 0)

        goto fail;

    oc = seg->avf;

    if (av_get_frame_filename(oc->filename, sizeof(oc->filename),

                              s->filename, seg->segment_idx++) < 0) {

        ret = AVERROR(EINVAL);

        goto fail;

    }

    seg->segment_count++;

    if (seg->write_header_trailer) {

        if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,

                              &s->interrupt_callback, NULL)) < 0)

            goto fail;

    } else {

        if ((ret = open_null_ctx(&oc->pb)) < 0)

            goto fail;

    }

    if ((ret = avformat_write_header(oc, NULL)) < 0) {

        avio_close(oc->pb);

        goto fail;

    }

    if (oc->avoid_negative_ts > 0 && s->avoid_negative_ts < 0)

        s->avoid_negative_ts = 1;

    if (!seg->write_header_trailer) {

        close_null_ctx(oc->pb);

        if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,

                              &s->interrupt_callback, NULL)) < 0)

            goto fail;

    }

fail:

    if (ret) {

        if (seg->list)

            segment_list_close(s);

        if (seg->avf)

            avformat_free_context(seg->avf);

    }

    return ret;

}


void av_parser_close(AVCodecParserContext *s)

{

    if(s){

        if (s->parser->parser_close) {

            ff_lock_avcodec(NULL);

            s->parser->parser_close(s);

            ff_unlock_avcodec();

        }

        av_free(s->priv_data);

        av_free(s);

    }

}


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

{

    OpenPICState *opp = opaque;

    uint64_t r = 0;

    int i, srs;

    DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);

    if (addr & 0xF) {

        return -1;

    }

    srs = addr >> 4;

    switch (addr) {

    case 0x00:

    case 0x10:

    case 0x20:

    case 0x30:

    case 0x40:

    case 0x50:

    case 0x60:

    case 0x70: /* MSIRs */

        r = opp->msi[srs].msir;

        /* Clear on read */

        opp->msi[srs].msir = 0;

        break;

    case 0x120: /* MSISR */

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

            r |= (opp->msi[i].msir ? 1 : 0) << i;

        }

        break;

    }

    return r;

}


static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb, void *dst, const int type)

{

    int i, j, count = 0;

    int last, t;

    int A, B, L, L2, R, R2;

    int pos = s->pos;

    uint32_t crc = s->sc.crc;

    uint32_t crc_extra_bits = s->extra_sc.crc;

    int16_t *dst16 = dst;

    int32_t *dst32 = dst;

    float   *dstfl = dst;

    const int channel_pad = s->avctx->channels - 2;

    if(s->samples_left == s->samples)

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

    do{

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

        if(last) break;

        R = wv_get_value(s, gb, 1, &last);

        if(last) break;

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

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

            if(t > 0){

                if(t > 8){

                    if(t & 1){

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

                        B = 2 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1];

                    }else{

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

                        B = (3 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1]) >> 1;

                    }

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

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

                    j = 0;

                }else{

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

                    B = s->decorr[i].samplesB[pos];

                    j = (pos + t) & 7;

                }

                if(type != AV_SAMPLE_FMT_S16){

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

                    R2 = R + ((s->decorr[i].weightB * (int64_t)B + 512) >> 10);

                }else{

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

                    R2 = R + ((s->decorr[i].weightB * B + 512) >> 10);

                }

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

                if(B && R) s->decorr[i].weightB -= ((((R ^ B) >> 30) & 2) - 1) * s->decorr[i].delta;

                s->decorr[i].samplesA[j] = L = L2;

                s->decorr[i].samplesB[j] = R = R2;

            }else if(t == -1){

                if(type != AV_SAMPLE_FMT_S16)

                    L2 = L + ((s->decorr[i].weightA * (int64_t)s->decorr[i].samplesA[0] + 512) >> 10);

                else

                    L2 = L + ((s->decorr[i].weightA * s->decorr[i].samplesA[0] + 512) >> 10);

                UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, s->decorr[i].samplesA[0], L);

                L = L2;

                if(type != AV_SAMPLE_FMT_S16)

                    R2 = R + ((s->decorr[i].weightB * (int64_t)L2 + 512) >> 10);

                else

                    R2 = R + ((s->decorr[i].weightB * L2 + 512) >> 10);

                UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, L2, R);

                R = R2;

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

            }else{

                if(type != AV_SAMPLE_FMT_S16)

                    R2 = R + ((s->decorr[i].weightB * (int64_t)s->decorr[i].samplesB[0] + 512) >> 10);

                else

                    R2 = R + ((s->decorr[i].weightB * s->decorr[i].samplesB[0] + 512) >> 10);

                UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, s->decorr[i].samplesB[0], R);

                R = R2;

                if(t == -3){

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

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

                }

                if(type != AV_SAMPLE_FMT_S16)

                    L2 = L + ((s->decorr[i].weightA * (int64_t)R2 + 512) >> 10);

                else

                    L2 = L + ((s->decorr[i].weightA * R2 + 512) >> 10);

                UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, R2, L);

                L = L2;

                s->decorr[i].samplesB[0] = L;

            }

        }

        pos = (pos + 1) & 7;

        if(s->joint)

            L += (R -= (L >> 1));

        crc = (crc * 3 + L) * 3 + R;

        if(type == AV_SAMPLE_FMT_FLT){

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

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

            dstfl += channel_pad;

        } else if(type == AV_SAMPLE_FMT_S32){

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

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

            dst32 += channel_pad;

        } else {

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

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

            dst16 += channel_pad;

        }

        count++;

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

    s->samples_left -= count;

    if(!s->samples_left){

        wv_reset_saved_context(s);

        if(crc != s->CRC){

            av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");

            return -1;

        }

        if(s->got_extra_bits && crc_extra_bits != s->crc_extra_bits){

            av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");

            return -1;

        }

    }else{

        s->pos = pos;

        s->sc.crc = crc;

        s->sc.bits_used = get_bits_count(&s->gb);

        if(s->got_extra_bits){

            s->extra_sc.crc = crc_extra_bits;

            s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits);

        }

    }

    return count * 2;

}


static int get_mmu_address(CPUState * env, target_ulong * physical,

			   int *prot, target_ulong address,

			   int rw, int access_type)

{

    int use_asid, is_code, n;

    tlb_t *matching = NULL;

    use_asid = (env->mmucr & MMUCR_SV) == 0 && (env->sr & SR_MD) == 0;

    is_code = env->pc == address;	/* Hack */

    /* Use a hack to find if this is an instruction or data access */

    if (env->pc == address && !(rw & PAGE_WRITE)) {

	n = find_itlb_entry(env, address, use_asid, 1);

	if (n >= 0) {

	    matching = &env->itlb[n];

	    if ((env->sr & SR_MD) & !(matching->pr & 2))

		n = MMU_ITLB_VIOLATION;

	    else

		*prot = PAGE_READ;

	}

    } else {

	n = find_utlb_entry(env, address, use_asid);

	if (n >= 0) {

	    matching = &env->utlb[n];

	    switch ((matching->pr << 1) | ((env->sr & SR_MD) ? 1 : 0)) {

	    case 0:		/* 000 */

	    case 2:		/* 010 */

		n = (rw & PAGE_WRITE) ? MMU_DTLB_VIOLATION_WRITE :

		    MMU_DTLB_VIOLATION_READ;

		break;

	    case 1:		/* 001 */

	    case 4:		/* 100 */

	    case 5:		/* 101 */

		if (rw & PAGE_WRITE)

		    n = MMU_DTLB_VIOLATION_WRITE;

		else

		    *prot = PAGE_READ;

		break;

	    case 3:		/* 011 */

	    case 6:		/* 110 */

	    case 7:		/* 111 */

		*prot = rw & (PAGE_READ | PAGE_WRITE);

		break;

	    }

	} else if (n == MMU_DTLB_MISS) {

	    n = (rw & PAGE_WRITE) ? MMU_DTLB_MISS_WRITE :

		MMU_DTLB_MISS_READ;

	}

    }

    if (n >= 0) {

	*physical = ((matching->ppn << 10) & ~(matching->size - 1)) |

	    (address & (matching->size - 1));

	if ((rw & PAGE_WRITE) & !matching->d)

	    n = MMU_DTLB_INITIAL_WRITE;

	else

	    n = MMU_OK;

    }

    return n;

}


static inline void mix_2f_1r_to_mono(AC3DecodeContext *ctx)

{

    int i;

    float (*output)[256] = ctx->audio_block.block_output;

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

        output[1][i] += (output[2][i] + output[3][i]);

    memset(output[2], 0, sizeof(output[2]));

    memset(output[3], 0, sizeof(output[3]));

}


void mjpeg_picture_header(MpegEncContext *s)

{

    put_marker(&s->pb, SOI);

    jpeg_table_header(s);

    put_marker(&s->pb, SOF0);

    put_bits(&s->pb, 16, 17);

    put_bits(&s->pb, 8, 8); /* 8 bits/component */

    put_bits(&s->pb, 16, s->height);

    put_bits(&s->pb, 16, s->width);

    put_bits(&s->pb, 8, 3); /* 3 components */

    /* Y component */

    put_bits(&s->pb, 8, 1); /* component number */

    put_bits(&s->pb, 4, 2); /* H factor */

    put_bits(&s->pb, 4, 2); /* V factor */

    put_bits(&s->pb, 8, 0); /* select matrix */

    /* Cb component */

    put_bits(&s->pb, 8, 2); /* component number */

    put_bits(&s->pb, 4, 1); /* H factor */

    put_bits(&s->pb, 4, 1); /* V factor */

    put_bits(&s->pb, 8, 0); /* select matrix */

    /* Cr component */

    put_bits(&s->pb, 8, 3); /* component number */

    put_bits(&s->pb, 4, 1); /* H factor */

    put_bits(&s->pb, 4, 1); /* V factor */

    put_bits(&s->pb, 8, 0); /* select matrix */

    /* scan header */

    put_marker(&s->pb, SOS);

    put_bits(&s->pb, 16, 12); /* length */

    put_bits(&s->pb, 8, 3); /* 3 components */

    /* Y component */

    put_bits(&s->pb, 8, 1); /* index */

    put_bits(&s->pb, 4, 0); /* DC huffman table index */

    put_bits(&s->pb, 4, 0); /* AC huffman table index */

    /* Cb component */

    put_bits(&s->pb, 8, 2); /* index */

    put_bits(&s->pb, 4, 1); /* DC huffman table index */

    put_bits(&s->pb, 4, 1); /* AC huffman table index */

    /* Cr component */

    put_bits(&s->pb, 8, 3); /* index */

    put_bits(&s->pb, 4, 1); /* DC huffman table index */

    put_bits(&s->pb, 4, 1); /* AC huffman table index */

    put_bits(&s->pb, 8, 0); /* Ss (not used) */

    put_bits(&s->pb, 8, 63); /* Se (not used) */

    put_bits(&s->pb, 8, 0); /* (not used) */

}


void qmp_xen_save_devices_state(const char *filename, Error **errp)

{

    QEMUFile *f;

    QIOChannelFile *ioc;

    int saved_vm_running;

    int ret;

    saved_vm_running = runstate_is_running();

    vm_stop(RUN_STATE_SAVE_VM);

    global_state_store_running();

    ioc = qio_channel_file_new_path(filename, O_WRONLY | O_CREAT, 0660, errp);

    if (!ioc) {

        goto the_end;

    }

    qio_channel_set_name(QIO_CHANNEL(ioc), "migration-xen-save-state");

    f = qemu_fopen_channel_output(QIO_CHANNEL(ioc));

    ret = qemu_save_device_state(f);

    qemu_fclose(f);

    if (ret < 0) {

        error_setg(errp, QERR_IO_ERROR);

    }

 the_end:

    if (saved_vm_running) {

        vm_start();

    }

}


static int get_physical_address(CPUState *env, target_phys_addr_t *physical,

                                int *prot, int *access_index,

                                target_ulong address, int rw, int mmu_idx)

{

    int access_perms = 0;

    target_phys_addr_t pde_ptr;

    uint32_t pde;

    int error_code = 0, is_dirty, is_user;

    unsigned long page_offset;

    is_user = mmu_idx == MMU_USER_IDX;

    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */

        // Boot mode: instruction fetches are taken from PROM

        if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {

            *physical = env->prom_addr | (address & 0x7ffffULL);

            *prot = PAGE_READ | PAGE_EXEC;

            return 0;

        }

        *physical = address;

        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;

        return 0;

    }

    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);

    *physical = 0xffffffffffff0000ULL;

    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */

    /* Context base + context number */

    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);

    pde = ldl_phys(pde_ptr);

    /* Ctx pde */

    switch (pde & PTE_ENTRYTYPE_MASK) {

    default:

    case 0: /* Invalid */

        return 1 << 2;

    case 2: /* L0 PTE, maybe should not happen? */

    case 3: /* Reserved */

        return 4 << 2;

    case 1: /* L0 PDE */

        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);

        pde = ldl_phys(pde_ptr);

        switch (pde & PTE_ENTRYTYPE_MASK) {

        default:

        case 0: /* Invalid */

            return (1 << 8) | (1 << 2);

        case 3: /* Reserved */

            return (1 << 8) | (4 << 2);

        case 1: /* L1 PDE */

            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);

            pde = ldl_phys(pde_ptr);

            switch (pde & PTE_ENTRYTYPE_MASK) {

            default:

            case 0: /* Invalid */

                return (2 << 8) | (1 << 2);

            case 3: /* Reserved */

                return (2 << 8) | (4 << 2);

            case 1: /* L2 PDE */

                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);

                pde = ldl_phys(pde_ptr);

                switch (pde & PTE_ENTRYTYPE_MASK) {

                default:

                case 0: /* Invalid */

                    return (3 << 8) | (1 << 2);

                case 1: /* PDE, should not happen */

                case 3: /* Reserved */

                    return (3 << 8) | (4 << 2);

                case 2: /* L3 PTE */

                    page_offset = (address & TARGET_PAGE_MASK) &

                        (TARGET_PAGE_SIZE - 1);

                }

                break;

            case 2: /* L2 PTE */

                page_offset = address & 0x3ffff;

            }

            break;

        case 2: /* L1 PTE */

            page_offset = address & 0xffffff;

        }

    }

    /* update page modified and dirty bits */

    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);

    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

        pde |= PG_ACCESSED_MASK;

        if (is_dirty)

            pde |= PG_MODIFIED_MASK;

        stl_phys_notdirty(pde_ptr, pde);

    }

    /* check access */

    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;

    error_code = access_table[*access_index][access_perms];

    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))

        return error_code;

    /* the page can be put in the TLB */

    *prot = perm_table[is_user][access_perms];

    if (!(pde & PG_MODIFIED_MASK)) {

        /* only set write access if already dirty... otherwise wait

           for dirty access */

        *prot &= ~PAGE_WRITE;

    }

    /* Even if large ptes, we map only one 4KB page in the cache to

       avoid filling it too fast */

    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;

    return error_code;

}


static void pci_bridge_region_cleanup(PCIBridge *br)

{

    PCIBus *parent = br->dev.bus;

    pci_bridge_cleanup_alias(&br->alias_io,

                             parent->address_space_io);

    pci_bridge_cleanup_alias(&br->alias_mem,

                             parent->address_space_mem);

    pci_bridge_cleanup_alias(&br->alias_pref_mem,

                             parent->address_space_mem);

}


static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)

{

    IDEState *s = opaque;

    int data_offset, n;

    if (ret < 0) {

        ide_atapi_io_error(s, ret);

        goto eot;

    }

    if (s->io_buffer_size > 0) {

        /*

         * For a cdrom read sector command (s->lba != -1),

         * adjust the lba for the next s->io_buffer_size chunk

         * and dma the current chunk.

         * For a command != read (s->lba == -1), just transfer

         * the reply data.

         */

        if (s->lba != -1) {

            if (s->cd_sector_size == 2352) {

                n = 1;

                cd_data_to_raw(s->io_buffer, s->lba);

            } else {

                n = s->io_buffer_size >> 11;

            }

            s->lba += n;

        }

        s->packet_transfer_size -= s->io_buffer_size;

        if (s->bus->dma->ops->rw_buf(s->bus->dma, 1) == 0)

            goto eot;

    }

    if (s->packet_transfer_size <= 0) {

        s->status = READY_STAT | SEEK_STAT;

        s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;

        ide_set_irq(s->bus);

        goto eot;

    }

    s->io_buffer_index = 0;

    if (s->cd_sector_size == 2352) {

        n = 1;

        s->io_buffer_size = s->cd_sector_size;

        data_offset = 16;

    } else {

        n = s->packet_transfer_size >> 11;

        if (n > (IDE_DMA_BUF_SECTORS / 4))

            n = (IDE_DMA_BUF_SECTORS / 4);

        s->io_buffer_size = n * 2048;

        data_offset = 0;

    }

#ifdef DEBUG_AIO

    printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);

#endif

    s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);

    s->bus->dma->iov.iov_len = n * 4 * 512;

    qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);

    s->bus->dma->aiocb = blk_aio_readv(s->blk, (int64_t)s->lba << 2,

                                       &s->bus->dma->qiov, n * 4,

                                       ide_atapi_cmd_read_dma_cb, s);

    return;

eot:

    block_acct_done(blk_get_stats(s->blk), &s->acct);

    ide_set_inactive(s, false);

}


static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)

{

    S390CCWDevice *cdev = data;

    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);

    struct ccw_io_region *region = vcdev->io_region;

    int ret;

    QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB));

    QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW));

    QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB));

    memset(region, 0, sizeof(*region));

    memcpy(region->orb_area, orb, sizeof(ORB));

    memcpy(region->scsw_area, scsw, sizeof(SCSW));

again:

    ret = pwrite(vcdev->vdev.fd, region,

                 vcdev->io_region_size, vcdev->io_region_offset);

    if (ret != vcdev->io_region_size) {

        if (errno == EAGAIN) {

            goto again;

        }

        error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno);

        return -errno;

    }

    return region->ret_code;

}


static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)

{

    VideoState *is = opaque;

    int audio_size, len1, silence = 0;

    audio_callback_time = av_gettime_relative();

    while (len > 0) {

        if (is->audio_buf_index >= is->audio_buf_size) {

           audio_size = audio_decode_frame(is);

           if (audio_size < 0) {

                /* if error, just output silence */

               silence = 1;

               is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;

           } else {

               if (is->show_mode != SHOW_MODE_VIDEO)

                   update_sample_display(is, (int16_t *)is->audio_buf, audio_size);

               is->audio_buf_size = audio_size;

           }

           is->audio_buf_index = 0;

        }

        len1 = is->audio_buf_size - is->audio_buf_index;

        if (len1 > len)

            len1 = len;

        if (!is->muted && !silence && is->audio_volume == SDL_MIX_MAXVOLUME)

            memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);

        else {

            memset(stream, 0, len1);

            if (!is->muted && !silence)

                SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, is->audio_volume);

        }

        len -= len1;

        stream += len1;

        is->audio_buf_index += len1;

    }

    is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;

    /* Let's assume the audio driver that is used by SDL has two periods. */

    if (!isnan(is->audio_clock)) {

        set_clock_at(&is->audclk, is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec, is->audio_clock_serial, audio_callback_time / 1000000.0);

        sync_clock_to_slave(&is->extclk, &is->audclk);

    }

}


static int wmavoice_decode_packet(AVCodecContext *ctx, void *data,

                                  int *got_frame_ptr, AVPacket *avpkt)

{

    WMAVoiceContext *s = ctx->priv_data;

    GetBitContext *gb = &s->gb;

    int size, res, pos;

    /* Packets are sometimes a multiple of ctx->block_align, with a packet

     * header at each ctx->block_align bytes. However, FFmpeg's ASF demuxer

     * feeds us ASF packets, which may concatenate multiple "codec" packets

     * in a single "muxer" packet, so we artificially emulate that by

     * capping the packet size at ctx->block_align. */

    for (size = avpkt->size; size > ctx->block_align; size -= ctx->block_align);

    init_get_bits(&s->gb, avpkt->data, size << 3);

    /* size == ctx->block_align is used to indicate whether we are dealing with

     * a new packet or a packet of which we already read the packet header

     * previously. */

    if (!(size % ctx->block_align)) { // new packet header

        if (!size) {

            s->spillover_nbits = 0;

            s->nb_superframes = 0;

        } else {

            if ((res = parse_packet_header(s)) < 0)

                return res;

            s->nb_superframes = res;

        }

        /* If the packet header specifies a s->spillover_nbits, then we want

         * to push out all data of the previous packet (+ spillover) before

         * continuing to parse new superframes in the current packet. */

        if (s->sframe_cache_size > 0) {

            int cnt = get_bits_count(gb);

            copy_bits(&s->pb, avpkt->data, size, gb, s->spillover_nbits);

            flush_put_bits(&s->pb);

            s->sframe_cache_size += s->spillover_nbits;

            if ((res = synth_superframe(ctx, data, got_frame_ptr)) == 0 &&

                *got_frame_ptr) {

                cnt += s->spillover_nbits;

                s->skip_bits_next = cnt & 7;

                res = cnt >> 3;

                if (res > avpkt->size) {

                    av_log(ctx, AV_LOG_ERROR,

                           "Trying to skip %d bytes in packet of size %d\n",

                           res, avpkt->size);

                    return AVERROR_INVALIDDATA;

                }

                return res;

            } else

                skip_bits_long (gb, s->spillover_nbits - cnt +

                                get_bits_count(gb)); // resync

        } else if (s->spillover_nbits) {

            skip_bits_long(gb, s->spillover_nbits);  // resync

        }

    } else if (s->skip_bits_next)

        skip_bits(gb, s->skip_bits_next);

    /* Try parsing superframes in current packet */

    s->sframe_cache_size = 0;

    s->skip_bits_next = 0;

    pos = get_bits_left(gb);

    if (s->nb_superframes-- == 0) {

        *got_frame_ptr = 0;

        return size;

    } else if (s->nb_superframes > 0) {

        if ((res = synth_superframe(ctx, data, got_frame_ptr)) < 0) {

            return res;

        } else if (*got_frame_ptr) {

            int cnt = get_bits_count(gb);

            s->skip_bits_next = cnt & 7;

            res = cnt >> 3;

            if (res > avpkt->size) {

                av_log(ctx, AV_LOG_ERROR,

                       "Trying to skip %d bytes in packet of size %d\n",

                       res, avpkt->size);

                return AVERROR_INVALIDDATA;

            }

            return res;

        }

    } else if ((s->sframe_cache_size = pos) > 0) {

        /* ... cache it for spillover in next packet */

        init_put_bits(&s->pb, s->sframe_cache, SFRAME_CACHE_MAXSIZE);

        copy_bits(&s->pb, avpkt->data, size, gb, s->sframe_cache_size);

        // FIXME bad - just copy bytes as whole and add use the

        // skip_bits_next field

    }

    return size;

}


static void ppc_core99_init (ram_addr_t ram_size,

                             const char *boot_device,

                             const char *kernel_filename,

                             const char *kernel_cmdline,

                             const char *initrd_filename,

                             const char *cpu_model)

{

    CPUState *env = NULL;

    char *filename;

    qemu_irq *pic, **openpic_irqs;

    int unin_memory;

    int linux_boot, i;

    ram_addr_t ram_offset, bios_offset;

    target_phys_addr_t kernel_base, initrd_base, cmdline_base = 0;

    long kernel_size, initrd_size;

    PCIBus *pci_bus;

    MacIONVRAMState *nvr;

    int bios_size;

    MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem;

    MemoryRegion *ide_mem[3];

    int ppc_boot_device;

    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    void *fw_cfg;

    void *dbdma;

    int machine_arch;

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */

    if (cpu_model == NULL)

#ifdef TARGET_PPC64

        cpu_model = "970fx";

#else

        cpu_model = "G4";

#endif

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

        env = cpu_init(cpu_model);

        if (!env) {

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

            exit(1);

        }

        /* Set time-base frequency to 100 Mhz */

        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);

        qemu_register_reset((QEMUResetHandler*)&cpu_reset, env);

    }

    /* allocate RAM */

    ram_offset = qemu_ram_alloc(NULL, "ppc_core99.ram", ram_size);

    cpu_register_physical_memory(0, ram_size, ram_offset);

    /* allocate and load BIOS */

    bios_offset = qemu_ram_alloc(NULL, "ppc_core99.bios", BIOS_SIZE);

    if (bios_name == NULL)

        bios_name = PROM_FILENAME;

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);

    cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM);

    /* Load OpenBIOS (ELF) */

    if (filename) {

        bios_size = load_elf(filename, NULL, NULL, NULL,

                             NULL, NULL, 1, ELF_MACHINE, 0);

        g_free(filename);

    } else {

        bios_size = -1;

    }

    if (bios_size < 0 || bios_size > BIOS_SIZE) {

        hw_error("qemu: could not load PowerPC bios '%s'\n", bios_name);

        exit(1);

    }

    if (linux_boot) {

        uint64_t lowaddr = 0;

        int bswap_needed;

#ifdef BSWAP_NEEDED

        bswap_needed = 1;

#else

        bswap_needed = 0;

#endif

        kernel_base = KERNEL_LOAD_ADDR;

        kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,

                               NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);

        if (kernel_size < 0)

            kernel_size = load_aout(kernel_filename, kernel_base,

                                    ram_size - kernel_base, bswap_needed,

                                    TARGET_PAGE_SIZE);

        if (kernel_size < 0)

            kernel_size = load_image_targphys(kernel_filename,

                                              kernel_base,

                                              ram_size - kernel_base);

        if (kernel_size < 0) {

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

            exit(1);

        }

        /* load initrd */

        if (initrd_filename) {

            initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);

            initrd_size = load_image_targphys(initrd_filename, initrd_base,

                                              ram_size - initrd_base);

            if (initrd_size < 0) {

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

                         initrd_filename);

                exit(1);

            }

            cmdline_base = round_page(initrd_base + initrd_size);

        } else {

            initrd_base = 0;

            initrd_size = 0;

            cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);

        }

        ppc_boot_device = 'm';

    } else {

        kernel_base = 0;

        kernel_size = 0;

        initrd_base = 0;

        initrd_size = 0;

        ppc_boot_device = '\0';

        /* We consider that NewWorld PowerMac never have any floppy drive

         * For now, OHW cannot boot from the network.

         */

        for (i = 0; boot_device[i] != '\0'; i++) {

            if (boot_device[i] >= 'c' && boot_device[i] <= 'f') {

                ppc_boot_device = boot_device[i];

                break;

            }

        }

        if (ppc_boot_device == '\0') {

            fprintf(stderr, "No valid boot device for Mac99 machine\n");

            exit(1);

        }

    }

    isa_mem_base = 0x80000000;

    /* Register 8 MB of ISA IO space */

    isa_mmio_init(0xf2000000, 0x00800000);

    /* UniN init */

    unin_memory = cpu_register_io_memory(unin_read, unin_write, NULL,

                                         DEVICE_NATIVE_ENDIAN);

    cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);

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

    openpic_irqs[0] =

        g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);

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

        /* Mac99 IRQ connection between OpenPIC outputs pins

         * and PowerPC input pins

         */

        switch (PPC_INPUT(env)) {

        case PPC_FLAGS_INPUT_6xx:

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

            openpic_irqs[i][OPENPIC_OUTPUT_INT] =

                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];

            openpic_irqs[i][OPENPIC_OUTPUT_CINT] =

                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];

            openpic_irqs[i][OPENPIC_OUTPUT_MCK] =

                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];

            /* Not connected ? */

            openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;

            /* Check this */

            openpic_irqs[i][OPENPIC_OUTPUT_RESET] =

                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];

            break;

#if defined(TARGET_PPC64)

        case PPC_FLAGS_INPUT_970:

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

            openpic_irqs[i][OPENPIC_OUTPUT_INT] =

                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];

            openpic_irqs[i][OPENPIC_OUTPUT_CINT] =

                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];

            openpic_irqs[i][OPENPIC_OUTPUT_MCK] =

                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];

            /* Not connected ? */

            openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;

            /* Check this */

            openpic_irqs[i][OPENPIC_OUTPUT_RESET] =

                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];

            break;

#endif /* defined(TARGET_PPC64) */

        default:

            hw_error("Bus model not supported on mac99 machine\n");

            exit(1);

        }

    }

    pic = openpic_init(NULL, &pic_mem, smp_cpus, openpic_irqs, NULL);

    if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {

        /* 970 gets a U3 bus */

        pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io());

        machine_arch = ARCH_MAC99_U3;

    } else {

        pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io());

        machine_arch = ARCH_MAC99;

    }

    /* init basic PC hardware */

    pci_vga_init(pci_bus);

    escc_mem = escc_init(0x80013000, pic[0x25], pic[0x24],

                         serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);

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

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

    ide_drive_get(hd, MAX_IDE_BUS);

    dbdma = DBDMA_init(&dbdma_mem);

    /* We only emulate 2 out of 3 IDE controllers for now */

    ide_mem[0] = NULL;

    ide_mem[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]);

    ide_mem[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]);

    /* cuda also initialize ADB */

    if (machine_arch == ARCH_MAC99_U3) {

        usb_enabled = 1;

    }

    cuda_init(&cuda_mem, pic[0x19]);

    adb_kbd_init(&adb_bus);

    adb_mouse_init(&adb_bus);

    macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem,

               dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_mem);

    if (usb_enabled) {

        usb_ohci_init_pci(pci_bus, -1);

    }

    /* U3 needs to use USB for input because Linux doesn't support via-cuda

       on PPC64 */

    if (machine_arch == ARCH_MAC99_U3) {

        usbdevice_create("keyboard");

        usbdevice_create("mouse");

    }

    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)

        graphic_depth = 15;

    /* The NewWorld NVRAM is not located in the MacIO device */

    nvr = macio_nvram_init(0x2000, 1);

    pmac_format_nvram_partition(nvr, 0x2000);

    macio_nvram_setup_bar(nvr, get_system_memory(), 0xFFF04000);

    /* No PCI init: the BIOS will do it */

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

    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);

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

    fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch);

    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);

    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);

    if (kernel_cmdline) {

        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);

        pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);

    } else {

        fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);

    }

    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base);

    fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);

    fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device);

    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width);

    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);

    fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);

    fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());

    if (kvm_enabled()) {

#ifdef CONFIG_KVM

        uint8_t *hypercall;

        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());

        hypercall = g_malloc(16);

        kvmppc_get_hypercall(env, hypercall, 16);

        fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);

        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());

#endif

    } else {

        fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());

    }

    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);

}


void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,

                               int is_write, target_phys_addr_t access_len)

{

    if (buffer != bounce.buffer) {

        if (is_write) {

            unsigned long addr1 = (uint8_t *)buffer - phys_ram_base;

            while (access_len) {

                unsigned l;

                l = TARGET_PAGE_SIZE;

                if (l > access_len)

                    l = access_len;

                if (!cpu_physical_memory_is_dirty(addr1)) {

                    /* invalidate code */

                    tb_invalidate_phys_page_range(addr1, addr1 + l, 0);

                    /* set dirty bit */

                    phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=

                        (0xff & ~CODE_DIRTY_FLAG);

                }

                addr1 += l;

                access_len -= l;

            }

        }

        return;

    }

    if (is_write) {

        cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);

    }

    qemu_free(bounce.buffer);

    bounce.buffer = NULL;

}


static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)

{

    AVStream *st;

    if (c->fc->nb_streams < 1)

        return 0;

    st = c->fc->streams[c->fc->nb_streams-1];

    if ((uint64_t)atom.size > (1<<30))

        return AVERROR_INVALIDDATA;

    if (atom.size >= 10) {

        // Broken files created by legacy versions of libavformat will

        // wrap a whole fiel atom inside of a glbl atom.

        unsigned size = avio_rb32(pb);

        unsigned type = avio_rl32(pb);

        avio_seek(pb, -8, SEEK_CUR);

        if (type == MKTAG('f','i','e','l') && size == atom.size)

            return mov_read_default(c, pb, atom);

    }

    av_free(st->codec->extradata);

    st->codec->extradata = av_mallocz(atom.size + FF_INPUT_BUFFER_PADDING_SIZE);

    if (!st->codec->extradata)

        return AVERROR(ENOMEM);

    st->codec->extradata_size = atom.size;

    avio_read(pb, st->codec->extradata, atom.size);

    return 0;

}