av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,

                             SwsFilter *dstFilter)

{

    int i;

    int usesVFilter, usesHFilter;

    int unscaled;

    SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };

    int srcW              = c->srcW;

    int srcH              = c->srcH;

    int dstW              = c->dstW;

    int dstH              = c->dstH;

    int dst_stride        = FFALIGN(dstW * sizeof(int16_t) + 16, 16);

    int dst_stride_px     = dst_stride >> 1;

    int flags, cpu_flags;

    enum PixelFormat srcFormat = c->srcFormat;

    enum PixelFormat dstFormat = c->dstFormat;

    cpu_flags = av_get_cpu_flags();

    flags     = c->flags;

    emms_c();

    if (!rgb15to16)

        sws_rgb2rgb_init();

    unscaled = (srcW == dstW && srcH == dstH);

    if (!sws_isSupportedInput(srcFormat)) {

        av_log(c, AV_LOG_ERROR, "%s is not supported as input pixel format\n",

               sws_format_name(srcFormat));

        return AVERROR(EINVAL);

    }

    if (!sws_isSupportedOutput(dstFormat)) {

        av_log(c, AV_LOG_ERROR, "%s is not supported as output pixel format\n",

               sws_format_name(dstFormat));

        return AVERROR(EINVAL);

    }

    i = flags & (SWS_POINT         |

                 SWS_AREA          |

                 SWS_BILINEAR      |

                 SWS_FAST_BILINEAR |

                 SWS_BICUBIC       |

                 SWS_X             |

                 SWS_GAUSS         |

                 SWS_LANCZOS       |

                 SWS_SINC          |

                 SWS_SPLINE        |

                 SWS_BICUBLIN);

    if (!i || (i & (i - 1))) {

        av_log(c, AV_LOG_ERROR,

               "Exactly one scaler algorithm must be chosen\n");

        return AVERROR(EINVAL);

    }

    /* sanity check */

    if (srcW < 4 || srcH < 1 || dstW < 8 || dstH < 1) {

        /* FIXME check if these are enough and try to lower them after

         * fixing the relevant parts of the code */

        av_log(c, AV_LOG_ERROR, "%dx%d -> %dx%d is invalid scaling dimension\n",

               srcW, srcH, dstW, dstH);

        return AVERROR(EINVAL);

    }

    if (!dstFilter)

        dstFilter = &dummyFilter;

    if (!srcFilter)

        srcFilter = &dummyFilter;

    c->lumXInc      = (((int64_t)srcW << 16) + (dstW >> 1)) / dstW;

    c->lumYInc      = (((int64_t)srcH << 16) + (dstH >> 1)) / dstH;

    c->dstFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[dstFormat]);

    c->srcFormatBpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[srcFormat]);

    c->vRounder     = 4 * 0x0001000100010001ULL;

    usesVFilter = (srcFilter->lumV && srcFilter->lumV->length > 1) ||

                  (srcFilter->chrV && srcFilter->chrV->length > 1) ||

                  (dstFilter->lumV && dstFilter->lumV->length > 1) ||

                  (dstFilter->chrV && dstFilter->chrV->length > 1);

    usesHFilter = (srcFilter->lumH && srcFilter->lumH->length > 1) ||

                  (srcFilter->chrH && srcFilter->chrH->length > 1) ||

                  (dstFilter->lumH && dstFilter->lumH->length > 1) ||

                  (dstFilter->chrH && dstFilter->chrH->length > 1);

    getSubSampleFactors(&c->chrSrcHSubSample, &c->chrSrcVSubSample, srcFormat);

    getSubSampleFactors(&c->chrDstHSubSample, &c->chrDstVSubSample, dstFormat);

    /* reuse chroma for 2 pixels RGB/BGR unless user wants full

     * chroma interpolation */

    if (flags & SWS_FULL_CHR_H_INT &&

        isAnyRGB(dstFormat)        &&

        dstFormat != PIX_FMT_RGBA  &&

        dstFormat != PIX_FMT_ARGB  &&

        dstFormat != PIX_FMT_BGRA  &&

        dstFormat != PIX_FMT_ABGR  &&

        dstFormat != PIX_FMT_RGB24 &&

        dstFormat != PIX_FMT_BGR24) {

        av_log(c, AV_LOG_ERROR,

               "full chroma interpolation for destination format '%s' not yet implemented\n",

               sws_format_name(dstFormat));

        flags   &= ~SWS_FULL_CHR_H_INT;

        c->flags = flags;

    }

    if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT))

        c->chrDstHSubSample = 1;

    // drop some chroma lines if the user wants it

    c->vChrDrop          = (flags & SWS_SRC_V_CHR_DROP_MASK) >>

                           SWS_SRC_V_CHR_DROP_SHIFT;

    c->chrSrcVSubSample += c->vChrDrop;

    /* drop every other pixel for chroma calculation unless user

     * wants full chroma */

    if (isAnyRGB(srcFormat) && !(flags & SWS_FULL_CHR_H_INP)   &&

        srcFormat != PIX_FMT_RGB8 && srcFormat != PIX_FMT_BGR8 &&

        srcFormat != PIX_FMT_RGB4 && srcFormat != PIX_FMT_BGR4 &&

        srcFormat != PIX_FMT_RGB4_BYTE && srcFormat != PIX_FMT_BGR4_BYTE &&

        ((dstW >> c->chrDstHSubSample) <= (srcW >> 1) ||

         (flags & SWS_FAST_BILINEAR)))

        c->chrSrcHSubSample = 1;

    // Note the -((-x)>>y) is so that we always round toward +inf.

    c->chrSrcW = -((-srcW) >> c->chrSrcHSubSample);

    c->chrSrcH = -((-srcH) >> c->chrSrcVSubSample);

    c->chrDstW = -((-dstW) >> c->chrDstHSubSample);

    c->chrDstH = -((-dstH) >> c->chrDstVSubSample);

    /* unscaled special cases */

    if (unscaled && !usesHFilter && !usesVFilter &&

        (c->srcRange == c->dstRange || isAnyRGB(dstFormat))) {

        ff_get_unscaled_swscale(c);

        if (c->swScale) {

            if (flags & SWS_PRINT_INFO)

                av_log(c, AV_LOG_INFO,

                       "using unscaled %s -> %s special converter\n",

                       sws_format_name(srcFormat), sws_format_name(dstFormat));

            return 0;

        }

    }

    c->srcBpc = 1 + av_pix_fmt_descriptors[srcFormat].comp[0].depth_minus1;

    if (c->srcBpc < 8)

        c->srcBpc = 8;

    c->dstBpc = 1 + av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1;

    if (c->dstBpc < 8)

        c->dstBpc = 8;

    if (c->dstBpc == 16)

        dst_stride <<= 1;

    FF_ALLOC_OR_GOTO(c, c->formatConvBuffer,

                     (FFALIGN(srcW, 16) * 2 * FFALIGN(c->srcBpc, 8) >> 3) + 16,

                     fail);

    if (HAVE_MMXEXT && HAVE_INLINE_ASM && cpu_flags & AV_CPU_FLAG_MMXEXT &&

        c->srcBpc == 8 && c->dstBpc <= 10) {

        c->canMMX2BeUsed = (dstW >= srcW && (dstW & 31) == 0 &&

                            (srcW & 15) == 0) ? 1 : 0;

        if (!c->canMMX2BeUsed && dstW >= srcW && (srcW & 15) == 0

            && (flags & SWS_FAST_BILINEAR)) {

            if (flags & SWS_PRINT_INFO)

                av_log(c, AV_LOG_INFO,

                       "output width is not a multiple of 32 -> no MMX2 scaler\n");

        }

        if (usesHFilter)

            c->canMMX2BeUsed = 0;

    } else

        c->canMMX2BeUsed = 0;

    c->chrXInc = (((int64_t)c->chrSrcW << 16) + (c->chrDstW >> 1)) / c->chrDstW;

    c->chrYInc = (((int64_t)c->chrSrcH << 16) + (c->chrDstH >> 1)) / c->chrDstH;

    /* Match pixel 0 of the src to pixel 0 of dst and match pixel n-2 of src

     * to pixel n-2 of dst, but only for the FAST_BILINEAR mode otherwise do

     * correct scaling.

     * n-2 is the last chrominance sample available.

     * This is not perfect, but no one should notice the difference, the more

     * correct variant would be like the vertical one, but that would require

     * some special code for the first and last pixel */

    if (flags & SWS_FAST_BILINEAR) {

        if (c->canMMX2BeUsed) {

            c->lumXInc += 20;

            c->chrXInc += 20;

        }

        // we don't use the x86 asm scaler if MMX is available

        else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {

            c->lumXInc = ((int64_t)(srcW       - 2) << 16) / (dstW       - 2) - 20;

            c->chrXInc = ((int64_t)(c->chrSrcW - 2) << 16) / (c->chrDstW - 2) - 20;

        }

    }

    /* precalculate horizontal scaler filter coefficients */

    {

#if HAVE_MMXEXT_INLINE

// can't downscale !!!

        if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR)) {

            c->lumMmx2FilterCodeSize = initMMX2HScaler(dstW, c->lumXInc, NULL,

                                                       NULL, NULL, 8);

            c->chrMmx2FilterCodeSize = initMMX2HScaler(c->chrDstW, c->chrXInc,

                                                       NULL, NULL, NULL, 4);

#ifdef MAP_ANONYMOUS

            c->lumMmx2FilterCode = mmap(NULL, c->lumMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

            c->chrMmx2FilterCode = mmap(NULL, c->chrMmx2FilterCodeSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

#elif HAVE_VIRTUALALLOC

            c->lumMmx2FilterCode = VirtualAlloc(NULL, c->lumMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

            c->chrMmx2FilterCode = VirtualAlloc(NULL, c->chrMmx2FilterCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

#else

            c->lumMmx2FilterCode = av_malloc(c->lumMmx2FilterCodeSize);

            c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize);

#endif

            if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode)

                return AVERROR(ENOMEM);

            FF_ALLOCZ_OR_GOTO(c, c->hLumFilter,    (dstW           / 8 + 8) * sizeof(int16_t), fail);

            FF_ALLOCZ_OR_GOTO(c, c->hChrFilter,    (c->chrDstW     / 4 + 8) * sizeof(int16_t), fail);

            FF_ALLOCZ_OR_GOTO(c, c->hLumFilterPos, (dstW       / 2 / 8 + 8) * sizeof(int32_t), fail);

            FF_ALLOCZ_OR_GOTO(c, c->hChrFilterPos, (c->chrDstW / 2 / 4 + 8) * sizeof(int32_t), fail);

            initMMX2HScaler(dstW, c->lumXInc, c->lumMmx2FilterCode,

                            c->hLumFilter, c->hLumFilterPos, 8);

            initMMX2HScaler(c->chrDstW, c->chrXInc, c->chrMmx2FilterCode,

                            c->hChrFilter, c->hChrFilterPos, 4);

#ifdef MAP_ANONYMOUS

            mprotect(c->lumMmx2FilterCode, c->lumMmx2FilterCodeSize, PROT_EXEC | PROT_READ);

            mprotect(c->chrMmx2FilterCode, c->chrMmx2FilterCodeSize, PROT_EXEC | PROT_READ);

#endif

        } else

#endif /* HAVE_MMXEXT_INLINE */

        {

            const int filterAlign =

                (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 4 :

                (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :

                1;

            if (initFilter(&c->hLumFilter, &c->hLumFilterPos,

                           &c->hLumFilterSize, c->lumXInc,

                           srcW, dstW, filterAlign, 1 << 14,

                           (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,

                           cpu_flags, srcFilter->lumH, dstFilter->lumH,

                           c->param, 1) < 0)

                goto fail;

            if (initFilter(&c->hChrFilter, &c->hChrFilterPos,

                           &c->hChrFilterSize, c->chrXInc,

                           c->chrSrcW, c->chrDstW, filterAlign, 1 << 14,

                           (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,

                           cpu_flags, srcFilter->chrH, dstFilter->chrH,

                           c->param, 1) < 0)

                goto fail;

        }

    } // initialize horizontal stuff

    /* precalculate vertical scaler filter coefficients */

    {

        const int filterAlign =

            (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) ? 2 :

            (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC) ? 8 :

            1;

        if (initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,

                       c->lumYInc, srcH, dstH, filterAlign, (1 << 12),

                       (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags,

                       cpu_flags, srcFilter->lumV, dstFilter->lumV,

                       c->param, 0) < 0)

            goto fail;

        if (initFilter(&c->vChrFilter, &c->vChrFilterPos, &c->vChrFilterSize,

                       c->chrYInc, c->chrSrcH, c->chrDstH,

                       filterAlign, (1 << 12),

                       (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags,

                       cpu_flags, srcFilter->chrV, dstFilter->chrV,

                       c->param, 0) < 0)

            goto fail;

#if HAVE_ALTIVEC

        FF_ALLOC_OR_GOTO(c, c->vYCoeffsBank, sizeof(vector signed short) * c->vLumFilterSize * c->dstH,    fail);

        FF_ALLOC_OR_GOTO(c, c->vCCoeffsBank, sizeof(vector signed short) * c->vChrFilterSize * c->chrDstH, fail);

        for (i = 0; i < c->vLumFilterSize * c->dstH; i++) {

            int j;

            short *p = (short *)&c->vYCoeffsBank[i];

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

                p[j] = c->vLumFilter[i];

        }

        for (i = 0; i < c->vChrFilterSize * c->chrDstH; i++) {

            int j;

            short *p = (short *)&c->vCCoeffsBank[i];

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

                p[j] = c->vChrFilter[i];

        }

#endif

    }

    // calculate buffer sizes so that they won't run out while handling these damn slices

    c->vLumBufSize = c->vLumFilterSize;

    c->vChrBufSize = c->vChrFilterSize;

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

        int chrI      = (int64_t)i * c->chrDstH / dstH;

        int nextSlice = FFMAX(c->vLumFilterPos[i] + c->vLumFilterSize - 1,

                              ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)

                               << c->chrSrcVSubSample));

        nextSlice >>= c->chrSrcVSubSample;

        nextSlice <<= c->chrSrcVSubSample;

        if (c->vLumFilterPos[i] + c->vLumBufSize < nextSlice)

            c->vLumBufSize = nextSlice - c->vLumFilterPos[i];

        if (c->vChrFilterPos[chrI] + c->vChrBufSize <

            (nextSlice >> c->chrSrcVSubSample))

            c->vChrBufSize = (nextSlice >> c->chrSrcVSubSample) -

                             c->vChrFilterPos[chrI];

    }

    /* Allocate pixbufs (we use dynamic allocation because otherwise we would

     * need to allocate several megabytes to handle all possible cases) */

    FF_ALLOC_OR_GOTO(c, c->lumPixBuf,  c->vLumBufSize * 3 * sizeof(int16_t *), fail);

    FF_ALLOC_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);

    FF_ALLOC_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);

    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))

        FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);

    /* Note we need at least one pixel more at the end because of the MMX code

     * (just in case someone wants to replace the 4000/8000). */

    /* align at 16 bytes for AltiVec */

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

        FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i + c->vLumBufSize],

                          dst_stride + 16, fail);

        c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];

    }

    // 64 / (c->dstBpc & ~7) is the same as 16 / sizeof(scaling_intermediate)

    c->uv_off_px   = dst_stride_px + 64 / (c->dstBpc & ~7);

    c->uv_off_byte = dst_stride + 16;

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

        FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],

                         dst_stride * 2 + 32, fail);

        c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];

        c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]

                         = c->chrUPixBuf[i] + (dst_stride >> 1) + 8;

    }

    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)

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

            FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i + c->vLumBufSize],

                              dst_stride + 16, fail);

            c->alpPixBuf[i] = c->alpPixBuf[i + c->vLumBufSize];

        }

    // try to avoid drawing green stuff between the right end and the stride end

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

        memset(c->chrUPixBuf[i], 64, dst_stride * 2 + 1);

    assert(c->chrDstH <= dstH);

    if (flags & SWS_PRINT_INFO) {

        if (flags & SWS_FAST_BILINEAR)

            av_log(c, AV_LOG_INFO, "FAST_BILINEAR scaler, ");

        else if (flags & SWS_BILINEAR)

            av_log(c, AV_LOG_INFO, "BILINEAR scaler, ");

        else if (flags & SWS_BICUBIC)

            av_log(c, AV_LOG_INFO, "BICUBIC scaler, ");

        else if (flags & SWS_X)

            av_log(c, AV_LOG_INFO, "Experimental scaler, ");

        else if (flags & SWS_POINT)

            av_log(c, AV_LOG_INFO, "Nearest Neighbor / POINT scaler, ");

        else if (flags & SWS_AREA)

            av_log(c, AV_LOG_INFO, "Area Averaging scaler, ");

        else if (flags & SWS_BICUBLIN)

            av_log(c, AV_LOG_INFO, "luma BICUBIC / chroma BILINEAR scaler, ");

        else if (flags & SWS_GAUSS)

            av_log(c, AV_LOG_INFO, "Gaussian scaler, ");

        else if (flags & SWS_SINC)

            av_log(c, AV_LOG_INFO, "Sinc scaler, ");

        else if (flags & SWS_LANCZOS)

            av_log(c, AV_LOG_INFO, "Lanczos scaler, ");

        else if (flags & SWS_SPLINE)

            av_log(c, AV_LOG_INFO, "Bicubic spline scaler, ");

        else

            av_log(c, AV_LOG_INFO, "ehh flags invalid?! ");

        av_log(c, AV_LOG_INFO, "from %s to %s%s ",

               sws_format_name(srcFormat),

#ifdef DITHER1XBPP

               dstFormat == PIX_FMT_BGR555   || dstFormat == PIX_FMT_BGR565   ||

               dstFormat == PIX_FMT_RGB444BE || dstFormat == PIX_FMT_RGB444LE ||

               dstFormat == PIX_FMT_BGR444BE || dstFormat == PIX_FMT_BGR444LE ?

                                                             "dithered " : "",

#else

               "",

#endif

               sws_format_name(dstFormat));

        if (HAVE_MMXEXT && cpu_flags & AV_CPU_FLAG_MMXEXT)

            av_log(c, AV_LOG_INFO, "using MMX2\n");

        else if (HAVE_AMD3DNOW && cpu_flags & AV_CPU_FLAG_3DNOW)

            av_log(c, AV_LOG_INFO, "using 3DNOW\n");

        else if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX)

            av_log(c, AV_LOG_INFO, "using MMX\n");

        else if (HAVE_ALTIVEC && cpu_flags & AV_CPU_FLAG_ALTIVEC)

            av_log(c, AV_LOG_INFO, "using AltiVec\n");

        else

            av_log(c, AV_LOG_INFO, "using C\n");

        av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH);

        av_log(c, AV_LOG_DEBUG,

               "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",

               c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc);

        av_log(c, AV_LOG_DEBUG,

               "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n",

               c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH,

               c->chrXInc, c->chrYInc);

    }

    c->swScale = ff_getSwsFunc(c);

    return 0;

fail: // FIXME replace things by appropriate error codes

    return -1;

}


static int vsink_query_formats(AVFilterContext *ctx)

{

    BufferSinkContext *buf = ctx->priv;

    AVFilterFormats *formats = NULL;

    unsigned i;

    int ret;

    if (buf->pixel_fmts_size % sizeof(*buf->pixel_fmts)) {

        av_log(ctx, AV_LOG_ERROR, "Invalid size for format list\n");

        return AVERROR(EINVAL);

    }

    if (buf->pixel_fmts_size) {

        for (i = 0; i < NB_ITEMS(buf->pixel_fmts); i++)

            if ((ret = ff_add_format(&formats, buf->pixel_fmts[i])) < 0)

                return ret;

        ff_set_common_formats(ctx, formats);

    } else {

        ff_default_query_formats(ctx);

    }

    return 0;

}


av_cold void ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha)

{

    VP56Context *s = avctx->priv_data;

    int i;

    s->avctx = avctx;

    avctx->pix_fmt = has_alpha ? PIX_FMT_YUVA420P : PIX_FMT_YUV420P;

    if (avctx->idct_algo == FF_IDCT_AUTO)

        avctx->idct_algo = FF_IDCT_VP3;

    ff_dsputil_init(&s->dsp, avctx);

    ff_vp56dsp_init(&s->vp56dsp, avctx->codec->id);

    ff_init_scantable(s->dsp.idct_permutation, &s->scantable,ff_zigzag_direct);

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

        s->framep[i] = &s->frames[i];

    s->framep[VP56_FRAME_UNUSED] = s->framep[VP56_FRAME_GOLDEN];

    s->framep[VP56_FRAME_UNUSED2] = s->framep[VP56_FRAME_GOLDEN2];

    s->edge_emu_buffer_alloc = NULL;

    s->above_blocks = NULL;

    s->macroblocks = NULL;

    s->quantizer = -1;

    s->deblock_filtering = 1;

    s->filter = NULL;

    s->has_alpha = has_alpha;

    if (flip) {

        s->flip = -1;

        s->frbi = 2;

        s->srbi = 0;

    } else {

        s->flip = 1;

        s->frbi = 0;

        s->srbi = 2;

    }

}


static int sd_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)

{

    /* FIXME: Delete specified snapshot id.  */

    return 0;

}


static int rso_read_packet(AVFormatContext *s, AVPacket *pkt)

{

    int bps = av_get_bits_per_sample(s->streams[0]->codec->codec_id);

    int ret = av_get_packet(s->pb, pkt, BLOCK_SIZE * bps >> 3);

    if (ret < 0)

        return ret;

    pkt->stream_index = 0;

    /* note: we need to modify the packet size here to handle the last packet */

    pkt->size = ret;

    return 0;

}


static int vmd_read_header(AVFormatContext *s)

{

    VmdDemuxContext *vmd = s->priv_data;

    AVIOContext *pb = s->pb;

    AVStream *st = NULL, *vst;

    unsigned int toc_offset;

    unsigned char *raw_frame_table;

    int raw_frame_table_size;

    int64_t current_offset;

    int i, j;

    unsigned int total_frames;

    int64_t current_audio_pts = 0;

    unsigned char chunk[BYTES_PER_FRAME_RECORD];

    int num, den;

    int sound_buffers;

    /* fetch the main header, including the 2 header length bytes */

    avio_seek(pb, 0, SEEK_SET);

    if (avio_read(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE)

        return AVERROR(EIO);

    if(vmd->vmd_header[24] == 'i' && vmd->vmd_header[25] == 'v' && vmd->vmd_header[26] == '3')

        vmd->is_indeo3 = 1;

    else

        vmd->is_indeo3 = 0;

    /* start up the decoders */

    vst = avformat_new_stream(s, NULL);

    if (!vst)

        return AVERROR(ENOMEM);

    avpriv_set_pts_info(vst, 33, 1, 10);

    vmd->video_stream_index = vst->index;

    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;

    vst->codec->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO;

    vst->codec->codec_tag = 0;  /* no fourcc */

    vst->codec->width = AV_RL16(&vmd->vmd_header[12]);

    vst->codec->height = AV_RL16(&vmd->vmd_header[14]);

    if(vmd->is_indeo3 && vst->codec->width > 320){

        vst->codec->width >>= 1;

        vst->codec->height >>= 1;

    }

    vst->codec->extradata_size = VMD_HEADER_SIZE;

    vst->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);

    memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE);

    /* if sample rate is 0, assume no audio */

    vmd->sample_rate = AV_RL16(&vmd->vmd_header[804]);

    if (vmd->sample_rate) {

        st = avformat_new_stream(s, NULL);

        if (!st)

            return AVERROR(ENOMEM);

        vmd->audio_stream_index = st->index;

        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;

        st->codec->codec_id = AV_CODEC_ID_VMDAUDIO;

        st->codec->codec_tag = 0;  /* no fourcc */

        if (vmd->vmd_header[811] & 0x80) {

            st->codec->channels       = 2;

            st->codec->channel_layout = AV_CH_LAYOUT_STEREO;

        } else {

            st->codec->channels       = 1;

            st->codec->channel_layout = AV_CH_LAYOUT_MONO;

        }

        st->codec->sample_rate = vmd->sample_rate;

        st->codec->block_align = AV_RL16(&vmd->vmd_header[806]);

        if (st->codec->block_align & 0x8000) {

            st->codec->bits_per_coded_sample = 16;

            st->codec->block_align = -(st->codec->block_align - 0x10000);

        } else {

            st->codec->bits_per_coded_sample = 8;

        }

        st->codec->bit_rate = st->codec->sample_rate *

            st->codec->bits_per_coded_sample * st->codec->channels;

        /* calculate pts */

        num = st->codec->block_align;

        den = st->codec->sample_rate * st->codec->channels;

        av_reduce(&den, &num, den, num, (1UL<<31)-1);

        avpriv_set_pts_info(vst, 33, num, den);

        avpriv_set_pts_info(st, 33, num, den);

    }

    toc_offset = AV_RL32(&vmd->vmd_header[812]);

    vmd->frame_count = AV_RL16(&vmd->vmd_header[6]);

    vmd->frames_per_block = AV_RL16(&vmd->vmd_header[18]);

    avio_seek(pb, toc_offset, SEEK_SET);

    raw_frame_table = NULL;

    vmd->frame_table = NULL;

    sound_buffers = AV_RL16(&vmd->vmd_header[808]);

    raw_frame_table_size = vmd->frame_count * 6;

    if(vmd->frame_count * vmd->frames_per_block >= UINT_MAX / sizeof(vmd_frame) - sound_buffers){

        av_log(s, AV_LOG_ERROR, "vmd->frame_count * vmd->frames_per_block too large\n");

        return -1;

    }

    raw_frame_table = av_malloc(raw_frame_table_size);

    vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame));

    if (!raw_frame_table || !vmd->frame_table) {

        av_free(raw_frame_table);

        av_free(vmd->frame_table);

        return AVERROR(ENOMEM);

    }

    if (avio_read(pb, raw_frame_table, raw_frame_table_size) !=

        raw_frame_table_size) {

        av_free(raw_frame_table);

        av_free(vmd->frame_table);

        return AVERROR(EIO);

    }

    total_frames = 0;

    for (i = 0; i < vmd->frame_count; i++) {

        current_offset = AV_RL32(&raw_frame_table[6 * i + 2]);

        /* handle each entry in index block */

        for (j = 0; j < vmd->frames_per_block; j++) {

            int type;

            uint32_t size;

            avio_read(pb, chunk, BYTES_PER_FRAME_RECORD);

            type = chunk[0];

            size = AV_RL32(&chunk[2]);

            if(!size && type != 1)

                continue;

            switch(type) {

            case 1: /* Audio Chunk */

                if (!st) break;

                /* first audio chunk contains several audio buffers */

                vmd->frame_table[total_frames].frame_offset = current_offset;

                vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index;

                vmd->frame_table[total_frames].frame_size = size;

                memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);

                vmd->frame_table[total_frames].pts = current_audio_pts;

                total_frames++;

                if(!current_audio_pts)

                    current_audio_pts += sound_buffers - 1;

                else

                    current_audio_pts++;

                break;

            case 2: /* Video Chunk */

                vmd->frame_table[total_frames].frame_offset = current_offset;

                vmd->frame_table[total_frames].stream_index = vmd->video_stream_index;

                vmd->frame_table[total_frames].frame_size = size;

                memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);

                vmd->frame_table[total_frames].pts = i;

                total_frames++;

                break;

            }

            current_offset += size;

        }

    }

    av_free(raw_frame_table);

    vmd->current_frame = 0;

    vmd->frame_count = total_frames;

    return 0;

}


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

{

    struct timeval t1, t2;

    bool Cflag = false, qflag = false, vflag = false;

    bool Pflag = false, sflag = false, lflag = false, bflag = false;

    int c, cnt;

    char *buf;

    int64_t offset;

    int64_t count;

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

    int64_t total = 0;

    int pattern = 0;

    int64_t pattern_offset = 0, pattern_count = 0;

    while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {

        switch (c) {

        case 'b':

            bflag = true;

            break;

        case 'C':

            Cflag = true;

            break;

        case 'l':

            lflag = true;

            pattern_count = cvtnum(optarg);

            if (pattern_count < 0) {

                print_cvtnum_err(pattern_count, optarg);

                return 0;

            }

            break;

        case 'p':

            /* Ignored for backwards compatibility */

            break;

        case 'P':

            Pflag = true;

            pattern = parse_pattern(optarg);

            if (pattern < 0) {

                return 0;

            }

            break;

        case 'q':

            qflag = true;

            break;

        case 's':

            sflag = true;

            pattern_offset = cvtnum(optarg);

            if (pattern_offset < 0) {

                print_cvtnum_err(pattern_offset, optarg);

                return 0;

            }

            break;

        case 'v':

            vflag = true;

            break;

        default:

            return qemuio_command_usage(&read_cmd);

        }

    }

    if (optind != argc - 2) {

        return qemuio_command_usage(&read_cmd);

    }

    offset = cvtnum(argv[optind]);

    if (offset < 0) {

        print_cvtnum_err(offset, argv[optind]);

        return 0;

    }

    optind++;

    count = cvtnum(argv[optind]);

    if (count < 0) {

        print_cvtnum_err(count, argv[optind]);

        return 0;

    } else if (count > SIZE_MAX) {

        printf("length cannot exceed %" PRIu64 ", given %s\n",

               (uint64_t) SIZE_MAX, argv[optind]);

        return 0;

    }

    if (!Pflag && (lflag || sflag)) {

        return qemuio_command_usage(&read_cmd);

    }

    if (!lflag) {

        pattern_count = count - pattern_offset;

    }

    if ((pattern_count < 0) || (pattern_count + pattern_offset > count))  {

        printf("pattern verification range exceeds end of read data\n");

        return 0;

    }

    if (bflag) {

        if (offset & 0x1ff) {

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

                   offset);

            return 0;

        }

        if (count & 0x1ff) {

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

                   count);

            return 0;

        }

    }

    buf = qemu_io_alloc(blk, count, 0xab);

    gettimeofday(&t1, NULL);

    if (bflag) {

        cnt = do_load_vmstate(blk, buf, offset, count, &total);

    } else {

        cnt = do_pread(blk, buf, offset, count, &total);

    }

    gettimeofday(&t2, NULL);

    if (cnt < 0) {

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

        goto out;

    }

    if (Pflag) {

        void *cmp_buf = g_malloc(pattern_count);

        memset(cmp_buf, pattern, pattern_count);

        if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {

            printf("Pattern verification failed at offset %"

                   PRId64 ", %"PRId64" bytes\n",

                   offset + pattern_offset, pattern_count);

        }

        g_free(cmp_buf);

    }

    if (qflag) {

        goto out;

    }

    if (vflag) {

        dump_buffer(buf, offset, count);

    }

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

    t2 = tsub(t2, t1);

    print_report("read", &t2, offset, count, total, cnt, Cflag);

out:

    qemu_io_free(buf);

    return 0;

}


PPC_OP(subfze)

{

    T1 = ~T0;

    T0 = T1 + xer_ca;

    if (T0 < T1) {

        xer_ca = 1;

    } else {

        xer_ca = 0;

    }

    RETURN();

}


void ff_celp_lp_zero_synthesis_filterf(float *out,

                                       const float* filter_coeffs,

                                       const float* in,

                                       int buffer_length,

                                       int filter_length)

{

    int i,n;

    // Avoids a +1 in the inner loop.

    filter_length++;

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

        out[n] = in[n];

        for (i = 1; i < filter_length; i++)

            out[n] += filter_coeffs[i-1] * in[n-i];

    }

}


static int RENAME(epzs_motion_search2)(MpegEncContext * s,

                             int *mx_ptr, int *my_ptr,

                             int P[10][2], int pred_x, int pred_y,

                             uint8_t *src_data[3],

                             uint8_t *ref_data[3], int stride, int uvstride, int16_t (*last_mv)[2],

                             int ref_mv_scale, uint8_t * const mv_penalty)

{

    int best[2]={0, 0};

    int d, dmin;

    const int shift= 1+s->quarter_sample;

    uint32_t *map= s->me.map;

    int map_generation;

    const int penalty_factor= s->me.penalty_factor;

    const int size=0; //FIXME pass as arg

    const int h=8;

    const int ref_mv_stride= s->mb_stride;

    const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;

    me_cmp_func cmp, chroma_cmp;

    LOAD_COMMON

    cmp= s->dsp.me_cmp[size];

    chroma_cmp= s->dsp.me_cmp[size+1];

    map_generation= update_map_generation(s);

    dmin = 1000000;

//printf("%d %d %d %d //",xmin, ymin, xmax, ymax);

    /* first line */

    if (s->first_slice_line) {

	CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)

        CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,

                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)

        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)

    }else{

        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)

        //FIXME try some early stop

        if(dmin>64*2){

            CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)

            CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)

            CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)

            CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)

            CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,

                            (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)

        }

    }

    if(dmin>64*4){

        CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,

                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)

        if(s->end_mb_y == s->mb_height || s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line

            CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,

                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)

    }

    if(s->me.dia_size==-1)

        dmin= RENAME(funny_diamond_search)(s, best, dmin, src_data, ref_data, stride, uvstride,

                                   pred_x, pred_y, penalty_factor,

				   shift, map, map_generation, size, h, mv_penalty);

    else if(s->me.dia_size<-1)

        dmin= RENAME(sab_diamond_search)(s, best, dmin, src_data, ref_data, stride, uvstride,

                                   pred_x, pred_y, penalty_factor,

				   shift, map, map_generation, size, h, mv_penalty);

    else if(s->me.dia_size<2)

        dmin= RENAME(small_diamond_search)(s, best, dmin, src_data, ref_data, stride, uvstride,

                                   pred_x, pred_y, penalty_factor,

				   shift, map, map_generation, size, h, mv_penalty);

    else

        dmin= RENAME(var_diamond_search)(s, best, dmin, src_data, ref_data, stride, uvstride,

                                   pred_x, pred_y, penalty_factor,

				   shift, map, map_generation, size, h, mv_penalty);

    *mx_ptr= best[0];

    *my_ptr= best[1];

//    printf("%d %d %d \n", best[0], best[1], dmin);

    return dmin;

}


static int decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src,

                          int log2w, int log2h, int stride)

{

    const int index = size2index[log2h][log2w];

    const int h     = 1 << log2h;

    int code        = get_vlc2(&f->gb,

                               block_type_vlc[1 - (f->version > 1)][index].table,

                               BLOCK_TYPE_VLC_BITS, 1);

    uint16_t *start = f->last_frame_buffer;

    uint16_t *end   = start + stride * (f->avctx->height - h + 1) - (1 << log2w);

    int ret;

    int scale   = 1;

    unsigned dc = 0;

    if (code < 0 || code > 6 || log2w < 0)

        return AVERROR_INVALIDDATA;

    if (code == 1) {

        log2h--;

        if ((ret = decode_p_block(f, dst, src, log2w, log2h, stride)) < 0)

            return ret;

        return decode_p_block(f, dst + (stride << log2h),

                              src + (stride << log2h),

                              log2w, log2h, stride);

    } else if (code == 2) {

        log2w--;

        if ((ret = decode_p_block(f, dst , src, log2w, log2h, stride)) < 0)

            return ret;

        return decode_p_block(f, dst + (1 << log2w),

                              src + (1 << log2w),

                              log2w, log2h, stride);

    } else if (code == 6) {

        if (log2w) {

            dst[0]      = bytestream2_get_le16(&f->g2);

            dst[1]      = bytestream2_get_le16(&f->g2);

        } else {

            dst[0]      = bytestream2_get_le16(&f->g2);

            dst[stride] = bytestream2_get_le16(&f->g2);

        }

        return 0;

    }

    if (code == 0) {

        src  += f->mv[bytestream2_get_byte(&f->g)];

    } else if (code == 3 && f->version >= 2) {

        return 0;

    } else if (code == 4) {

        src  += f->mv[bytestream2_get_byte(&f->g)];

        dc    = bytestream2_get_le16(&f->g2);

    } else if (code == 5) {

        scale = 0;

        dc    = bytestream2_get_le16(&f->g2);

    }

    if (start > src || src > end) {

        av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");

        return AVERROR_INVALIDDATA;

    }

    mcdc(dst, src, log2w, h, stride, scale, dc);

    return 0;

}


static void achroma(WaveformContext *s, AVFrame *in, AVFrame *out,

                    int component, int intensity, int offset, int column)

{

    const int plane = s->desc->comp[component].plane;

    const int mirror = s->mirror;

    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];

    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];

    const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];

    const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];

    const int max = 255 - intensity;

    const int src_h = in->height;

    const int src_w = in->width;

    int x, y;

    if (column) {

        const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);

        const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);

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

            const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];

            const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];

            uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;

            uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;

            uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);

            uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);

            uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);

            uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);

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

                const int c1 = c1_data[x] - 128;

                const int c2 = c2_data[x] - 128;

                uint8_t *target;

                int p;

                for (p = 128 + c1; p < 128; p++) {

                    target = d1 + x + d1_signed_linesize * p;

                    update(target, max, 1);

                }

                for (p = 128 + c1 - 1; p > 128; p--) {

                    target = d1 + x + d1_signed_linesize * p;

                    update(target, max, 1);

                }

                for (p = 128 + c2; p < 128; p++) {

                    target = d2 + x + d2_signed_linesize * p;

                    update(target, max, 1);

                }

                for (p = 128 + c2 - 1; p > 128; p--) {

                    target = d2 + x + d2_signed_linesize * p;

                    update(target, max, 1);

                }

                c1_data += c1_linesize;

                c2_data += c2_linesize;

                d1_data += d1_linesize;

                d2_data += d2_linesize;

            }

        }

    } else {

        const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];

        const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];

        uint8_t *d0_data = out->data[plane] + offset;

        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;

        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;

        if (mirror) {

            d0_data += s->size - 1;

            d1_data += s->size - 1;

            d2_data += s->size - 1;

        }

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

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

                const int c1 = c1_data[x] - 128;

                const int c2 = c2_data[x] - 128;

                uint8_t *target;

                int p;

                for (p = 128 + c1; p < 128; p++) {

                    if (mirror)

                        target = d1_data - p;

                    else

                        target = d1_data + p;

                    update(target, max, 1);

                }

                for (p = 128 + 1; p < 128 + c1; p++) {

                    if (mirror)

                        target = d1_data - p;

                    else

                        target = d1_data + p;

                    update(target, max, 1);

                }

                for (p = 128 + c2; p < 128; p++) {

                    if (mirror)

                        target = d2_data - p;

                    else

                        target = d2_data + p;

                    update(target, max, 1);

                }

                for (p = 128 + 1; p < 128 + c2; p++) {

                    if (mirror)

                        target = d2_data - p;

                    else

                        target = d2_data + p;

                    update(target, max, 1);

                }

            }

            c1_data += c1_linesize;

            c2_data += c2_linesize;

            d1_data += d1_linesize;

            d2_data += d2_linesize;

        }

    }

    envelope(s, out, plane, (plane + 1) % s->ncomp);

    envelope(s, out, plane, (plane + 2) % s->ncomp);

}


static int flac_probe(AVProbeData *p)

{

    uint8_t *bufptr = p->buf;

    if(ff_id3v2_match(bufptr))

        bufptr += ff_id3v2_tag_len(bufptr);

    if(memcmp(bufptr, "fLaC", 4)) return 0;

    else                          return AVPROBE_SCORE_MAX / 2;

}


static av_always_inline void decode_dc_coeffs(GetBitContext *gb, DCTELEM *out,

                                              int blocks_per_slice)

{

    DCTELEM prev_dc;

    int code, i, sign;

    OPEN_READER(re, gb);

    DECODE_CODEWORD(code, FIRST_DC_CB);

    prev_dc = TOSIGNED(code);

    out[0] = prev_dc;

    out += 64; // dc coeff for the next block

    code = 5;

    sign = 0;

    for (i = 1; i < blocks_per_slice; i++, out += 64) {

        DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6)]);

        if(code) sign ^= -(code & 1);

        else     sign  = 0;

        prev_dc += (((code + 1) >> 1) ^ sign) - sign;

        out[0] = prev_dc;

    }

    CLOSE_READER(re, gb);

}


int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,

                          VdpGetProcAddress *get_proc, unsigned flags)

{

    VDPAUHWContext *hwctx;

    if (flags != 0)

        return AVERROR(EINVAL);

    if (av_reallocp(&avctx->hwaccel_context, sizeof(*hwctx)))

        return AVERROR(ENOMEM);

    hwctx = avctx->hwaccel_context;

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

    hwctx->context.decoder  = VDP_INVALID_HANDLE;

    hwctx->device           = device;

    hwctx->get_proc_address = get_proc;

    hwctx->reset            = 1;

    return 0;

}


static int decode_ref_pic_marking(H264Context *h){

    MpegEncContext * const s = &h->s;

    int i;

    if(h->nal_unit_type == NAL_IDR_SLICE){ //FIXME fields

        s->broken_link= get_bits1(&s->gb) -1;

        h->mmco[0].long_index= get_bits1(&s->gb) - 1; // current_long_term_idx

        if(h->mmco[0].long_index == -1)

            h->mmco_index= 0;

        else{

            h->mmco[0].opcode= MMCO_LONG;

            h->mmco_index= 1;

        }

    }else{

        if(get_bits1(&s->gb)){ // adaptive_ref_pic_marking_mode_flag

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

                MMCOOpcode opcode= get_ue_golomb(&s->gb);;

                h->mmco[i].opcode= opcode;

                if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){

                    h->mmco[i].short_frame_num= (h->frame_num - get_ue_golomb(&s->gb) - 1) & ((1<<h->sps.log2_max_frame_num)-1); //FIXME fields

/*                    if(h->mmco[i].short_frame_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_frame_num ] == NULL){

                        av_log(s->avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco);

                        return -1;

                    }*/

                }

                if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){

                    h->mmco[i].long_index= get_ue_golomb(&s->gb);

                    if(/*h->mmco[i].long_index >= h->long_ref_count || h->long_ref[ h->mmco[i].long_index ] == NULL*/ h->mmco[i].long_index >= 16){

                        av_log(h->s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode);

                        return -1;

                    }

                }

                if(opcode > MMCO_LONG){

                    av_log(h->s.avctx, AV_LOG_ERROR, "illegal memory management control operation %d\n", opcode);

                    return -1;

                }

                if(opcode == MMCO_END)

                    break;

            }

            h->mmco_index= i;

        }else{

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

            if(h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count){ //FIXME fields

                h->mmco[0].opcode= MMCO_SHORT2UNUSED;

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

                h->mmco_index= 1;

            }else

                h->mmco_index= 0;

        }

    }

    return 0;

}


static DeviceState *sbi_init(target_phys_addr_t addr, qemu_irq **parent_irq)

{

    DeviceState *dev;

    SysBusDevice *s;

    unsigned int i;

    dev = qdev_create(NULL, "sbi");

    qdev_init(dev);

    s = sysbus_from_qdev(dev);

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

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

    }

    sysbus_mmio_map(s, 0, addr);

    return dev;

}


void qdist_add(struct qdist *dist, double x, long count)

{

    struct qdist_entry *entry = NULL;

    if (dist->n) {

        struct qdist_entry e;

        e.x = x;

        entry = bsearch(&e, dist->entries, dist->n, sizeof(e), qdist_cmp);

    }

    if (entry) {

        entry->count += count;

        return;

    }

    if (unlikely(dist->n == dist->size)) {

        dist->size *= 2;

        dist->entries = g_realloc(dist->entries,

                                  sizeof(*dist->entries) * (dist->size));

    }

    dist->n++;

    entry = &dist->entries[dist->n - 1];

    entry->x = x;

    entry->count = count;

    qsort(dist->entries, dist->n, sizeof(*entry), qdist_cmp);

}


static void av_always_inline filter_mb_edgeh( uint8_t *pix, int stride, const int16_t bS[4], unsigned int qp, H264Context *h ) {

    const int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8);

    const unsigned int index_a = qp - qp_bd_offset + h->slice_alpha_c0_offset;

    const int alpha = alpha_table[index_a];

    const int beta  = beta_table[qp - qp_bd_offset + h->slice_beta_offset];

    if (alpha ==0 || beta == 0) return;

    if( bS[0] < 4 ) {

        int8_t tc[4];

        tc[0] = tc0_table[index_a][bS[0]];

        tc[1] = tc0_table[index_a][bS[1]];

        tc[2] = tc0_table[index_a][bS[2]];

        tc[3] = tc0_table[index_a][bS[3]];

        h->h264dsp.h264_v_loop_filter_luma(pix, stride, alpha, beta, tc);

    } else {

        h->h264dsp.h264_v_loop_filter_luma_intra(pix, stride, alpha, beta);

    }

}


static int decode_residual(H264Context *h, GetBitContext *gb, DCTELEM *block, int n, const uint8_t *scantable, int qp, int max_coeff){

    MpegEncContext * const s = &h->s;

    const uint16_t *qmul= dequant_coeff[qp];

    static const int coeff_token_table_index[17]= {0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3};

    int level[16], run[16];

    int suffix_length, zeros_left, coeff_num, coeff_token, total_coeff, i, trailing_ones;

    //FIXME put trailing_onex into the context

    if(n == CHROMA_DC_BLOCK_INDEX){

        coeff_token= get_vlc2(gb, chroma_dc_coeff_token_vlc.table, CHROMA_DC_COEFF_TOKEN_VLC_BITS, 1);

        total_coeff= coeff_token>>2;

    }else{

        if(n == LUMA_DC_BLOCK_INDEX){

            total_coeff= pred_non_zero_count(h, 0);

            coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2);

            total_coeff= coeff_token>>2;

        }else{

            total_coeff= pred_non_zero_count(h, n);

            coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2);

            total_coeff= coeff_token>>2;

            h->non_zero_count_cache[ scan8[n] ]= total_coeff;

        }

    }

    //FIXME set last_non_zero?

    if(total_coeff==0)

        return 0;

    trailing_ones= coeff_token&3;

    tprintf("trailing:%d, total:%d\n", trailing_ones, total_coeff);

    assert(total_coeff<=16);

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

        level[i]= 1 - 2*get_bits1(gb);

    }

    suffix_length= total_coeff > 10 && trailing_ones < 3;

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

        const int prefix= get_level_prefix(gb);

        int level_code, mask;

        if(prefix<14){ //FIXME try to build a large unified VLC table for all this

            if(suffix_length)

                level_code= (prefix<<suffix_length) + get_bits(gb, suffix_length); //part

            else

                level_code= (prefix<<suffix_length); //part

        }else if(prefix==14){

            if(suffix_length)

                level_code= (prefix<<suffix_length) + get_bits(gb, suffix_length); //part

            else

                level_code= prefix + get_bits(gb, 4); //part

        }else if(prefix==15){

            level_code= (prefix<<suffix_length) + get_bits(gb, 12); //part

            if(suffix_length==0) level_code+=15; //FIXME doesnt make (much)sense

        }else{

            av_log(h->s.avctx, AV_LOG_ERROR, "prefix too large at %d %d\n", s->mb_x, s->mb_y);

            return -1;

        }

        if(i==trailing_ones && i<3) level_code+= 2; //FIXME split first iteration

        mask= -(level_code&1);

        level[i]= (((2+level_code)>>1) ^ mask) - mask;

        if(suffix_length==0) suffix_length=1; //FIXME split first iteration

#if 1

        if(ABS(level[i]) > (3<<(suffix_length-1)) && suffix_length<6) suffix_length++;

#else

        if((2+level_code)>>1) > (3<<(suffix_length-1)) && suffix_length<6) suffix_length++;

        ? == prefix > 2 or sth

#endif

        tprintf("level: %d suffix_length:%d\n", level[i], suffix_length);

    }

    if(total_coeff == max_coeff)

        zeros_left=0;

    else{

        if(n == CHROMA_DC_BLOCK_INDEX)

            zeros_left= get_vlc2(gb, chroma_dc_total_zeros_vlc[ total_coeff-1 ].table, CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 1);

        else

            zeros_left= get_vlc2(gb, total_zeros_vlc[ total_coeff-1 ].table, TOTAL_ZEROS_VLC_BITS, 1);

    }

    for(i=0; i<total_coeff-1; i++){

        if(zeros_left <=0)

            break;

        else if(zeros_left < 7){

            run[i]= get_vlc2(gb, run_vlc[zeros_left-1].table, RUN_VLC_BITS, 1);

        }else{

            run[i]= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2);

        }

        zeros_left -= run[i];

    }

    if(zeros_left<0){

        av_log(h->s.avctx, AV_LOG_ERROR, "negative number of zero coeffs at %d %d\n", s->mb_x, s->mb_y);

        return -1;

    }

    for(; i<total_coeff-1; i++){

        run[i]= 0;

    }

    run[i]= zeros_left;

    coeff_num=-1;

    if(n > 24){

        for(i=total_coeff-1; i>=0; i--){ //FIXME merge into rundecode?

            int j;

            coeff_num += run[i] + 1; //FIXME add 1 earlier ?

            j= scantable[ coeff_num ];

            block[j]= level[i];

        }

    }else{

        for(i=total_coeff-1; i>=0; i--){ //FIXME merge into  rundecode?

            int j;

            coeff_num += run[i] + 1; //FIXME add 1 earlier ?

            j= scantable[ coeff_num ];

            block[j]= level[i] * qmul[j];

//            printf("%d %d  ", block[j], qmul[j]);

        }

    }

    return 0;

}


static void spapr_phb_vfio_finish_realize(sPAPRPHBState *sphb, Error **errp)

{

    sPAPRPHBVFIOState *svphb = SPAPR_PCI_VFIO_HOST_BRIDGE(sphb);

    struct vfio_iommu_spapr_tce_info info = { .argsz = sizeof(info) };

    int ret;

    sPAPRTCETable *tcet;

    uint32_t liobn = svphb->phb.dma_liobn;

    if (svphb->iommugroupid == -1) {

        error_setg(errp, "Wrong IOMMU group ID %d", svphb->iommugroupid);

        return;

    }

    ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid,

                               VFIO_CHECK_EXTENSION,

                               (void *) VFIO_SPAPR_TCE_IOMMU);

    if (ret != 1) {

        error_setg_errno(errp, -ret,

                         "spapr-vfio: SPAPR extension is not supported");

        return;

    }

    ret = vfio_container_ioctl(&svphb->phb.iommu_as, svphb->iommugroupid,

                               VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info);

    if (ret) {

        error_setg_errno(errp, -ret,

                         "spapr-vfio: get info from container failed");

        return;

    }

    tcet = spapr_tce_new_table(DEVICE(sphb), liobn, info.dma32_window_start,

                               SPAPR_TCE_PAGE_SHIFT,

                               info.dma32_window_size >> SPAPR_TCE_PAGE_SHIFT,

                               true);

    if (!tcet) {

        error_setg(errp, "spapr-vfio: failed to create VFIO TCE table");

        return;

    }

    /* Register default 32bit DMA window */

    memory_region_add_subregion(&sphb->iommu_root, tcet->bus_offset,

                                spapr_tce_get_iommu(tcet));

}


static int coroutine_fn bdrv_mirror_top_flush(BlockDriverState *bs)

{

    return bdrv_co_flush(bs->backing->bs);


static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)

{

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

    MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;

    int entries, i;

    print_atom("stss", atom);

    get_byte(pb); /* version */

    get_byte(pb); get_byte(pb); get_byte(pb); /* flags */

    entries = get_be32(pb);

    sc->keyframe_count = entries;

#ifdef DEBUG

    av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);

#endif

    sc->keyframes = (long*) av_malloc(entries * sizeof(long));

    if (!sc->keyframes)

        return -1;

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

        sc->keyframes[i] = get_be32(pb);

#ifdef DEBUG

/*        av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */

#endif

    }

    return 0;

}


static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
    ConcatContext *cat = avf->priv_data;
    int ret;
    int64_t delta;
    while (1) {
        if ((ret = av_read_frame(cat->avf, pkt)) != AVERROR_EOF ||
            (ret = open_next_file(avf)) < 0)
            break;
    }
    delta = av_rescale_q(cat->cur_file->start_time - cat->avf->start_time,
                         AV_TIME_BASE_Q,
                         cat->avf->streams[pkt->stream_index]->time_base);
    if (pkt->pts != AV_NOPTS_VALUE)
        pkt->pts += delta;
    if (pkt->dts != AV_NOPTS_VALUE)
        pkt->dts += delta;
}


static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)

{

    BDRVQcowState *s = bs->opaque;

    int ret;

    qemu_co_mutex_lock(&s->lock);

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

    if (ret < 0) {

        qemu_co_mutex_unlock(&s->lock);

        return ret;

    }

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

    if (ret < 0) {

        qemu_co_mutex_unlock(&s->lock);

        return ret;

    }

    qemu_co_mutex_unlock(&s->lock);

    return 0;

}


static inline void RENAME(rgb24ToY)(uint8_t *dst, const uint8_t *src, int width, uint32_t *unused)

{

#if COMPILE_TEMPLATE_MMX

    RENAME(bgr24ToY_mmx)(dst, src, width, PIX_FMT_RGB24);

#else

    int i;

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

        int r= src[i*3+0];

        int g= src[i*3+1];

        int b= src[i*3+2];

        dst[i]= ((RY*r + GY*g + BY*b + (33<<(RGB2YUV_SHIFT-1)))>>RGB2YUV_SHIFT);

    }

#endif

}


static inline void RENAME(rgb16to32)(const uint8_t *src, uint8_t *dst, int src_size)

{

    const uint16_t *end;

    const uint16_t *mm_end;

    uint8_t *d = dst;

    const uint16_t *s = (const uint16_t*)src;

    end = s + src_size/2;

    __asm__ volatile(PREFETCH"    %0"::"m"(*s):"memory");

    __asm__ volatile("pxor    %%mm7,%%mm7    \n\t":::"memory");

    __asm__ volatile("pcmpeqd %%mm6,%%mm6    \n\t":::"memory");

    mm_end = end - 3;

    while (s < mm_end) {

        __asm__ volatile(

            PREFETCH"    32%1           \n\t"

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

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

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

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

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

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

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

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

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

            PACK_RGB32

            :"=m"(*d)

            :"m"(*s),"m"(mask16b),"m"(mask16g),"m"(mask16r)

            :"memory");

        d += 16;

        s += 4;

    }

    __asm__ volatile(SFENCE:::"memory");

    __asm__ volatile(EMMS:::"memory");

    while (s < end) {

        register uint16_t bgr;

        bgr = *s++;

        *d++ = (bgr&0x1F)<<3;

        *d++ = (bgr&0x7E0)>>3;

        *d++ = (bgr&0xF800)>>8;

        *d++ = 255;

    }

}


void helper_sysret(CPUX86State *env, int dflag)

{

    int cpl, selector;

    if (!(env->efer & MSR_EFER_SCE)) {

        raise_exception_err(env, EXCP06_ILLOP, 0);

    }

    cpl = env->hflags & HF_CPL_MASK;

    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {

        raise_exception_err(env, EXCP0D_GPF, 0);

    }

    selector = (env->star >> 48) & 0xffff;

    if (env->hflags & HF_LMA_MASK) {

        cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK

                        | ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |

                        NT_MASK);

        if (dflag == 2) {

            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,

                                   0, 0xffffffff,

                                   DESC_G_MASK | DESC_P_MASK |

                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |

                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK |

                                   DESC_L_MASK);

            env->eip = env->regs[R_ECX];

        } else {

            cpu_x86_load_seg_cache(env, R_CS, selector | 3,

                                   0, 0xffffffff,

                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |

                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);

            env->eip = (uint32_t)env->regs[R_ECX];

        }

        cpu_x86_load_seg_cache(env, R_SS, selector + 8,

                               0, 0xffffffff,

                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |

                               DESC_W_MASK | DESC_A_MASK);

    } else {

        env->eflags |= IF_MASK;

        cpu_x86_load_seg_cache(env, R_CS, selector | 3,

                               0, 0xffffffff,

                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |

                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);

        env->eip = (uint32_t)env->regs[R_ECX];

        cpu_x86_load_seg_cache(env, R_SS, selector + 8,

                               0, 0xffffffff,

                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |

                               DESC_W_MASK | DESC_A_MASK);

    }

}


static av_cold int adx_encode_init(AVCodecContext *avctx)

{

    ADXContext *c = avctx->priv_data;

    if (avctx->channels > 2)

        return -1;

    avctx->frame_size = 32;

    avctx->coded_frame = avcodec_alloc_frame();

    avctx->coded_frame->key_frame = 1;

    /* the cutoff can be adjusted, but this seems to work pretty well */

    c->cutoff = 500;

    ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff);

    return 0;

}


static int mpegps_read_header(AVFormatContext *s,

                              AVFormatParameters *ap)

{

    MpegDemuxContext *m = s->priv_data;

    uint8_t buffer[8192];

    char *p;

    m->header_state = 0xff;

    s->ctx_flags |= AVFMTCTX_NOHEADER;

    get_buffer(&s->pb, buffer, sizeof(buffer));

    if ((p=memchr(buffer, 'S', sizeof(buffer))))

        if (!memcmp(p, "Sofdec", 6))

            m->sofdec = 1;

    url_fseek(&s->pb, -sizeof(buffer), SEEK_CUR);

    /* no need to do more */

    return 0;

}


int get_frame_filename(char *buf, int buf_size,

                       const char *path, int number)

{

    const char *p;

    char *q, buf1[20];

    int nd, len, c, percentd_found;

    q = buf;

    p = path;

    percentd_found = 0;

    for(;;) {

        c = *p++;

        if (c == '\0')

            break;

        if (c == '%') {

            do {

                nd = 0;

                while (isdigit(*p)) {

                    nd = nd * 10 + *p++ - '0';

                }

                c = *p++;

                if (c == '*' && nd > 0) {

                    // The nd field is actually the modulus

                    number = number % nd;

                    c = *p++;

                    nd = 0;

                }

            } while (isdigit(c));

            switch(c) {

            case '%':

                goto addchar;

            case 'd':

                if (percentd_found)

                    goto fail;

                percentd_found = 1;

                snprintf(buf1, sizeof(buf1), "%0*d", nd, number);

                len = strlen(buf1);

                if ((q - buf + len) > buf_size - 1)

                    goto fail;

                memcpy(q, buf1, len);

                q += len;

                break;

            default:

                goto fail;

            }

        } else {

        addchar:

            if ((q - buf) < buf_size - 1)

                *q++ = c;

        }

    }

    if (!percentd_found)

        goto fail;

    *q = '\0';

    return 0;

 fail:

    *q = '\0';

    return -1;

}


static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band, IVITile *tile,

                             AVCodecContext *avctx)

{

    int         mbn, blk, num_blocks, num_coeffs, blk_size, scan_pos, run, val,

                pos, is_intra, mc_type = 0, mv_x, mv_y, col_mask;

    uint8_t     col_flags[8];

    int32_t     prev_dc, trvec[64];

    uint32_t    cbp, sym, lo, hi, quant, buf_offs, q;

    IVIMbInfo   *mb;

    RVMapDesc   *rvmap = band->rv_map;

    void (*mc_with_delta_func)(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type);

    void (*mc_no_delta_func)  (int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type);

    const uint16_t  *base_tab;

    const uint8_t   *scale_tab;

    prev_dc = 0; /* init intra prediction for the DC coefficient */

    blk_size   = band->blk_size;

    col_mask   = blk_size - 1; /* column mask for tracking non-zero coeffs */

    num_blocks = (band->mb_size != blk_size) ? 4 : 1; /* number of blocks per mb */

    num_coeffs = blk_size * blk_size;

    if (blk_size == 8) {

        mc_with_delta_func = ff_ivi_mc_8x8_delta;

        mc_no_delta_func   = ff_ivi_mc_8x8_no_delta;

    } else {

        mc_with_delta_func = ff_ivi_mc_4x4_delta;

        mc_no_delta_func   = ff_ivi_mc_4x4_no_delta;

    }

    for (mbn = 0, mb = tile->mbs; mbn < tile->num_MBs; mb++, mbn++) {

        is_intra = !mb->type;

        cbp      = mb->cbp;

        buf_offs = mb->buf_offs;

        quant = av_clip(band->glob_quant + mb->q_delta, 0, 23);

        base_tab  = is_intra ? band->intra_base  : band->inter_base;

        scale_tab = is_intra ? band->intra_scale : band->inter_scale;

        if (scale_tab)

            quant = scale_tab[quant];

        if (!is_intra) {

            mv_x = mb->mv_x;

            mv_y = mb->mv_y;

            if (band->is_halfpel) {

                mc_type = ((mv_y & 1) << 1) | (mv_x & 1);

                mv_x >>= 1;

                mv_y >>= 1; /* convert halfpel vectors into fullpel ones */

            }

            if (mb->type) {

                int dmv_x, dmv_y, cx, cy;

                dmv_x = mb->mv_x >> band->is_halfpel;

                dmv_y = mb->mv_y >> band->is_halfpel;

                cx    = mb->mv_x &  band->is_halfpel;

                cy    = mb->mv_y &  band->is_halfpel;

                if (   mb->xpos + dmv_x < 0

                    || mb->xpos + dmv_x + band->mb_size + cx > band->pitch

                    || mb->ypos + dmv_y < 0

                    || mb->ypos + dmv_y + band->mb_size + cy > band->aheight) {

                    return AVERROR_INVALIDDATA;

                }

            }

        }

        for (blk = 0; blk < num_blocks; blk++) {

            /* adjust block position in the buffer according to its number */

            if (blk & 1) {

                buf_offs += blk_size;

            } else if (blk == 2) {

                buf_offs -= blk_size;

                buf_offs += blk_size * band->pitch;

            }

            if (cbp & 1) { /* block coded ? */

                if (!band->scan) {

                    av_log(avctx, AV_LOG_ERROR, "Scan pattern is not set.\n");

                    return AVERROR_INVALIDDATA;

                }

                scan_pos = -1;

                memset(trvec, 0, num_coeffs*sizeof(trvec[0])); /* zero transform vector */

                memset(col_flags, 0, sizeof(col_flags));      /* zero column flags */

                while (scan_pos <= num_coeffs) {

                    sym = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1);

                    if (sym == rvmap->eob_sym)

                        break; /* End of block */

                    if (sym == rvmap->esc_sym) { /* Escape - run/val explicitly coded using 3 vlc codes */

                        run = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1) + 1;

                        lo  = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1);

                        hi  = get_vlc2(gb, band->blk_vlc.tab->table, IVI_VLC_BITS, 1);

                        val = IVI_TOSIGNED((hi << 6) | lo); /* merge them and convert into signed val */

                    } else {

                        if (sym >= 256U) {

                            av_log(avctx, AV_LOG_ERROR, "Invalid sym encountered: %d.\n", sym);

                            return -1;

                        }

                        run = rvmap->runtab[sym];

                        val = rvmap->valtab[sym];

                    }

                    /* de-zigzag and dequantize */

                    scan_pos += run;

                    if (scan_pos >= (unsigned)num_coeffs)

                        break;

                    pos = band->scan[scan_pos];

                    if (!val)

                        av_dlog(avctx, "Val = 0 encountered!\n");

                    q = (base_tab[pos] * quant) >> 9;

                    if (q > 1)

                        val = val * q + FFSIGN(val) * (((q ^ 1) - 1) >> 1);

                    trvec[pos] = val;

                    col_flags[pos & col_mask] |= !!val; /* track columns containing non-zero coeffs */

                }// while

                if (scan_pos >= num_coeffs && sym != rvmap->eob_sym)

                    return -1; /* corrupt block data */

                /* undoing DC coeff prediction for intra-blocks */

                if (is_intra && band->is_2d_trans) {

                    prev_dc      += trvec[0];

                    trvec[0]      = prev_dc;

                    col_flags[0] |= !!prev_dc;

                }

                if(band->transform_size > band->blk_size){

                    av_log(NULL, AV_LOG_ERROR, "Too large transform\n");

                    return AVERROR_INVALIDDATA;

                }

                /* apply inverse transform */

                band->inv_transform(trvec, band->buf + buf_offs,

                                    band->pitch, col_flags);

                /* apply motion compensation */

                if (!is_intra)

                    mc_with_delta_func(band->buf + buf_offs,

                                       band->ref_buf + buf_offs + mv_y * band->pitch + mv_x,

                                       band->pitch, mc_type);

            } else {

                /* block not coded */

                /* for intra blocks apply the dc slant transform */

                /* for inter - perform the motion compensation without delta */

                if (is_intra) {

                    band->dc_transform(&prev_dc, band->buf + buf_offs,

                                       band->pitch, blk_size);

                } else

                    mc_no_delta_func(band->buf + buf_offs,

                                     band->ref_buf + buf_offs + mv_y * band->pitch + mv_x,

                                     band->pitch, mc_type);

            }

            cbp >>= 1;

        }// for blk

    }// for mbn

    align_get_bits(gb);

    return 0;

}


static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,

                                    int is_write, sigset_t *old_set)

{

    CPUState *cpu;

    CPUClass *cc;

    int ret;

#if defined(DEBUG_SIGNAL)

    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",

           pc, address, is_write, *(unsigned long *)old_set);

#endif

    /* XXX: locking issue */

    if (is_write && h2g_valid(address)) {

        switch (page_unprotect(h2g(address), pc)) {

        case 0:

            /* Fault not caused by a page marked unwritable to protect

             * cached translations, must be the guest binary's problem

             */

            break;

        case 1:

            /* Fault caused by protection of cached translation; TBs

             * invalidated, so resume execution

             */

            return 1;

        case 2:

            /* Fault caused by protection of cached translation, and the

             * currently executing TB was modified and must be exited

             * immediately.

             */

            cpu_exit_tb_from_sighandler(current_cpu, old_set);

            g_assert_not_reached();

        default:

            g_assert_not_reached();

        }

    }

    /* Convert forcefully to guest address space, invalid addresses

       are still valid segv ones */

    address = h2g_nocheck(address);

    cpu = current_cpu;

    cc = CPU_GET_CLASS(cpu);

    /* see if it is an MMU fault */

    g_assert(cc->handle_mmu_fault);

    ret = cc->handle_mmu_fault(cpu, address, is_write, MMU_USER_IDX);

    if (ret < 0) {

        return 0; /* not an MMU fault */

    }

    if (ret == 0) {

        return 1; /* the MMU fault was handled without causing real CPU fault */

    }

    /* Now we have a real cpu fault.  Since this is the exact location of

     * the exception, we must undo the adjustment done by cpu_restore_state

     * for handling call return addresses.  */

    cpu_restore_state(cpu, pc + GETPC_ADJ);

    sigprocmask(SIG_SETMASK, old_set, NULL);

    cpu_loop_exit(cpu);

    /* never comes here */

    return 1;

}


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

{

    bool *v = pv;

    qemu_put_byte(f, *v);

}


static void uhci_frame_timer(void *opaque)

{

    UHCIState *s = opaque;

    /* prepare the timer for the next frame */

    s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);

    s->frame_bytes = 0;

    s->completions_only = false;

    qemu_bh_cancel(s->bh);

    if (!(s->cmd & UHCI_CMD_RS)) {

        /* Full stop */

        trace_usb_uhci_schedule_stop();

        qemu_del_timer(s->frame_timer);

        uhci_async_cancel_all(s);

        /* set hchalted bit in status - UHCI11D 2.1.2 */

        s->status |= UHCI_STS_HCHALTED;

        return;

    }

    /* Process the current frame */

    trace_usb_uhci_frame_start(s->frnum);

    uhci_async_validate_begin(s);

    uhci_process_frame(s);

    uhci_async_validate_end(s);

    /* The uhci spec says frnum reflects the frame currently being processed,

     * and the guest must look at frnum - 1 on interrupt, so inc frnum now */

    s->frnum = (s->frnum + 1) & 0x7ff;

    /* Complete the previous frame */

    if (s->pending_int_mask) {

        s->status2 |= s->pending_int_mask;

        s->status  |= UHCI_STS_USBINT;

        uhci_update_irq(s);

    }

    s->pending_int_mask = 0;

    qemu_mod_timer(s->frame_timer, s->expire_time);

}


static TCGv gen_vfp_mrs(void)

{

    TCGv tmp = new_tmp();

    tcg_gen_mov_i32(tmp, cpu_F0s);

    return tmp;

}


static int epzs_motion_search(MpegEncContext * s,

                             int *mx_ptr, int *my_ptr,

                             int P[5][2], int pred_x, int pred_y,

                             int xmin, int ymin, int xmax, int ymax)

{

    int best[2]={0, 0};

    int d, dmin;

    UINT8 *new_pic, *old_pic;

    const int pic_stride= s->linesize;

    const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;

    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame

    int quant= s->qscale; // qscale of the prev frame

    const int shift= 1+s->quarter_sample;

    new_pic = s->new_picture[0] + pic_xy;

    old_pic = s->last_picture[0] + pic_xy;

//printf("%d %d %d %d\n", xmin, ymin, xmax, ymax);

    dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);

    if(dmin<Z_THRESHOLD){

        *mx_ptr= 0;

        *my_ptr= 0;

//printf("Z");

        return dmin;

    }

    /* first line */

    if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {

        CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)

    }else{

        CHECK_MV(P[4][0]>>shift, P[4][1]>>shift)

        if(dmin<Z_THRESHOLD){

            *mx_ptr= P[4][0]>>shift;

            *my_ptr= P[4][1]>>shift;

//printf("M\n");

            return dmin;

        }

        CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)

        CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)

        CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)

    }

    CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)

    dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride,

                               pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);

    *mx_ptr= best[0];

    *my_ptr= best[1];

//    printf("%d %d %d \n", best[0], best[1], dmin);

    return dmin;

}


void acpi_build(AcpiBuildTables *tables, MachineState *machine)

{

    PCMachineState *pcms = PC_MACHINE(machine);

    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);

    GArray *table_offsets;

    unsigned facs, dsdt, rsdt, fadt;

    AcpiPmInfo pm;

    AcpiMiscInfo misc;

    AcpiMcfgInfo mcfg;

    Range pci_hole, pci_hole64;

    uint8_t *u;

    size_t aml_len = 0;

    GArray *tables_blob = tables->table_data;

    AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };

    acpi_get_pm_info(&pm);

    acpi_get_misc_info(&misc);

    acpi_get_pci_holes(&pci_hole, &pci_hole64);

    acpi_get_slic_oem(&slic_oem);

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

                                        sizeof(uint32_t));

    ACPI_BUILD_DPRINTF("init ACPI tables\n");

    bios_linker_loader_alloc(tables->linker,

                             ACPI_BUILD_TABLE_FILE, tables_blob,

                             64 /* Ensure FACS is aligned */,

                             false /* high memory */);

    /*

     * FACS is pointed to by FADT.

     * We place it first since it's the only table that has alignment

     * requirements.

     */

    facs = tables_blob->len;

    build_facs(tables_blob, tables->linker);

    /* DSDT is pointed to by FADT */

    dsdt = tables_blob->len;

    build_dsdt(tables_blob, tables->linker, &pm, &misc,

               &pci_hole, &pci_hole64, machine);

    /* Count the size of the DSDT and SSDT, we will need it for legacy

     * sizing of ACPI tables.

     */

    aml_len += tables_blob->len - dsdt;

    /* ACPI tables pointed to by RSDT */

    fadt = tables_blob->len;

    acpi_add_table(table_offsets, tables_blob);

    build_fadt(tables_blob, tables->linker, &pm, facs, dsdt,

               slic_oem.id, slic_oem.table_id);

    aml_len += tables_blob->len - fadt;

    acpi_add_table(table_offsets, tables_blob);

    build_madt(tables_blob, tables->linker, pcms);

    if (misc.has_hpet) {

        acpi_add_table(table_offsets, tables_blob);

        build_hpet(tables_blob, tables->linker);

    }

    if (misc.tpm_version != TPM_VERSION_UNSPEC) {

        acpi_add_table(table_offsets, tables_blob);

        build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog);

        if (misc.tpm_version == TPM_VERSION_2_0) {

            acpi_add_table(table_offsets, tables_blob);

            build_tpm2(tables_blob, tables->linker);

        }

    }

    if (pcms->numa_nodes) {

        acpi_add_table(table_offsets, tables_blob);

        build_srat(tables_blob, tables->linker, machine);

    }

    if (acpi_get_mcfg(&mcfg)) {

        acpi_add_table(table_offsets, tables_blob);

        build_mcfg_q35(tables_blob, tables->linker, &mcfg);

    }

    if (x86_iommu_get_default()) {

        IommuType IOMMUType = x86_iommu_get_type();

        if (IOMMUType == TYPE_AMD) {

            acpi_add_table(table_offsets, tables_blob);

            build_amd_iommu(tables_blob, tables->linker);

        } else if (IOMMUType == TYPE_INTEL) {

            acpi_add_table(table_offsets, tables_blob);

            build_dmar_q35(tables_blob, tables->linker);

        }

    }

    if (pcms->acpi_nvdimm_state.is_enabled) {

        nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,

                          pcms->acpi_nvdimm_state.dsm_mem, machine->ram_slots);

    }

    /* Add tables supplied by user (if any) */

    for (u = acpi_table_first(); u; u = acpi_table_next(u)) {

        unsigned len = acpi_table_len(u);

        acpi_add_table(table_offsets, tables_blob);

        g_array_append_vals(tables_blob, u, len);

    }

    /* RSDT is pointed to by RSDP */

    rsdt = tables_blob->len;

    build_rsdt(tables_blob, tables->linker, table_offsets,

               slic_oem.id, slic_oem.table_id);

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

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

    /* We'll expose it all to Guest so we want to reduce

     * chance of size changes.

     *

     * We used to align the tables to 4k, but of course this would

     * too simple to be enough.  4k turned out to be too small an

     * alignment very soon, and in fact it is almost impossible to

     * keep the table size stable for all (max_cpus, max_memory_slots)

     * combinations.  So the table size is always 64k for pc-i440fx-2.1

     * and we give an error if the table grows beyond that limit.

     *

     * We still have the problem of migrating from "-M pc-i440fx-2.0".  For

     * that, we exploit the fact that QEMU 2.1 generates _smaller_ tables

     * than 2.0 and we can always pad the smaller tables with zeros.  We can

     * then use the exact size of the 2.0 tables.

     *

     * All this is for PIIX4, since QEMU 2.0 didn't support Q35 migration.

     */

    if (pcmc->legacy_acpi_table_size) {

        /* Subtracting aml_len gives the size of fixed tables.  Then add the

         * size of the PIIX4 DSDT/SSDT in QEMU 2.0.

         */

        int legacy_aml_len =

            pcmc->legacy_acpi_table_size +

            ACPI_BUILD_LEGACY_CPU_AML_SIZE * max_cpus;

        int legacy_table_size =

            ROUND_UP(tables_blob->len - aml_len + legacy_aml_len,

                     ACPI_BUILD_ALIGN_SIZE);

        if (tables_blob->len > legacy_table_size) {

            /* Should happen only with PCI bridges and -M pc-i440fx-2.0.  */

            error_report("Warning: migration may not work.");

        }

        g_array_set_size(tables_blob, legacy_table_size);

    } else {

        /* Make sure we have a buffer in case we need to resize the tables. */

        if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {

            /* As of QEMU 2.1, this fires with 160 VCPUs and 255 memory slots.  */

            error_report("Warning: ACPI tables are larger than 64k.");

            error_report("Warning: migration may not work.");

            error_report("Warning: please remove CPUs, NUMA nodes, "

                         "memory slots or PCI bridges.");

        }

        acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);

    }

    acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE);

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

    g_array_free(table_offsets, true);

}


void ff_snow_horizontal_compose97i_sse2(DWTELEM *b, int width){

    const int w2= (width+1)>>1;

    // SSE2 code runs faster with pointers aligned on a 32-byte boundary.

    DWTELEM temp_buf[(width>>1) + 4];

    DWTELEM * const temp = temp_buf + 4 - (((int)temp_buf & 0xF) >> 2);

    const int w_l= (width>>1);

    const int w_r= w2 - 1;

    int i;

    { // Lift 0

        DWTELEM * const ref = b + w2 - 1;

        DWTELEM b_0 = b[0]; //By allowing the first entry in b[0] to be calculated twice

        // (the first time erroneously), we allow the SSE2 code to run an extra pass.

        // The savings in code and time are well worth having to store this value and

        // calculate b[0] correctly afterwards.

        i = 0;

        asm volatile(

            "pcmpeqd   %%xmm7, %%xmm7         \n\t"

            "pslld        $31, %%xmm7         \n\t"

            "psrld        $29, %%xmm7         \n\t"

        ::);

        for(; i<w_l-7; i+=8){

            asm volatile(

                "movdqu   (%1), %%xmm1        \n\t"

                "movdqu 16(%1), %%xmm5        \n\t"

                "movdqu  4(%1), %%xmm2        \n\t"

                "movdqu 20(%1), %%xmm6        \n\t"

                "paddd  %%xmm1, %%xmm2        \n\t"

                "paddd  %%xmm5, %%xmm6        \n\t"

                "movdqa %%xmm2, %%xmm0        \n\t"

                "movdqa %%xmm6, %%xmm4        \n\t"

                "paddd  %%xmm2, %%xmm2        \n\t"

                "paddd  %%xmm6, %%xmm6        \n\t"

                "paddd  %%xmm0, %%xmm2        \n\t"

                "paddd  %%xmm4, %%xmm6        \n\t"

                "paddd  %%xmm7, %%xmm2        \n\t"

                "paddd  %%xmm7, %%xmm6        \n\t"

                "psrad      $3, %%xmm2        \n\t"

                "psrad      $3, %%xmm6        \n\t"

                "movdqa   (%0), %%xmm0        \n\t"

                "movdqa 16(%0), %%xmm4        \n\t"

                "psubd  %%xmm2, %%xmm0        \n\t"

                "psubd  %%xmm6, %%xmm4        \n\t"

                "movdqa %%xmm0, (%0)          \n\t"

                "movdqa %%xmm4, 16(%0)        \n\t"

                :: "r"(&b[i]), "r"(&ref[i])

                : "memory"

            );

        }

        snow_horizontal_compose_lift_lead_out(i, b, b, ref, width, w_l, 0, W_DM, W_DO, W_DS);

        b[0] = b_0 - ((W_DM * 2 * ref[1]+W_DO)>>W_DS);

    }

    { // Lift 1

        DWTELEM * const dst = b+w2;

        i = 0;

        for(; (((long)&dst[i]) & 0xF) && i<w_r; i++){

            dst[i] = dst[i] - (b[i] + b[i + 1]);

        }

        for(; i<w_r-7; i+=8){

            asm volatile(

                "movdqu   (%1), %%xmm1        \n\t"

                "movdqu 16(%1), %%xmm5        \n\t"

                "movdqu  4(%1), %%xmm2        \n\t"

                "movdqu 20(%1), %%xmm6        \n\t"

                "paddd  %%xmm1, %%xmm2        \n\t"

                "paddd  %%xmm5, %%xmm6        \n\t"

                "movdqa   (%0), %%xmm0        \n\t"

                "movdqa 16(%0), %%xmm4        \n\t"

                "psubd  %%xmm2, %%xmm0        \n\t"

                "psubd  %%xmm6, %%xmm4        \n\t"

                "movdqa %%xmm0, (%0)          \n\t"

                "movdqa %%xmm4, 16(%0)        \n\t"

                :: "r"(&dst[i]), "r"(&b[i])

                : "memory"

            );

        }

        snow_horizontal_compose_lift_lead_out(i, dst, dst, b, width, w_r, 1, W_CM, W_CO, W_CS);

    }

    { // Lift 2

        DWTELEM * const ref = b+w2 - 1;

        DWTELEM b_0 = b[0];

        i = 0;

        asm volatile(

            "pslld          $1, %%xmm7        \n\t"

        ::);

        for(; i<w_l-7; i+=8){

            asm volatile(

                "movdqu   (%1), %%xmm1        \n\t"

                "movdqu 16(%1), %%xmm5        \n\t"

                "movdqu  4(%1), %%xmm0        \n\t"

                "movdqu 20(%1), %%xmm4        \n\t" //FIXME try aligned reads and shifts

                "paddd  %%xmm1, %%xmm0        \n\t"

                "paddd  %%xmm5, %%xmm4        \n\t"

                "paddd  %%xmm7, %%xmm0        \n\t"

                "paddd  %%xmm7, %%xmm4        \n\t"

                "movdqa   (%0), %%xmm1        \n\t"

                "movdqa 16(%0), %%xmm5        \n\t"

                "psrad      $2, %%xmm0        \n\t"

                "psrad      $2, %%xmm4        \n\t"

                "paddd  %%xmm1, %%xmm0        \n\t"

                "paddd  %%xmm5, %%xmm4        \n\t"

                "psrad      $2, %%xmm0        \n\t"

                "psrad      $2, %%xmm4        \n\t"

                "paddd  %%xmm1, %%xmm0        \n\t"

                "paddd  %%xmm5, %%xmm4        \n\t"

                "movdqa %%xmm0, (%0)          \n\t"

                "movdqa %%xmm4, 16(%0)        \n\t"

                :: "r"(&b[i]), "r"(&ref[i])

                : "memory"

            );

        }

        snow_horizontal_compose_liftS_lead_out(i, b, b, ref, width, w_l);

        b[0] = b_0 + ((2 * ref[1] + W_BO-1 + 4 * b_0) >> W_BS);

    }

    { // Lift 3

        DWTELEM * const src = b+w2;

        i = 0;

        for(; (((long)&temp[i]) & 0xF) && i<w_r; i++){

            temp[i] = src[i] - ((-W_AM*(b[i] + b[i+1]))>>W_AS);

        }

        for(; i<w_r-7; i+=8){

            asm volatile(

                "movdqu  4(%1), %%xmm2        \n\t"

                "movdqu 20(%1), %%xmm6        \n\t"

                "paddd    (%1), %%xmm2        \n\t"

                "paddd  16(%1), %%xmm6        \n\t"

                "movdqu   (%0), %%xmm0        \n\t"

                "movdqu 16(%0), %%xmm4        \n\t"

                "paddd  %%xmm2, %%xmm0        \n\t"

                "paddd  %%xmm6, %%xmm4        \n\t"

                "psrad      $1, %%xmm2        \n\t"

                "psrad      $1, %%xmm6        \n\t"

                "paddd  %%xmm0, %%xmm2        \n\t"

                "paddd  %%xmm4, %%xmm6        \n\t"

                "movdqa %%xmm2, (%2)          \n\t"

                "movdqa %%xmm6, 16(%2)        \n\t"

                :: "r"(&src[i]), "r"(&b[i]), "r"(&temp[i])

                 : "memory"

               );

        }

        snow_horizontal_compose_lift_lead_out(i, temp, src, b, width, w_r, 1, -W_AM, W_AO+1, W_AS);

    }

    {

        snow_interleave_line_header(&i, width, b, temp);

        for (; (i & 0x1E) != 0x1E; i-=2){

            b[i+1] = temp[i>>1];

            b[i] = b[i>>1];

        }

        for (i-=30; i>=0; i-=32){

            asm volatile(

                "movdqa      (%1), %%xmm0       \n\t"

                "movdqa    16(%1), %%xmm2       \n\t"

                "movdqa    32(%1), %%xmm4       \n\t"

                "movdqa    48(%1), %%xmm6       \n\t"

                "movdqa      (%1), %%xmm1       \n\t"

                "movdqa    16(%1), %%xmm3       \n\t"

                "movdqa    32(%1), %%xmm5       \n\t"

                "movdqa    48(%1), %%xmm7       \n\t"

                "punpckldq   (%2), %%xmm0       \n\t"

                "punpckldq 16(%2), %%xmm2       \n\t"

                "punpckldq 32(%2), %%xmm4       \n\t"

                "punpckldq 48(%2), %%xmm6       \n\t"

                "movdqa    %%xmm0, (%0)         \n\t"

                "movdqa    %%xmm2, 32(%0)       \n\t"

                "movdqa    %%xmm4, 64(%0)       \n\t"

                "movdqa    %%xmm6, 96(%0)       \n\t"

                "punpckhdq   (%2), %%xmm1       \n\t"

                "punpckhdq 16(%2), %%xmm3       \n\t"

                "punpckhdq 32(%2), %%xmm5       \n\t"

                "punpckhdq 48(%2), %%xmm7       \n\t"

                "movdqa    %%xmm1, 16(%0)       \n\t"

                "movdqa    %%xmm3, 48(%0)       \n\t"

                "movdqa    %%xmm5, 80(%0)       \n\t"

                "movdqa    %%xmm7, 112(%0)      \n\t"

                :: "r"(&(b)[i]), "r"(&(b)[i>>1]), "r"(&(temp)[i>>1])

                 : "memory"

               );

        }

    }

}


PPC_OP(btest_T1)

{

    if (T0) {

        regs->nip = T1 & ~3;

    } else {

        regs->nip = PARAM1;

    }

    RETURN();

}


static BlockDriverState *bdrv_open_inherit(const char *filename,

                                           const char *reference,

                                           QDict *options, int flags,

                                           BlockDriverState *parent,

                                           const BdrvChildRole *child_role,

                                           Error **errp)

{

    int ret;

    BlockBackend *file = NULL;

    BlockDriverState *bs;

    BlockDriver *drv = NULL;

    const char *drvname;

    const char *backing;

    Error *local_err = NULL;

    QDict *snapshot_options = NULL;

    int snapshot_flags = 0;

    assert(!child_role || !flags);

    assert(!child_role == !parent);

    if (reference) {

        bool options_non_empty = options ? qdict_size(options) : false;

        QDECREF(options);

        if (filename || options_non_empty) {

            error_setg(errp, "Cannot reference an existing block device with "

                       "additional options or a new filename");

            return NULL;

        }

        bs = bdrv_lookup_bs(reference, reference, errp);

        if (!bs) {

            return NULL;

        }

        bdrv_ref(bs);

        return bs;

    }

    bs = bdrv_new();

    /* NULL means an empty set of options */

    if (options == NULL) {

        options = qdict_new();

    }

    /* json: syntax counts as explicit options, as if in the QDict */

    parse_json_protocol(options, &filename, &local_err);

    if (local_err) {

        goto fail;

    }

    bs->explicit_options = qdict_clone_shallow(options);

    if (child_role) {

        bs->inherits_from = parent;

        child_role->inherit_options(&flags, options,

                                    parent->open_flags, parent->options);

    }

    ret = bdrv_fill_options(&options, filename, &flags, &local_err);

    if (local_err) {

        goto fail;

    }

    /*

     * Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags.

     * Caution: getting a boolean member of @options requires care.

     * When @options come from -blockdev or blockdev_add, members are

     * typed according to the QAPI schema, but when they come from

     * -drive, they're all QString.

     */

    if (g_strcmp0(qdict_get_try_str(options, BDRV_OPT_READ_ONLY), "on") &&

        !qdict_get_try_bool(options, BDRV_OPT_READ_ONLY, false)) {

        flags |= (BDRV_O_RDWR | BDRV_O_ALLOW_RDWR);

    } else {

        flags &= ~BDRV_O_RDWR;

    }

    if (flags & BDRV_O_SNAPSHOT) {

        snapshot_options = qdict_new();

        bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,

                                   flags, options);

        /* Let bdrv_backing_options() override "read-only" */

        qdict_del(options, BDRV_OPT_READ_ONLY);

        bdrv_backing_options(&flags, options, flags, options);

    }

    bs->open_flags = flags;

    bs->options = options;

    options = qdict_clone_shallow(options);

    /* Find the right image format driver */

    /* See cautionary note on accessing @options above */

    drvname = qdict_get_try_str(options, "driver");

    if (drvname) {

        drv = bdrv_find_format(drvname);

        if (!drv) {

            error_setg(errp, "Unknown driver: '%s'", drvname);

            goto fail;

        }

    }

    assert(drvname || !(flags & BDRV_O_PROTOCOL));

    /* See cautionary note on accessing @options above */

    backing = qdict_get_try_str(options, "backing");

    if (backing && *backing == '\0') {

        flags |= BDRV_O_NO_BACKING;

        qdict_del(options, "backing");

    }

    /* Open image file without format layer. This BlockBackend is only used for

     * probing, the block drivers will do their own bdrv_open_child() for the

     * same BDS, which is why we put the node name back into options. */

    if ((flags & BDRV_O_PROTOCOL) == 0) {

        BlockDriverState *file_bs;

        file_bs = bdrv_open_child_bs(filename, options, "file", bs,

                                     &child_file, true, &local_err);

        if (local_err) {

            goto fail;

        }

        if (file_bs != NULL) {

            file = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);

            blk_insert_bs(file, file_bs, &local_err);

            bdrv_unref(file_bs);

            if (local_err) {

                goto fail;

            }

            qdict_put_str(options, "file", bdrv_get_node_name(file_bs));

        }

    }

    /* Image format probing */

    bs->probed = !drv;

    if (!drv && file) {

        ret = find_image_format(file, filename, &drv, &local_err);

        if (ret < 0) {

            goto fail;

        }

        /*

         * This option update would logically belong in bdrv_fill_options(),

         * but we first need to open bs->file for the probing to work, while

         * opening bs->file already requires the (mostly) final set of options

         * so that cache mode etc. can be inherited.

         *

         * Adding the driver later is somewhat ugly, but it's not an option

         * that would ever be inherited, so it's correct. We just need to make

         * sure to update both bs->options (which has the full effective

         * options for bs) and options (which has file.* already removed).

         */

        qdict_put_str(bs->options, "driver", drv->format_name);

        qdict_put_str(options, "driver", drv->format_name);

    } else if (!drv) {

        error_setg(errp, "Must specify either driver or file");

        goto fail;

    }

    /* BDRV_O_PROTOCOL must be set iff a protocol BDS is about to be created */

    assert(!!(flags & BDRV_O_PROTOCOL) == !!drv->bdrv_file_open);

    /* file must be NULL if a protocol BDS is about to be created

     * (the inverse results in an error message from bdrv_open_common()) */

    assert(!(flags & BDRV_O_PROTOCOL) || !file);

    /* Open the image */

    ret = bdrv_open_common(bs, file, options, &local_err);

    if (ret < 0) {

        goto fail;

    }

    if (file) {

        blk_unref(file);

        file = NULL;

    }

    /* If there is a backing file, use it */

    if ((flags & BDRV_O_NO_BACKING) == 0) {

        ret = bdrv_open_backing_file(bs, options, "backing", &local_err);

        if (ret < 0) {

            goto close_and_fail;

        }

    }

    bdrv_refresh_filename(bs);

    /* Check if any unknown options were used */

    if (qdict_size(options) != 0) {

        const QDictEntry *entry = qdict_first(options);

        if (flags & BDRV_O_PROTOCOL) {

            error_setg(errp, "Block protocol '%s' doesn't support the option "

                       "'%s'", drv->format_name, entry->key);

        } else {

            error_setg(errp,

                       "Block format '%s' does not support the option '%s'",

                       drv->format_name, entry->key);

        }

        goto close_and_fail;

    }

    bdrv_parent_cb_change_media(bs, true);

    QDECREF(options);

    /* For snapshot=on, create a temporary qcow2 overlay. bs points to the

     * temporary snapshot afterwards. */

    if (snapshot_flags) {

        BlockDriverState *snapshot_bs;

        snapshot_bs = bdrv_append_temp_snapshot(bs, snapshot_flags,

                                                snapshot_options, &local_err);

        snapshot_options = NULL;

        if (local_err) {

            goto close_and_fail;

        }

        /* We are not going to return bs but the overlay on top of it

         * (snapshot_bs); thus, we have to drop the strong reference to bs

         * (which we obtained by calling bdrv_new()). bs will not be deleted,

         * though, because the overlay still has a reference to it. */

        bdrv_unref(bs);

        bs = snapshot_bs;

    }

    return bs;

fail:

    blk_unref(file);

    if (bs->file != NULL) {

        bdrv_unref_child(bs, bs->file);

    }

    QDECREF(snapshot_options);

    QDECREF(bs->explicit_options);

    QDECREF(bs->options);

    QDECREF(options);

    bs->options = NULL;

    bs->explicit_options = NULL;

    bdrv_unref(bs);

    error_propagate(errp, local_err);

    return NULL;

close_and_fail:

    bdrv_unref(bs);

    QDECREF(snapshot_options);

    QDECREF(options);

    error_propagate(errp, local_err);

    return NULL;

}