static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)

{

    MpegEncContext *s = &ctx->m;

    int time_incr, time_increment;

    int64_t pts;

    s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I;        /* pict type: I = 0 , P = 1 */

    if (s->pict_type == AV_PICTURE_TYPE_B && s->low_delay &&

        ctx->vol_control_parameters == 0 && !(s->flags & CODEC_FLAG_LOW_DELAY)) {

        av_log(s->avctx, AV_LOG_ERROR, "low_delay flag set incorrectly, clearing it\n");

        s->low_delay = 0;

    }

    s->partitioned_frame = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B;

    if (s->partitioned_frame)

        s->decode_mb = mpeg4_decode_partitioned_mb;

    else

        s->decode_mb = mpeg4_decode_mb;

    time_incr = 0;

    while (get_bits1(gb) != 0)

        time_incr++;

    check_marker(gb, "before time_increment");

    if (ctx->time_increment_bits == 0 ||

        !(show_bits(gb, ctx->time_increment_bits + 1) & 1)) {

        av_log(s->avctx, AV_LOG_WARNING,

               "time_increment_bits %d is invalid in relation to the current bitstream, this is likely caused by a missing VOL header\n", ctx->time_increment_bits);

        for (ctx->time_increment_bits = 1;

             ctx->time_increment_bits < 16;

             ctx->time_increment_bits++) {

            if (s->pict_type == AV_PICTURE_TYPE_P ||

                (s->pict_type == AV_PICTURE_TYPE_S &&

                 ctx->vol_sprite_usage == GMC_SPRITE)) {

                if ((show_bits(gb, ctx->time_increment_bits + 6) & 0x37) == 0x30)

                    break;

            } else if ((show_bits(gb, ctx->time_increment_bits + 5) & 0x1F) == 0x18)

                break;

        }

        av_log(s->avctx, AV_LOG_WARNING,

               "time_increment_bits set to %d bits, based on bitstream analysis\n", ctx->time_increment_bits);

        if (s->avctx->framerate.num && 4*s->avctx->framerate.num < 1<<ctx->time_increment_bits) {

            s->avctx->framerate.num = 1<<ctx->time_increment_bits;

            s->avctx->time_base = av_inv_q(av_mul_q(s->avctx->framerate, (AVRational){s->avctx->ticks_per_frame, 1}));

        }

    }

    if (IS_3IV1)

        time_increment = get_bits1(gb);        // FIXME investigate further

    else

        time_increment = get_bits(gb, ctx->time_increment_bits);

    if (s->pict_type != AV_PICTURE_TYPE_B) {

        s->last_time_base = s->time_base;

        s->time_base     += time_incr;

        s->time = s->time_base * s->avctx->framerate.num + time_increment;

        if (s->workaround_bugs & FF_BUG_UMP4) {

            if (s->time < s->last_non_b_time) {

                /* header is not mpeg-4-compatible, broken encoder,

                 * trying to workaround */

                s->time_base++;

                s->time += s->avctx->framerate.num;

            }

        }

        s->pp_time         = s->time - s->last_non_b_time;

        s->last_non_b_time = s->time;

    } else {

        s->time    = (s->last_time_base + time_incr) * s->avctx->framerate.num + time_increment;

        s->pb_time = s->pp_time - (s->last_non_b_time - s->time);

        if (s->pp_time <= s->pb_time ||

            s->pp_time <= s->pp_time - s->pb_time ||

            s->pp_time <= 0) {

            /* messed up order, maybe after seeking? skipping current b-frame */

            return FRAME_SKIPPED;

        }

        ff_mpeg4_init_direct_mv(s);

        if (ctx->t_frame == 0)

            ctx->t_frame = s->pb_time;

        if (ctx->t_frame == 0)

            ctx->t_frame = 1;  // 1/0 protection

        s->pp_field_time = (ROUNDED_DIV(s->last_non_b_time, ctx->t_frame) -

                            ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2;

        s->pb_field_time = (ROUNDED_DIV(s->time, ctx->t_frame) -

                            ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2;

        if (s->pp_field_time <= s->pb_field_time || s->pb_field_time <= 1) {

            s->pb_field_time = 2;

            s->pp_field_time = 4;

            if (!s->progressive_sequence)

                return FRAME_SKIPPED;

        }

    }

    if (s->avctx->framerate.den)

        pts = ROUNDED_DIV(s->time, s->avctx->framerate.den);

    else

        pts = AV_NOPTS_VALUE;

    if (s->avctx->debug&FF_DEBUG_PTS)

        av_log(s->avctx, AV_LOG_DEBUG, "MPEG4 PTS: %"PRId64"\n",

               pts);

    check_marker(gb, "before vop_coded");

    /* vop coded */

    if (get_bits1(gb) != 1) {

        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_ERROR, "vop not coded\n");

        return FRAME_SKIPPED;

    }

    if (ctx->new_pred)

        decode_new_pred(ctx, gb);

    if (ctx->shape != BIN_ONLY_SHAPE &&

                    (s->pict_type == AV_PICTURE_TYPE_P ||

                     (s->pict_type == AV_PICTURE_TYPE_S &&

                      ctx->vol_sprite_usage == GMC_SPRITE))) {

        /* rounding type for motion estimation */

        s->no_rounding = get_bits1(gb);

    } else {

        s->no_rounding = 0;

    }

    // FIXME reduced res stuff

    if (ctx->shape != RECT_SHAPE) {

        if (ctx->vol_sprite_usage != 1 || s->pict_type != AV_PICTURE_TYPE_I) {

            skip_bits(gb, 13);  /* width */

            skip_bits1(gb);     /* marker */

            skip_bits(gb, 13);  /* height */

            skip_bits1(gb);     /* marker */

            skip_bits(gb, 13);  /* hor_spat_ref */

            skip_bits1(gb);     /* marker */

            skip_bits(gb, 13);  /* ver_spat_ref */

        }

        skip_bits1(gb);         /* change_CR_disable */

        if (get_bits1(gb) != 0)

            skip_bits(gb, 8);   /* constant_alpha_value */

    }

    // FIXME complexity estimation stuff

    if (ctx->shape != BIN_ONLY_SHAPE) {

        skip_bits_long(gb, ctx->cplx_estimation_trash_i);

        if (s->pict_type != AV_PICTURE_TYPE_I)

            skip_bits_long(gb, ctx->cplx_estimation_trash_p);

        if (s->pict_type == AV_PICTURE_TYPE_B)

            skip_bits_long(gb, ctx->cplx_estimation_trash_b);

        if (get_bits_left(gb) < 3) {

            av_log(s->avctx, AV_LOG_ERROR, "Header truncated\n");

            return AVERROR_INVALIDDATA;

        }

        ctx->intra_dc_threshold = ff_mpeg4_dc_threshold[get_bits(gb, 3)];

        if (!s->progressive_sequence) {

            s->top_field_first = get_bits1(gb);

            s->alternate_scan  = get_bits1(gb);

        } else

            s->alternate_scan = 0;

    }

    if (s->alternate_scan) {

        ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable,   ff_alternate_vertical_scan);

        ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable,   ff_alternate_vertical_scan);

        ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_vertical_scan);

        ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan);

    } else {

        ff_init_scantable(s->idsp.idct_permutation, &s->inter_scantable,   ff_zigzag_direct);

        ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable,   ff_zigzag_direct);

        ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan);

        ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan);

    }

    if (s->pict_type == AV_PICTURE_TYPE_S &&

        (ctx->vol_sprite_usage == STATIC_SPRITE ||

         ctx->vol_sprite_usage == GMC_SPRITE)) {

        if (mpeg4_decode_sprite_trajectory(ctx, gb) < 0)

            return AVERROR_INVALIDDATA;

        if (ctx->sprite_brightness_change)

            av_log(s->avctx, AV_LOG_ERROR,

                   "sprite_brightness_change not supported\n");

        if (ctx->vol_sprite_usage == STATIC_SPRITE)

            av_log(s->avctx, AV_LOG_ERROR, "static sprite not supported\n");

    }

    if (ctx->shape != BIN_ONLY_SHAPE) {

        s->chroma_qscale = s->qscale = get_bits(gb, s->quant_precision);

        if (s->qscale == 0) {

            av_log(s->avctx, AV_LOG_ERROR,

                   "Error, header damaged or not MPEG4 header (qscale=0)\n");

            return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then

        }

        if (s->pict_type != AV_PICTURE_TYPE_I) {

            s->f_code = get_bits(gb, 3);        /* fcode_for */

            if (s->f_code == 0) {

                av_log(s->avctx, AV_LOG_ERROR,

                       "Error, header damaged or not MPEG4 header (f_code=0)\n");

                s->f_code = 1;

                return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then

            }

        } else

            s->f_code = 1;

        if (s->pict_type == AV_PICTURE_TYPE_B) {

            s->b_code = get_bits(gb, 3);

            if (s->b_code == 0) {

                av_log(s->avctx, AV_LOG_ERROR,

                       "Error, header damaged or not MPEG4 header (b_code=0)\n");

                s->b_code=1;

                return AVERROR_INVALIDDATA; // makes no sense to continue, as the MV decoding will break very quickly

            }

        } else

            s->b_code = 1;

        if (s->avctx->debug & FF_DEBUG_PICT_INFO) {

            av_log(s->avctx, AV_LOG_DEBUG,

                   "qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n",

                   s->qscale, s->f_code, s->b_code,

                   s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")),

                   gb->size_in_bits,s->progressive_sequence, s->alternate_scan,

                   s->top_field_first, s->quarter_sample ? "q" : "h",

                   s->data_partitioning, ctx->resync_marker,

                   ctx->num_sprite_warping_points, s->sprite_warping_accuracy,

                   1 - s->no_rounding, s->vo_type,

                   ctx->vol_control_parameters ? " VOLC" : " ", ctx->intra_dc_threshold,

                   ctx->cplx_estimation_trash_i, ctx->cplx_estimation_trash_p,

                   ctx->cplx_estimation_trash_b,

                   s->time,

                   time_increment

                  );

        }

        if (!ctx->scalability) {

            if (ctx->shape != RECT_SHAPE && s->pict_type != AV_PICTURE_TYPE_I)

                skip_bits1(gb);  // vop shape coding type

        } else {

            if (ctx->enhancement_type) {

                int load_backward_shape = get_bits1(gb);

                if (load_backward_shape)

                    av_log(s->avctx, AV_LOG_ERROR,

                           "load backward shape isn't supported\n");

            }

            skip_bits(gb, 2);  // ref_select_code

        }

    }

    /* detect buggy encoders which don't set the low_delay flag

     * (divx4/xvid/opendivx). Note we cannot detect divx5 without b-frames

     * easily (although it's buggy too) */

    if (s->vo_type == 0 && ctx->vol_control_parameters == 0 &&

        ctx->divx_version == -1 && s->picture_number == 0) {

        av_log(s->avctx, AV_LOG_WARNING,

               "looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag\n");

        s->low_delay = 1;

    }

    s->picture_number++;  // better than pic number==0 always ;)

    // FIXME add short header support

    s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table;

    s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table;

    if (s->workaround_bugs & FF_BUG_EDGE) {

        s->h_edge_pos = s->width;

        s->v_edge_pos = s->height;

    }

    return 0;

}


static void event_class_init(ObjectClass *klass, void *data)

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->bus_type = TYPE_SCLP_EVENTS_BUS;

    dc->unplug = qdev_simple_unplug_cb;

    dc->init = event_qdev_init;

    dc->exit = event_qdev_exit;

}


static int dvvideo_init(AVCodecContext *avctx)

{

    DVVideoContext *s = avctx->priv_data;

    DSPContext dsp;

    static int done=0;

    int i, j;

    if (!done) {

        VLC dv_vlc;

        uint16_t new_dv_vlc_bits[NB_DV_VLC*2];

        uint8_t new_dv_vlc_len[NB_DV_VLC*2];

        uint8_t new_dv_vlc_run[NB_DV_VLC*2];

        int16_t new_dv_vlc_level[NB_DV_VLC*2];

        done = 1;

        dv_vlc_map = av_mallocz(DV_VLC_MAP_LEV_SIZE*DV_VLC_MAP_RUN_SIZE*sizeof(struct dv_vlc_pair));

	if (!dv_vlc_map)

	    return -ENOMEM;

	/* dv_anchor lets each thread know its Id */

	dv_anchor = av_malloc(12*27*sizeof(void*));

	if (!dv_anchor) {

	    av_free(dv_vlc_map);

	    return -ENOMEM;

	}

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

	    dv_anchor[i] = (void*)(size_t)i;

	/* it's faster to include sign bit in a generic VLC parsing scheme */

	for (i=0, j=0; i<NB_DV_VLC; i++, j++) {

	    new_dv_vlc_bits[j] = dv_vlc_bits[i];

	    new_dv_vlc_len[j] = dv_vlc_len[i];

	    new_dv_vlc_run[j] = dv_vlc_run[i];

	    new_dv_vlc_level[j] = dv_vlc_level[i];

	    if (dv_vlc_level[i]) {

	        new_dv_vlc_bits[j] <<= 1;

		new_dv_vlc_len[j]++;

		j++;

		new_dv_vlc_bits[j] = (dv_vlc_bits[i] << 1) | 1;

		new_dv_vlc_len[j] = dv_vlc_len[i] + 1;

		new_dv_vlc_run[j] = dv_vlc_run[i];

		new_dv_vlc_level[j] = -dv_vlc_level[i];

	    }

	}

        /* NOTE: as a trick, we use the fact the no codes are unused

           to accelerate the parsing of partial codes */

        init_vlc(&dv_vlc, TEX_VLC_BITS, j,

                 new_dv_vlc_len, 1, 1, new_dv_vlc_bits, 2, 2);

        dv_rl_vlc = av_malloc(dv_vlc.table_size * sizeof(RL_VLC_ELEM));

	if (!dv_rl_vlc) {

	    av_free(dv_anchor);

	    av_free(dv_vlc_map);

	    return -ENOMEM;

	}

        for(i = 0; i < dv_vlc.table_size; i++){

            int code= dv_vlc.table[i][0];

            int len = dv_vlc.table[i][1];

            int level, run;

            if(len<0){ //more bits needed

                run= 0;

                level= code;

            } else {

                run=   new_dv_vlc_run[code] + 1;

                level= new_dv_vlc_level[code];

            }

            dv_rl_vlc[i].len = len;

            dv_rl_vlc[i].level = level;

            dv_rl_vlc[i].run = run;

        }

	free_vlc(&dv_vlc);

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

           if (dv_vlc_run[i] >= DV_VLC_MAP_RUN_SIZE || dv_vlc_level[i] >= DV_VLC_MAP_LEV_SIZE)

	       continue;

	   if (dv_vlc_map[dv_vlc_run[i]][dv_vlc_level[i]].size != 0)

	       continue;

	   dv_vlc_map[dv_vlc_run[i]][dv_vlc_level[i]].vlc = dv_vlc_bits[i] <<

	                                                    (!!dv_vlc_level[i]);

	   dv_vlc_map[dv_vlc_run[i]][dv_vlc_level[i]].size = dv_vlc_len[i] +

	                                                     (!!dv_vlc_level[i]);

	}

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

#ifdef DV_CODEC_TINY_TARGET

	   for (j = 1; j < DV_VLC_MAP_LEV_SIZE; j++) {

	      if (dv_vlc_map[i][j].size == 0) {

	          dv_vlc_map[i][j].vlc = dv_vlc_map[0][j].vlc |

		            (dv_vlc_map[i-1][0].vlc << (dv_vlc_map[0][j].size));

	          dv_vlc_map[i][j].size = dv_vlc_map[i-1][0].size +

		                          dv_vlc_map[0][j].size;

	      }

	   }

#else

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

	      if (dv_vlc_map[i][j].size == 0) {

	          dv_vlc_map[i][j].vlc = dv_vlc_map[0][j].vlc |

		            (dv_vlc_map[i-1][0].vlc << (dv_vlc_map[0][j].size));

	          dv_vlc_map[i][j].size = dv_vlc_map[i-1][0].size +

		                          dv_vlc_map[0][j].size;

	      }

	      dv_vlc_map[i][((uint16_t)(-j))&0x1ff].vlc =

	                                    dv_vlc_map[i][j].vlc | 1;

	      dv_vlc_map[i][((uint16_t)(-j))&0x1ff].size =

	                                    dv_vlc_map[i][j].size;

	   }

#endif

	}

    }

    /* Generic DSP setup */

    dsputil_init(&dsp, avctx);

    s->get_pixels = dsp.get_pixels;

    /* 88DCT setup */

    s->fdct[0] = dsp.fdct;

    s->idct_put[0] = dsp.idct_put;

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

       s->dv_zigzag[0][i] = dsp.idct_permutation[ff_zigzag_direct[i]];

    /* 248DCT setup */

    s->fdct[1] = dsp.fdct248;

    s->idct_put[1] = simple_idct248_put;  // FIXME: need to add it to DSP

    memcpy(s->dv_zigzag[1], ff_zigzag248_direct, 64);

    /* XXX: do it only for constant case */

    dv_build_unquantize_tables(s, dsp.idct_permutation);

    /* FIXME: I really don't think this should be here */

    if (dv_codec_profile(avctx))

	avctx->pix_fmt = dv_codec_profile(avctx)->pix_fmt;

    avctx->coded_frame = &s->picture;

    return 0;

}


static int wv_read_header(AVFormatContext *s)

{

    AVIOContext *pb = s->pb;

    WVContext *wc = s->priv_data;

    AVStream *st;

    int ret;

    wc->block_parsed = 0;

    for (;;) {

        if ((ret = wv_read_block_header(s, pb, 0)) < 0)

            return ret;

        if (!AV_RN32(wc->extra))

            avio_skip(pb, wc->blksize - 24);

        else

            break;

    }

    /* now we are ready: build format streams */

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;

    st->codec->codec_id              = AV_CODEC_ID_WAVPACK;

    st->codec->channels              = wc->chan;

    st->codec->channel_layout        = wc->chmask;

    st->codec->sample_rate           = wc->rate;

    st->codec->bits_per_coded_sample = wc->bpp;

    avpriv_set_pts_info(st, 64, 1, wc->rate);

    st->start_time = 0;

    st->duration   = wc->samples;

    if (s->pb->seekable) {

        int64_t cur = avio_tell(s->pb);

        wc->apetag_start = ff_ape_parse_tag(s);

        if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX))

            ff_id3v1_read(s);

        avio_seek(s->pb, cur, SEEK_SET);

    }

    return 0;

}


static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr,

                             uint64_t asc, target_ulong *raddr, int *flags,

                             int rw, bool exc)

{

    uint64_t asce = 0;

    int level;

    int r;

    switch (asc) {

    case PSW_ASC_PRIMARY:

        PTE_DPRINTF("%s: asc=primary\n", __func__);

        asce = env->cregs[1];

        break;

    case PSW_ASC_SECONDARY:

        PTE_DPRINTF("%s: asc=secondary\n", __func__);

        asce = env->cregs[7];

        break;

    case PSW_ASC_HOME:

        PTE_DPRINTF("%s: asc=home\n", __func__);

        asce = env->cregs[13];

        break;

    }

    if (asce & _ASCE_REAL_SPACE) {

        /* direct mapping */

        *raddr = vaddr;

        return 0;

    }

    level = asce & _ASCE_TYPE_MASK;

    switch (level) {

    case _ASCE_TYPE_REGION1:

        if ((vaddr >> 62) > (asce & _ASCE_TABLE_LENGTH)) {

            trigger_page_fault(env, vaddr, PGM_REG_FIRST_TRANS, asc, rw, exc);

            return -1;

        }

        break;

    case _ASCE_TYPE_REGION2:

        if (vaddr & 0xffe0000000000000ULL) {

            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64

                    " 0xffe0000000000000ULL\n", __func__, vaddr);

            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);

            return -1;

        }

        if ((vaddr >> 51 & 3) > (asce & _ASCE_TABLE_LENGTH)) {

            trigger_page_fault(env, vaddr, PGM_REG_SEC_TRANS, asc, rw, exc);

            return -1;

        }

        break;

    case _ASCE_TYPE_REGION3:

        if (vaddr & 0xfffffc0000000000ULL) {

            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64

                    " 0xfffffc0000000000ULL\n", __func__, vaddr);

            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);

            return -1;

        }

        if ((vaddr >> 40 & 3) > (asce & _ASCE_TABLE_LENGTH)) {

            trigger_page_fault(env, vaddr, PGM_REG_THIRD_TRANS, asc, rw, exc);

            return -1;

        }

        break;

    case _ASCE_TYPE_SEGMENT:

        if (vaddr & 0xffffffff80000000ULL) {

            DPRINTF("%s: vaddr doesn't fit 0x%16" PRIx64

                    " 0xffffffff80000000ULL\n", __func__, vaddr);

            trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw, exc);

            return -1;

        }

        if ((vaddr >> 29 & 3) > (asce & _ASCE_TABLE_LENGTH)) {

            trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw, exc);

            return -1;

        }

        break;

    }

    r = mmu_translate_region(env, vaddr, asc, asce, level, raddr, flags, rw,

                             exc);

    if ((rw == 1) && !(*flags & PAGE_WRITE)) {

        trigger_prot_fault(env, vaddr, asc, rw, exc);

        return -1;

    }

    return r;

}


void helper_check_tlb_flush(CPUPPCState *env)

{

    check_tlb_flush(env);

}


void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,

                                     int *size, unsigned int domain,

                                     unsigned int bus, unsigned int slot,

                                     unsigned int function)

{

    char name[32], rom_file[64];

    FILE *fp;

    uint8_t val;

    struct stat st;

    void *ptr = NULL;

    /* If loading ROM from file, pci handles it */

    if (dev->romfile || !dev->rom_bar) {

        return NULL;

    }

    snprintf(rom_file, sizeof(rom_file),

             "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom",

             domain, bus, slot, function);

    if (stat(rom_file, &st)) {

        return NULL;

    }

    if (access(rom_file, F_OK)) {

        error_report("pci-assign: Insufficient privileges for %s", rom_file);

        return NULL;

    }

    /* Write "1" to the ROM file to enable it */

    fp = fopen(rom_file, "r+");

    if (fp == NULL) {

        return NULL;

    }

    val = 1;

    if (fwrite(&val, 1, 1, fp) != 1) {

        goto close_rom;

    }

    fseek(fp, 0, SEEK_SET);

    snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));

    memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);

    vmstate_register_ram(&dev->rom, &dev->qdev);

    ptr = memory_region_get_ram_ptr(&dev->rom);

    memset(ptr, 0xff, st.st_size);

    if (!fread(ptr, 1, st.st_size, fp)) {

        error_report("pci-assign: Cannot read from host %s", rom_file);

        error_printf("Device option ROM contents are probably invalid "

                     "(check dmesg).\nSkip option ROM probe with rombar=0, "

                     "or load from file with romfile=\n");

        goto close_rom;

    }

    pci_register_bar(dev, PCI_ROM_SLOT, 0, &dev->rom);

    dev->has_rom = true;

    *size = st.st_size;

close_rom:

    /* Write "0" to disable ROM */

    fseek(fp, 0, SEEK_SET);

    val = 0;

    if (!fwrite(&val, 1, 1, fp)) {

        DEBUG("%s\n", "Failed to disable pci-sysfs rom file");

    }

    fclose(fp);

    return ptr;

}


static void nbd_reply_ready(void *opaque)

{

    BDRVNBDState *s = opaque;

    uint64_t i;

    if (s->reply.handle == 0) {

        /* No reply already in flight.  Fetch a header.  */

        if (nbd_receive_reply(s->sock, &s->reply) < 0) {

            s->reply.handle = 0;

            goto fail;

        }

    }

    /* There's no need for a mutex on the receive side, because the

     * handler acts as a synchronization point and ensures that only

     * one coroutine is called until the reply finishes.  */

    i = HANDLE_TO_INDEX(s, s->reply.handle);

    if (i >= MAX_NBD_REQUESTS) {

        goto fail;

    }

    if (s->recv_coroutine[i]) {

        qemu_coroutine_enter(s->recv_coroutine[i], NULL);

        return;

    }

fail:

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

        if (s->recv_coroutine[i]) {

            qemu_coroutine_enter(s->recv_coroutine[i], NULL);

        }

    }

}


static void quantize_and_encode_band_cost_UPAIR12_mips(struct AACEncContext *s,

                                                       PutBitContext *pb, const float *in, float *out,

                                                       const float *scaled, int size, int scale_idx,

                                                       int cb, const float lambda, const float uplim,

                                                       int *bits, const float ROUNDING)

{

    const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512];

    const float IQ  = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512];

    int i;

    int qc1, qc2, qc3, qc4;

    uint8_t  *p_bits  = (uint8_t*) ff_aac_spectral_bits[cb-1];

    uint16_t *p_codes = (uint16_t*)ff_aac_spectral_codes[cb-1];

    float    *p_vec   = (float   *)ff_aac_codebook_vectors[cb-1];

    abs_pow34_v(s->scoefs, in, size);

    scaled = s->scoefs;

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

        int curidx1, curidx2, sign1, count1, sign2, count2;

        int *in_int = (int *)&in[i];

        uint8_t v_bits;

        unsigned int v_codes;

        int t0, t1, t2, t3, t4;

        const float *vec1, *vec2;

        qc1 = scaled[i  ] * Q34 + ROUND_STANDARD;

        qc2 = scaled[i+1] * Q34 + ROUND_STANDARD;

        qc3 = scaled[i+2] * Q34 + ROUND_STANDARD;

        qc4 = scaled[i+3] * Q34 + ROUND_STANDARD;

        __asm__ volatile (

            ".set push                              \n\t"

            ".set noreorder                         \n\t"

            "ori    %[t4],      $zero,      12      \n\t"

            "ori    %[sign1],   $zero,      0       \n\t"

            "ori    %[sign2],   $zero,      0       \n\t"

            "slt    %[t0],      %[t4],      %[qc1]  \n\t"

            "slt    %[t1],      %[t4],      %[qc2]  \n\t"

            "slt    %[t2],      %[t4],      %[qc3]  \n\t"

            "slt    %[t3],      %[t4],      %[qc4]  \n\t"

            "movn   %[qc1],     %[t4],      %[t0]   \n\t"

            "movn   %[qc2],     %[t4],      %[t1]   \n\t"

            "movn   %[qc3],     %[t4],      %[t2]   \n\t"

            "movn   %[qc4],     %[t4],      %[t3]   \n\t"

            "lw     %[t0],      0(%[in_int])        \n\t"

            "lw     %[t1],      4(%[in_int])        \n\t"

            "lw     %[t2],      8(%[in_int])        \n\t"

            "lw     %[t3],      12(%[in_int])       \n\t"

            "slt    %[t0],      %[t0],      $zero   \n\t"

            "movn   %[sign1],   %[t0],      %[qc1]  \n\t"

            "slt    %[t2],      %[t2],      $zero   \n\t"

            "movn   %[sign2],   %[t2],      %[qc3]  \n\t"

            "slt    %[t1],      %[t1],      $zero   \n\t"

            "sll    %[t0],      %[sign1],   1       \n\t"

            "or     %[t0],      %[t0],      %[t1]   \n\t"

            "movn   %[sign1],   %[t0],      %[qc2]  \n\t"

            "slt    %[t3],      %[t3],      $zero   \n\t"

            "sll    %[t0],      %[sign2],   1       \n\t"

            "or     %[t0],      %[t0],      %[t3]   \n\t"

            "movn   %[sign2],   %[t0],      %[qc4]  \n\t"

            "slt    %[count1],  $zero,      %[qc1]  \n\t"

            "slt    %[t1],      $zero,      %[qc2]  \n\t"

            "slt    %[count2],  $zero,      %[qc3]  \n\t"

            "slt    %[t2],      $zero,      %[qc4]  \n\t"

            "addu   %[count1],  %[count1],  %[t1]   \n\t"

            "addu   %[count2],  %[count2],  %[t2]   \n\t"

            ".set pop                               \n\t"

            : [qc1]"+r"(qc1), [qc2]"+r"(qc2),

              [qc3]"+r"(qc3), [qc4]"+r"(qc4),

              [sign1]"=&r"(sign1), [count1]"=&r"(count1),

              [sign2]"=&r"(sign2), [count2]"=&r"(count2),

              [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3),

              [t4]"=&r"(t4)

            : [in_int]"r"(in_int)

            : "memory"

        );

        curidx1  = 13 * qc1;

        curidx1 += qc2;

        v_codes = (p_codes[curidx1] << count1) | sign1;

        v_bits  = p_bits[curidx1] + count1;

        put_bits(pb, v_bits, v_codes);

        curidx2  = 13 * qc3;

        curidx2 += qc4;

        v_codes = (p_codes[curidx2] << count2) | sign2;

        v_bits  = p_bits[curidx2] + count2;

        put_bits(pb, v_bits, v_codes);

        if (out) {

           vec1 = &p_vec[curidx1*2];

           vec2 = &p_vec[curidx2*2];

           out[i+0] = copysignf(vec1[0] * IQ, in[i+0]);

           out[i+1] = copysignf(vec1[1] * IQ, in[i+1]);

           out[i+2] = copysignf(vec2[0] * IQ, in[i+2]);

           out[i+3] = copysignf(vec2[1] * IQ, in[i+3]);

        }

    }

}


static int ast_probe(AVProbeData *p)

{

    if (AV_RL32(p->buf) == MKTAG('S','T','R','M') &&

        AV_RB16(p->buf + 10) &&

        AV_RB16(p->buf + 12) &&

        AV_RB32(p->buf + 16))

        return AVPROBE_SCORE_MAX / 3 * 2;

    return 0;

}


target_ulong helper_rdhwr_ccres(CPUMIPSState *env)

{

    check_hwrena(env, 3);

    return env->CCRes;

}


void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)

{

    RAMBlock *block;

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

        create_new_memory_mapping(list, block->offset, 0, block->length);

    }

}


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

{

    RPLContext *rpl = s->priv_data;

    AVIOContext *pb = s->pb;

    AVStream* stream;

    AVIndexEntry* index_entry;

    uint32_t ret;

    if (rpl->chunk_part == s->nb_streams) {

        rpl->chunk_number++;

        rpl->chunk_part = 0;

    }

    stream = s->streams[rpl->chunk_part];

    if (rpl->chunk_number >= stream->nb_index_entries)

        return AVERROR_EOF;

    index_entry = &stream->index_entries[rpl->chunk_number];

    if (rpl->frame_in_part == 0)

        if (avio_seek(pb, index_entry->pos, SEEK_SET) < 0)

            return AVERROR(EIO);

    if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO &&

        stream->codec->codec_tag == 124) {

        // We have to split Escape 124 frames because there are

        // multiple frames per chunk in Escape 124 samples.

        uint32_t frame_size;

        avio_skip(pb, 4); /* flags */

        frame_size = avio_rl32(pb);

        if (avio_seek(pb, -8, SEEK_CUR) < 0)

            return AVERROR(EIO);

        ret = av_get_packet(pb, pkt, frame_size);

        if (ret != frame_size) {

            av_free_packet(pkt);

            return AVERROR(EIO);

        }

        pkt->duration = 1;

        pkt->pts = index_entry->timestamp + rpl->frame_in_part;

        pkt->stream_index = rpl->chunk_part;

        rpl->frame_in_part++;

        if (rpl->frame_in_part == rpl->frames_per_chunk) {

            rpl->frame_in_part = 0;

            rpl->chunk_part++;

        }

    } else {

        ret = av_get_packet(pb, pkt, index_entry->size);

        if (ret != index_entry->size) {

            av_free_packet(pkt);

            return AVERROR(EIO);

        }

        if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {

            // frames_per_chunk should always be one here; the header

            // parsing will warn if it isn't.

            pkt->duration = rpl->frames_per_chunk;

        } else {

            // All the audio codecs supported in this container

            // (at least so far) are constant-bitrate.

            pkt->duration = ret * 8;

        }

        pkt->pts = index_entry->timestamp;

        pkt->stream_index = rpl->chunk_part;

        rpl->chunk_part++;

    }

    // None of the Escape formats have keyframes, and the ADPCM

    // format used doesn't have keyframes.

    if (rpl->chunk_number == 0 && rpl->frame_in_part == 0)

        pkt->flags |= AV_PKT_FLAG_KEY;

    return ret;

}


static void acpi_set_pci_info(void)

{

    PCIBus *bus = find_i440fx(); /* TODO: Q35 support */

    unsigned bsel_alloc = 0;

    if (bus) {

        /* Scan all PCI buses. Set property to enable acpi based hotplug. */

        pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &bsel_alloc);

    }

}


static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features)

{

    QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;

    qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES, features);

}


static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)

{

    XHCITRB *trb_setup, *trb_status;

    uint8_t bmRequestType, bRequest;

    uint16_t wValue, wLength, wIndex;

    XHCIPort *port;

    USBDevice *dev;

    int ret;

    DPRINTF("xhci_fire_ctl_transfer(slot=%d)\n", xfer->slotid);

    trb_setup = &xfer->trbs[0];

    trb_status = &xfer->trbs[xfer->trb_count-1];

    /* at most one Event Data TRB allowed after STATUS */

    if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {

        trb_status--;

    }

    /* do some sanity checks */

    if (TRB_TYPE(*trb_setup) != TR_SETUP) {

        fprintf(stderr, "xhci: ep0 first TD not SETUP: %d\n",

                TRB_TYPE(*trb_setup));

        return -1;

    }

    if (TRB_TYPE(*trb_status) != TR_STATUS) {

        fprintf(stderr, "xhci: ep0 last TD not STATUS: %d\n",

                TRB_TYPE(*trb_status));

        return -1;

    }

    if (!(trb_setup->control & TRB_TR_IDT)) {

        fprintf(stderr, "xhci: Setup TRB doesn't have IDT set\n");

        return -1;

    }

    if ((trb_setup->status & 0x1ffff) != 8) {

        fprintf(stderr, "xhci: Setup TRB has bad length (%d)\n",

                (trb_setup->status & 0x1ffff));

        return -1;

    }

    bmRequestType = trb_setup->parameter;

    bRequest = trb_setup->parameter >> 8;

    wValue = trb_setup->parameter >> 16;

    wIndex = trb_setup->parameter >> 32;

    wLength = trb_setup->parameter >> 48;

    if (xfer->data && xfer->data_alloced < wLength) {

        xfer->data_alloced = 0;

        g_free(xfer->data);

        xfer->data = NULL;

    }

    if (!xfer->data) {

        DPRINTF("xhci: alloc %d bytes data\n", wLength);

        xfer->data = g_malloc(wLength+1);

        xfer->data_alloced = wLength;

    }

    xfer->data_length = wLength;

    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];

    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);

    if (!dev) {

        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,

                xhci->slots[xfer->slotid-1].port);

        return -1;

    }

    xfer->in_xfer = bmRequestType & USB_DIR_IN;

    xfer->iso_xfer = false;

    xhci_setup_packet(xfer, dev);

    if (!xfer->in_xfer) {

        xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);

    }

    ret = usb_device_handle_control(dev, &xfer->packet,

                                    (bmRequestType << 8) | bRequest,

                                    wValue, wIndex, wLength, xfer->data);

    xhci_complete_packet(xfer, ret);

    if (!xfer->running_async && !xfer->running_retry) {

        xhci_kick_ep(xhci, xfer->slotid, xfer->epid);

    }

    return 0;

}


static int combine_residual_frame(DCAXllDecoder *s, DCAXllChSet *c)

{

    DCAContext *dca = s->avctx->priv_data;

    int ch, nsamples = s->nframesamples;

    DCAXllChSet *o;

    // Verify that core is compatible

    if (!(dca->packet & DCA_PACKET_CORE)) {

        av_log(s->avctx, AV_LOG_ERROR, "Residual encoded channels are present without core\n");

        return AVERROR(EINVAL);

    }

    if (c->freq != dca->core.output_rate) {

        av_log(s->avctx, AV_LOG_WARNING, "Sample rate mismatch between core (%d Hz) and XLL (%d Hz)\n", dca->core.output_rate, c->freq);

        return AVERROR_INVALIDDATA;

    }

    if (nsamples != dca->core.npcmsamples) {

        av_log(s->avctx, AV_LOG_WARNING, "Number of samples per frame mismatch between core (%d) and XLL (%d)\n", dca->core.npcmsamples, nsamples);

        return AVERROR_INVALIDDATA;

    }

    // See if this channel set is downmixed and find the next channel set in

    // hierarchy. If downmixed, undo core pre-scaling before combining with

    // residual (residual is not scaled).

    o = find_next_hier_dmix_chset(s, c);

    // Reduce core bit width and combine with residual

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

        int n, spkr, shift, round;

        int32_t *src, *dst;

        if (c->residual_encode & (1 << ch))

            continue;

        // Map this channel to core speaker

        spkr = ff_dca_core_map_spkr(&dca->core, c->ch_remap[ch]);

        if (spkr < 0) {

            av_log(s->avctx, AV_LOG_WARNING, "Residual encoded channel (%d) references unavailable core channel\n", c->ch_remap[ch]);

            return AVERROR_INVALIDDATA;

        }

        // Account for LSB width

        shift = 24 - c->pcm_bit_res + chs_get_lsb_width(s, c, 0, ch);

        if (shift > 24) {

            av_log(s->avctx, AV_LOG_WARNING, "Invalid core shift (%d bits)\n", shift);

            return AVERROR_INVALIDDATA;

        }

        round = shift > 0 ? 1 << (shift - 1) : 0;

        src = dca->core.output_samples[spkr];

        dst = c->bands[0].msb_sample_buffer[ch];

        if (o) {

            // Undo embedded core downmix pre-scaling

            int scale_inv = o->dmix_scale_inv[c->hier_ofs + ch];

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

                dst[n] += (SUINT)clip23((mul16(src[n], scale_inv) + round) >> shift);

        } else {

            // No downmix scaling

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

                dst[n] += (src[n] + round) >> shift;

        }

    }

    return 0;

}


static void boston_mach_class_init(MachineClass *mc)

{

    mc->desc = "MIPS Boston";

    mc->init = boston_mach_init;

    mc->block_default_type = IF_IDE;

    mc->default_ram_size = 2 * G_BYTE;

    mc->max_cpus = 16;

}


PAETH(mmx2, ABS3_MMX2)

#ifdef HAVE_SSSE3

PAETH(ssse3, ABS3_SSSE3)

#endif

#define QPEL_V_LOW(m3,m4,m5,m6, pw_20, pw_3, rnd, in0, in1, in2, in7, out, OP)\

        "paddw " #m4 ", " #m3 "           \n\t" /* x1 */\

        "movq "MANGLE(ff_pw_20)", %%mm4   \n\t" /* 20 */\

        "pmullw " #m3 ", %%mm4            \n\t" /* 20x1 */\

        "movq "#in7", " #m3 "             \n\t" /* d */\

        "movq "#in0", %%mm5               \n\t" /* D */\

        "paddw " #m3 ", %%mm5             \n\t" /* x4 */\

        "psubw %%mm5, %%mm4               \n\t" /* 20x1 - x4 */\

        "movq "#in1", %%mm5               \n\t" /* C */\

        "movq "#in2", %%mm6               \n\t" /* B */\

        "paddw " #m6 ", %%mm5             \n\t" /* x3 */\

        "paddw " #m5 ", %%mm6             \n\t" /* x2 */\

        "paddw %%mm6, %%mm6               \n\t" /* 2x2 */\

        "psubw %%mm6, %%mm5               \n\t" /* -2x2 + x3 */\

        "pmullw "MANGLE(ff_pw_3)", %%mm5  \n\t" /* -6x2 + 3x3 */\

        "paddw " #rnd ", %%mm4            \n\t" /* x2 */\

        "paddw %%mm4, %%mm5               \n\t" /* 20x1 - 6x2 + 3x3 - x4 */\

        "psraw $5, %%mm5                  \n\t"\

        "packuswb %%mm5, %%mm5            \n\t"\

        OP(%%mm5, out, %%mm7, d)

#define QPEL_BASE(OPNAME, ROUNDER, RND, OP_MMX2, OP_3DNOW)\

static void OPNAME ## mpeg4_qpel16_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\

    uint64_t temp;\

\

    asm volatile(\

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

        "1:                               \n\t"\

        "movq  (%0), %%mm0                \n\t" /* ABCDEFGH */\

        "movq %%mm0, %%mm1                \n\t" /* ABCDEFGH */\

        "movq %%mm0, %%mm2                \n\t" /* ABCDEFGH */\

        "punpcklbw %%mm7, %%mm0           \n\t" /* 0A0B0C0D */\

        "punpckhbw %%mm7, %%mm1           \n\t" /* 0E0F0G0H */\

        "pshufw $0x90, %%mm0, %%mm5       \n\t" /* 0A0A0B0C */\

        "pshufw $0x41, %%mm0, %%mm6       \n\t" /* 0B0A0A0B */\

        "movq %%mm2, %%mm3                \n\t" /* ABCDEFGH */\

        "movq %%mm2, %%mm4                \n\t" /* ABCDEFGH */\

        "psllq $8, %%mm2                  \n\t" /* 0ABCDEFG */\

        "psllq $16, %%mm3                 \n\t" /* 00ABCDEF */\

        "psllq $24, %%mm4                 \n\t" /* 000ABCDE */\

        "punpckhbw %%mm7, %%mm2           \n\t" /* 0D0E0F0G */\

        "punpckhbw %%mm7, %%mm3           \n\t" /* 0C0D0E0F */\

        "punpckhbw %%mm7, %%mm4           \n\t" /* 0B0C0D0E */\

        "paddw %%mm3, %%mm5               \n\t" /* b */\

        "paddw %%mm2, %%mm6               \n\t" /* c */\

        "paddw %%mm5, %%mm5               \n\t" /* 2b */\

        "psubw %%mm5, %%mm6               \n\t" /* c - 2b */\

        "pshufw $0x06, %%mm0, %%mm5       \n\t" /* 0C0B0A0A */\

        "pmullw "MANGLE(ff_pw_3)", %%mm6  \n\t" /* 3c - 6b */\

        "paddw %%mm4, %%mm0               \n\t" /* a */\

        "paddw %%mm1, %%mm5               \n\t" /* d */\

        "pmullw "MANGLE(ff_pw_20)", %%mm0 \n\t" /* 20a */\

        "psubw %%mm5, %%mm0               \n\t" /* 20a - d */\

        "paddw %6, %%mm6                  \n\t"\

        "paddw %%mm6, %%mm0               \n\t" /* 20a - 6b + 3c - d */\

        "psraw $5, %%mm0                  \n\t"\

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

        /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\

        \

        "movq 5(%0), %%mm0                \n\t" /* FGHIJKLM */\

        "movq %%mm0, %%mm5                \n\t" /* FGHIJKLM */\

        "movq %%mm0, %%mm6                \n\t" /* FGHIJKLM */\

        "psrlq $8, %%mm0                  \n\t" /* GHIJKLM0 */\

        "psrlq $16, %%mm5                 \n\t" /* HIJKLM00 */\

        "punpcklbw %%mm7, %%mm0           \n\t" /* 0G0H0I0J */\

        "punpcklbw %%mm7, %%mm5           \n\t" /* 0H0I0J0K */\

        "paddw %%mm0, %%mm2               \n\t" /* b */\

        "paddw %%mm5, %%mm3               \n\t" /* c */\

        "paddw %%mm2, %%mm2               \n\t" /* 2b */\

        "psubw %%mm2, %%mm3               \n\t" /* c - 2b */\

        "movq %%mm6, %%mm2                \n\t" /* FGHIJKLM */\

        "psrlq $24, %%mm6                 \n\t" /* IJKLM000 */\

        "punpcklbw %%mm7, %%mm2           \n\t" /* 0F0G0H0I */\

        "punpcklbw %%mm7, %%mm6           \n\t" /* 0I0J0K0L */\

        "pmullw "MANGLE(ff_pw_3)", %%mm3  \n\t" /* 3c - 6b */\

        "paddw %%mm2, %%mm1               \n\t" /* a */\

        "paddw %%mm6, %%mm4               \n\t" /* d */\

        "pmullw "MANGLE(ff_pw_20)", %%mm1 \n\t" /* 20a */\

        "psubw %%mm4, %%mm3               \n\t" /* - 6b +3c - d */\

        "paddw %6, %%mm1                  \n\t"\

        "paddw %%mm1, %%mm3               \n\t" /* 20a - 6b +3c - d */\

        "psraw $5, %%mm3                  \n\t"\

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

        "packuswb %%mm3, %%mm1            \n\t"\

        OP_MMX2(%%mm1, (%1),%%mm4, q)\

        /* mm0= GHIJ, mm2=FGHI, mm5=HIJK, mm6=IJKL, mm7=0 */\

        \

        "movq 9(%0), %%mm1                \n\t" /* JKLMNOPQ */\

        "movq %%mm1, %%mm4                \n\t" /* JKLMNOPQ */\

        "movq %%mm1, %%mm3                \n\t" /* JKLMNOPQ */\

        "psrlq $8, %%mm1                  \n\t" /* KLMNOPQ0 */\

        "psrlq $16, %%mm4                 \n\t" /* LMNOPQ00 */\

        "punpcklbw %%mm7, %%mm1           \n\t" /* 0K0L0M0N */\

        "punpcklbw %%mm7, %%mm4           \n\t" /* 0L0M0N0O */\

        "paddw %%mm1, %%mm5               \n\t" /* b */\

        "paddw %%mm4, %%mm0               \n\t" /* c */\

        "paddw %%mm5, %%mm5               \n\t" /* 2b */\

        "psubw %%mm5, %%mm0               \n\t" /* c - 2b */\

        "movq %%mm3, %%mm5                \n\t" /* JKLMNOPQ */\

        "psrlq $24, %%mm3                 \n\t" /* MNOPQ000 */\

        "pmullw "MANGLE(ff_pw_3)", %%mm0  \n\t" /* 3c - 6b */\

        "punpcklbw %%mm7, %%mm3           \n\t" /* 0M0N0O0P */\

        "paddw %%mm3, %%mm2               \n\t" /* d */\

        "psubw %%mm2, %%mm0               \n\t" /* -6b + 3c - d */\

        "movq %%mm5, %%mm2                \n\t" /* JKLMNOPQ */\

        "punpcklbw %%mm7, %%mm2           \n\t" /* 0J0K0L0M */\

        "punpckhbw %%mm7, %%mm5           \n\t" /* 0N0O0P0Q */\

        "paddw %%mm2, %%mm6               \n\t" /* a */\

        "pmullw "MANGLE(ff_pw_20)", %%mm6 \n\t" /* 20a */\

        "paddw %6, %%mm0                  \n\t"\

        "paddw %%mm6, %%mm0               \n\t" /* 20a - 6b + 3c - d */\

        "psraw $5, %%mm0                  \n\t"\

        /* mm1=KLMN, mm2=JKLM, mm3=MNOP, mm4=LMNO, mm5=NOPQ mm7=0 */\

        \

        "paddw %%mm5, %%mm3               \n\t" /* a */\

        "pshufw $0xF9, %%mm5, %%mm6       \n\t" /* 0O0P0Q0Q */\

        "paddw %%mm4, %%mm6               \n\t" /* b */\

        "pshufw $0xBE, %%mm5, %%mm4       \n\t" /* 0P0Q0Q0P */\

        "pshufw $0x6F, %%mm5, %%mm5       \n\t" /* 0Q0Q0P0O */\

        "paddw %%mm1, %%mm4               \n\t" /* c */\

        "paddw %%mm2, %%mm5               \n\t" /* d */\

        "paddw %%mm6, %%mm6               \n\t" /* 2b */\

        "psubw %%mm6, %%mm4               \n\t" /* c - 2b */\

        "pmullw "MANGLE(ff_pw_20)", %%mm3 \n\t" /* 20a */\

        "pmullw "MANGLE(ff_pw_3)", %%mm4  \n\t" /* 3c - 6b */\

        "psubw %%mm5, %%mm3               \n\t" /* -6b + 3c - d */\

        "paddw %6, %%mm4                  \n\t"\

        "paddw %%mm3, %%mm4               \n\t" /* 20a - 6b + 3c - d */\

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

        "packuswb %%mm4, %%mm0            \n\t"\

        OP_MMX2(%%mm0, 8(%1), %%mm4, q)\

        \

        "add %3, %0                       \n\t"\

        "add %4, %1                       \n\t"\

        "decl %2                          \n\t"\

        " jnz 1b                          \n\t"\

        : "+a"(src), "+c"(dst), "+g"(h)\

        : "d"((long)srcStride), "S"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\

        : "memory"\

    );\

}\

\

static void OPNAME ## mpeg4_qpel16_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\

    int i;\

    int16_t temp[16];\

    /* quick HACK, XXX FIXME MUST be optimized */\

    for(i=0; i<h; i++)\

    {\

        temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\

        temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\

        temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\

        temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\

        temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\

        temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 9]);\

        temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 9])*3 - (src[ 3]+src[10]);\

        temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 9])*6 + (src[ 5]+src[10])*3 - (src[ 4]+src[11]);\

        temp[ 8]= (src[ 8]+src[ 9])*20 - (src[ 7]+src[10])*6 + (src[ 6]+src[11])*3 - (src[ 5]+src[12]);\

        temp[ 9]= (src[ 9]+src[10])*20 - (src[ 8]+src[11])*6 + (src[ 7]+src[12])*3 - (src[ 6]+src[13]);\

        temp[10]= (src[10]+src[11])*20 - (src[ 9]+src[12])*6 + (src[ 8]+src[13])*3 - (src[ 7]+src[14]);\

        temp[11]= (src[11]+src[12])*20 - (src[10]+src[13])*6 + (src[ 9]+src[14])*3 - (src[ 8]+src[15]);\

        temp[12]= (src[12]+src[13])*20 - (src[11]+src[14])*6 + (src[10]+src[15])*3 - (src[ 9]+src[16]);\

        temp[13]= (src[13]+src[14])*20 - (src[12]+src[15])*6 + (src[11]+src[16])*3 - (src[10]+src[16]);\

        temp[14]= (src[14]+src[15])*20 - (src[13]+src[16])*6 + (src[12]+src[16])*3 - (src[11]+src[15]);\

        temp[15]= (src[15]+src[16])*20 - (src[14]+src[16])*6 + (src[13]+src[15])*3 - (src[12]+src[14]);\

        asm volatile(\

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

            "movq 8(%0), %%mm1              \n\t"\

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

            "paddw %2, %%mm1                \n\t"\

            "psraw $5, %%mm0                \n\t"\

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

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

            OP_3DNOW(%%mm0, (%1), %%mm1, q)\

            "movq 16(%0), %%mm0             \n\t"\

            "movq 24(%0), %%mm1             \n\t"\

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

            "paddw %2, %%mm1                \n\t"\

            "psraw $5, %%mm0                \n\t"\

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

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

            OP_3DNOW(%%mm0, 8(%1), %%mm1, q)\

            :: "r"(temp), "r"(dst), "m"(ROUNDER)\

            : "memory"\

        );\

        dst+=dstStride;\

        src+=srcStride;\

    }\

}\

\

static void OPNAME ## mpeg4_qpel8_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\

    asm volatile(\

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

        "1:                               \n\t"\

        "movq  (%0), %%mm0                \n\t" /* ABCDEFGH */\

        "movq %%mm0, %%mm1                \n\t" /* ABCDEFGH */\

        "movq %%mm0, %%mm2                \n\t" /* ABCDEFGH */\

        "punpcklbw %%mm7, %%mm0           \n\t" /* 0A0B0C0D */\

        "punpckhbw %%mm7, %%mm1           \n\t" /* 0E0F0G0H */\

        "pshufw $0x90, %%mm0, %%mm5       \n\t" /* 0A0A0B0C */\

        "pshufw $0x41, %%mm0, %%mm6       \n\t" /* 0B0A0A0B */\

        "movq %%mm2, %%mm3                \n\t" /* ABCDEFGH */\

        "movq %%mm2, %%mm4                \n\t" /* ABCDEFGH */\

        "psllq $8, %%mm2                  \n\t" /* 0ABCDEFG */\

        "psllq $16, %%mm3                 \n\t" /* 00ABCDEF */\

        "psllq $24, %%mm4                 \n\t" /* 000ABCDE */\

        "punpckhbw %%mm7, %%mm2           \n\t" /* 0D0E0F0G */\

        "punpckhbw %%mm7, %%mm3           \n\t" /* 0C0D0E0F */\

        "punpckhbw %%mm7, %%mm4           \n\t" /* 0B0C0D0E */\

        "paddw %%mm3, %%mm5               \n\t" /* b */\

        "paddw %%mm2, %%mm6               \n\t" /* c */\

        "paddw %%mm5, %%mm5               \n\t" /* 2b */\

        "psubw %%mm5, %%mm6               \n\t" /* c - 2b */\

        "pshufw $0x06, %%mm0, %%mm5       \n\t" /* 0C0B0A0A */\

        "pmullw "MANGLE(ff_pw_3)", %%mm6  \n\t" /* 3c - 6b */\

        "paddw %%mm4, %%mm0               \n\t" /* a */\

        "paddw %%mm1, %%mm5               \n\t" /* d */\

        "pmullw "MANGLE(ff_pw_20)", %%mm0 \n\t" /* 20a */\

        "psubw %%mm5, %%mm0               \n\t" /* 20a - d */\

        "paddw %5, %%mm6                  \n\t"\

        "paddw %%mm6, %%mm0               \n\t" /* 20a - 6b + 3c - d */\

        "psraw $5, %%mm0                  \n\t"\

        /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\

        \

        "movd 5(%0), %%mm5                \n\t" /* FGHI */\

        "punpcklbw %%mm7, %%mm5           \n\t" /* 0F0G0H0I */\

        "pshufw $0xF9, %%mm5, %%mm6       \n\t" /* 0G0H0I0I */\

        "paddw %%mm5, %%mm1               \n\t" /* a */\

        "paddw %%mm6, %%mm2               \n\t" /* b */\

        "pshufw $0xBE, %%mm5, %%mm6       \n\t" /* 0H0I0I0H */\

        "pshufw $0x6F, %%mm5, %%mm5       \n\t" /* 0I0I0H0G */\

        "paddw %%mm6, %%mm3               \n\t" /* c */\

        "paddw %%mm5, %%mm4               \n\t" /* d */\

        "paddw %%mm2, %%mm2               \n\t" /* 2b */\

        "psubw %%mm2, %%mm3               \n\t" /* c - 2b */\

        "pmullw "MANGLE(ff_pw_20)", %%mm1 \n\t" /* 20a */\

        "pmullw "MANGLE(ff_pw_3)", %%mm3  \n\t" /* 3c - 6b */\

        "psubw %%mm4, %%mm3               \n\t" /* -6b + 3c - d */\

        "paddw %5, %%mm1                  \n\t"\

        "paddw %%mm1, %%mm3               \n\t" /* 20a - 6b + 3c - d */\

        "psraw $5, %%mm3                  \n\t"\

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

        OP_MMX2(%%mm0, (%1), %%mm4, q)\

        \

        "add %3, %0                       \n\t"\

        "add %4, %1                       \n\t"\

        "decl %2                          \n\t"\

        " jnz 1b                          \n\t"\

        : "+a"(src), "+c"(dst), "+g"(h)\

        : "S"((long)srcStride), "D"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER)\

        : "memory"\

    );\

}\

\

static void OPNAME ## mpeg4_qpel8_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\

    int i;\

    int16_t temp[8];\

    /* quick HACK, XXX FIXME MUST be optimized */\

    for(i=0; i<h; i++)\

    {\

        temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\

        temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\

        temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\

        temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\

        temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\

        temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 8]);\

        temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 8])*3 - (src[ 3]+src[ 7]);\

        temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 8])*6 + (src[ 5]+src[ 7])*3 - (src[ 4]+src[ 6]);\

        asm volatile(\

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

            "movq 8(%0), %%mm1          \n\t"\

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

            "paddw %2, %%mm1            \n\t"\

            "psraw $5, %%mm0            \n\t"\

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

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

            OP_3DNOW(%%mm0, (%1), %%mm1, q)\

            :: "r"(temp), "r"(dst), "m"(ROUNDER)\

            :"memory"\

        );\

        dst+=dstStride;\

        src+=srcStride;\

    }\

}

#define QPEL_OP(OPNAME, ROUNDER, RND, OP, MMX)\

\

static void OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\

    uint64_t temp[17*4];\

    uint64_t *temp_ptr= temp;\

    int count= 17;\

\

    /*FIXME unroll */\

    asm volatile(\

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

        "1:                             \n\t"\

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

        "movq (%0), %%mm1               \n\t"\

        "movq 8(%0), %%mm2              \n\t"\

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

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

        "punpckhbw %%mm7, %%mm1         \n\t"\

        "punpcklbw %%mm7, %%mm2         \n\t"\

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

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

        "movq %%mm1, 17*8(%1)           \n\t"\

        "movq %%mm2, 2*17*8(%1)         \n\t"\

        "movq %%mm3, 3*17*8(%1)         \n\t"\

        "add $8, %1                     \n\t"\

        "add %3, %0                     \n\t"\

        "decl %2                        \n\t"\

        " jnz 1b                        \n\t"\

        : "+r" (src), "+r" (temp_ptr), "+r"(count)\

        : "r" ((long)srcStride)\

        : "memory"\

    );\

    \

    temp_ptr= temp;\

    count=4;\

    \

/*FIXME reorder for speed */\

    asm volatile(\

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

        "1:                             \n\t"\

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

        "movq 8(%0), %%mm1              \n\t"\

        "movq 16(%0), %%mm2             \n\t"\

        "movq 24(%0), %%mm3             \n\t"\

        QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)\

        QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)\

        \

        QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\

        QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 72(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 80(%0), (%1), OP)\

        QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 88(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 40(%0), 48(%0), 56(%0), 96(%0), (%1), OP)\

        QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 48(%0), 56(%0), 64(%0),104(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 56(%0), 64(%0), 72(%0),112(%0), (%1), OP)\

        QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 64(%0), 72(%0), 80(%0),120(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 72(%0), 80(%0), 88(%0),128(%0), (%1), OP)\

        \

        QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 80(%0), 88(%0), 96(%0),128(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"  \

        QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 88(%0), 96(%0),104(%0),120(%0), (%1), OP)\

        QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 96(%0),104(%0),112(%0),112(%0), (%1, %3), OP)\

        \

        "add $136, %0                   \n\t"\

        "add %6, %1                     \n\t"\

        "decl %2                        \n\t"\

        " jnz 1b                        \n\t"\

        \

        : "+r"(temp_ptr), "+r"(dst), "+g"(count)\

        : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-14*(long)dstStride)\

        :"memory"\

    );\

}\

\

static void OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\

    uint64_t temp[9*2];\

    uint64_t *temp_ptr= temp;\

    int count= 9;\

\

    /*FIXME unroll */\

    asm volatile(\

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

        "1:                             \n\t"\

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

        "movq (%0), %%mm1               \n\t"\

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

        "punpckhbw %%mm7, %%mm1         \n\t"\

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

        "movq %%mm1, 9*8(%1)            \n\t"\

        "add $8, %1                     \n\t"\

        "add %3, %0                     \n\t"\

        "decl %2                        \n\t"\

        " jnz 1b                        \n\t"\

        : "+r" (src), "+r" (temp_ptr), "+r"(count)\

        : "r" ((long)srcStride)\

        : "memory"\

    );\

    \

    temp_ptr= temp;\

    count=2;\

    \

/*FIXME reorder for speed */\

    asm volatile(\

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

        "1:                             \n\t"\

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

        "movq 8(%0), %%mm1              \n\t"\

        "movq 16(%0), %%mm2             \n\t"\

        "movq 24(%0), %%mm3             \n\t"\

        QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)\

        QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)\

        \

        QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\

        \

        QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 64(%0), (%1, %3), OP)\

        "add %4, %1                     \n\t"\

        QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 56(%0), (%1), OP)\

        QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 48(%0), (%1, %3), OP)\

                \

        "add $72, %0                    \n\t"\

        "add %6, %1                     \n\t"\

        "decl %2                        \n\t"\

        " jnz 1b                        \n\t"\

         \

        : "+r"(temp_ptr), "+r"(dst), "+g"(count)\

        : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-6*(long)dstStride)\

        : "memory"\

   );\

}\

\

static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## pixels8_ ## MMX(dst, src, stride, 8);\

}\

\

static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[8];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\

}\

\

static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, stride, 8);\

}\

\

static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[8];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, src+1, half, stride, stride, 8);\

}\

\

static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[8];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\

    OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\

}\

\

static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, stride, stride);\

}\

\

static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[8];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\

    OPNAME ## pixels8_l2_ ## MMX(dst, src+stride, half, stride, stride, 8);\

}\

static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half) + 64;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\

}\

static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half) + 64;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\

}\

static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half) + 64;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\

}\

static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half) + 64;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\

}\

static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half) + 64;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\

}\

static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half) + 64;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\

    OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\

}\

static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\

    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\

}\

static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[8 + 9];\

    uint8_t * const halfH= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\

    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\

}\

static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[9];\

    uint8_t * const halfH= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\

    OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\

}\

static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## pixels16_ ## MMX(dst, src, stride, 16);\

}\

\

static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[32];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\

}\

\

static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, stride, stride, 16);\

}\

\

static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[32];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, src+1, half, stride, stride, 16);\

}\

\

static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[32];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\

    OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\

}\

\

static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, stride, stride);\

}\

\

static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t temp[32];\

    uint8_t * const half= (uint8_t*)temp;\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\

    OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, stride, stride, 16);\

}\

static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[16*2 + 17*2];\

    uint8_t * const halfH= ((uint8_t*)half) + 256;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\

}\

static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[16*2 + 17*2];\

    uint8_t * const halfH= ((uint8_t*)half) + 256;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\

}\

static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[16*2 + 17*2];\

    uint8_t * const halfH= ((uint8_t*)half) + 256;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\

}\

static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[16*2 + 17*2];\

    uint8_t * const halfH= ((uint8_t*)half) + 256;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\

}\

static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[16*2 + 17*2];\

    uint8_t * const halfH= ((uint8_t*)half) + 256;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\

}\

static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[16*2 + 17*2];\

    uint8_t * const halfH= ((uint8_t*)half) + 256;\

    uint8_t * const halfHV= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\

    OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\

}\

static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[17*2];\

    uint8_t * const halfH= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\

    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\

}\

static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[17*2];\

    uint8_t * const halfH= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\

    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\

}\

static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    uint64_t half[17*2];\

    uint8_t * const halfH= ((uint8_t*)half);\

    put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\

    OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\

}

#define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b "        \n\t"

#define AVG_3DNOW_OP(a,b,temp, size) \

"mov" #size " " #b ", " #temp "   \n\t"\

"pavgusb " #temp ", " #a "        \n\t"\

"mov" #size " " #a ", " #b "      \n\t"

#define AVG_MMX2_OP(a,b,temp, size) \

"mov" #size " " #b ", " #temp "   \n\t"\

"pavgb " #temp ", " #a "          \n\t"\

"mov" #size " " #a ", " #b "      \n\t"

QPEL_BASE(put_       , ff_pw_16, _       , PUT_OP, PUT_OP)

QPEL_BASE(avg_       , ff_pw_16, _       , AVG_MMX2_OP, AVG_3DNOW_OP)

QPEL_BASE(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, PUT_OP)

QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, 3dnow)

QPEL_OP(avg_       , ff_pw_16, _       , AVG_3DNOW_OP, 3dnow)

QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, 3dnow)

QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, mmx2)

QPEL_OP(avg_       , ff_pw_16, _       , AVG_MMX2_OP, mmx2)

QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, mmx2)

/***********************************/

/* bilinear qpel: not compliant to any spec, only for -lavdopts fast */

#define QPEL_2TAP_XY(OPNAME, SIZE, MMX, XY, HPEL)\

static void OPNAME ## 2tap_qpel ## SIZE ## _mc ## XY ## _ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## pixels ## SIZE ## HPEL(dst, src, stride, SIZE);\

}

#define QPEL_2TAP_L3(OPNAME, SIZE, MMX, XY, S0, S1, S2)\

static void OPNAME ## 2tap_qpel ## SIZE ## _mc ## XY ## _ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## 2tap_qpel ## SIZE ## _l3_ ## MMX(dst, src+S0, stride, SIZE, S1, S2);\

}

#define QPEL_2TAP(OPNAME, SIZE, MMX)\

QPEL_2TAP_XY(OPNAME, SIZE, MMX, 20, _x2_ ## MMX)\

QPEL_2TAP_XY(OPNAME, SIZE, MMX, 02, _y2_ ## MMX)\

QPEL_2TAP_XY(OPNAME, SIZE, MMX, 22, _xy2_mmx)\

static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc00_ ## MMX =\

                          OPNAME ## qpel ## SIZE ## _mc00_ ## MMX;\

static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc21_ ## MMX =\

                          OPNAME ## 2tap_qpel ## SIZE ## _mc20_ ## MMX;\

static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc12_ ## MMX =\

                          OPNAME ## 2tap_qpel ## SIZE ## _mc02_ ## MMX;\

static void OPNAME ## 2tap_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## pixels ## SIZE ## _y2_ ## MMX(dst, src+1, stride, SIZE);\

}\

static void OPNAME ## 2tap_qpel ## SIZE ## _mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\

    OPNAME ## pixels ## SIZE ## _x2_ ## MMX(dst, src+stride, stride, SIZE);\

}\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 10, 0,         1,       0)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 30, 1,        -1,       0)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 01, 0,         stride,  0)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 03, stride,   -stride,  0)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 11, 0,         stride,  1)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 31, 1,         stride, -1)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 13, stride,   -stride,  1)\

QPEL_2TAP_L3(OPNAME, SIZE, MMX, 33, stride+1, -stride, -1)\

QPEL_2TAP(put_, 16, mmx2)

QPEL_2TAP(avg_, 16, mmx2)

QPEL_2TAP(put_,  8, mmx2)

QPEL_2TAP(avg_,  8, mmx2)

QPEL_2TAP(put_, 16, 3dnow)

QPEL_2TAP(avg_, 16, 3dnow)

QPEL_2TAP(put_,  8, 3dnow)

QPEL_2TAP(avg_,  8, 3dnow)

#if 0

static void just_return() { return; }

#endif

static void gmc_mmx(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy,

                    int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height){

    const int w = 8;

    const int ix = ox>>(16+shift);

    const int iy = oy>>(16+shift);

    const int oxs = ox>>4;

    const int oys = oy>>4;

    const int dxxs = dxx>>4;

    const int dxys = dxy>>4;

    const int dyxs = dyx>>4;

    const int dyys = dyy>>4;

    const uint16_t r4[4] = {r,r,r,r};

    const uint16_t dxy4[4] = {dxys,dxys,dxys,dxys};

    const uint16_t dyy4[4] = {dyys,dyys,dyys,dyys};

    const uint64_t shift2 = 2*shift;

    uint8_t edge_buf[(h+1)*stride];

    int x, y;

    const int dxw = (dxx-(1<<(16+shift)))*(w-1);

    const int dyh = (dyy-(1<<(16+shift)))*(h-1);

    const int dxh = dxy*(h-1);

    const int dyw = dyx*(w-1);

    if( // non-constant fullpel offset (3% of blocks)

        ((ox^(ox+dxw)) | (ox^(ox+dxh)) | (ox^(ox+dxw+dxh)) |

         (oy^(oy+dyw)) | (oy^(oy+dyh)) | (oy^(oy+dyw+dyh))) >> (16+shift)

        // uses more than 16 bits of subpel mv (only at huge resolution)

        || (dxx|dxy|dyx|dyy)&15 )

    {

        //FIXME could still use mmx for some of the rows

        ff_gmc_c(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r, width, height);

        return;

    }

    src += ix + iy*stride;

    if( (unsigned)ix >= width-w ||

        (unsigned)iy >= height-h )

    {

        ff_emulated_edge_mc(edge_buf, src, stride, w+1, h+1, ix, iy, width, height);

        src = edge_buf;

    }

    asm volatile(

        "movd         %0, %%mm6 \n\t"

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

        "punpcklwd %%mm6, %%mm6 \n\t"

        "punpcklwd %%mm6, %%mm6 \n\t"

        :: "r"(1<<shift)

    );

    for(x=0; x<w; x+=4){

        uint16_t dx4[4] = { oxs - dxys + dxxs*(x+0),

                            oxs - dxys + dxxs*(x+1),

                            oxs - dxys + dxxs*(x+2),

                            oxs - dxys + dxxs*(x+3) };

        uint16_t dy4[4] = { oys - dyys + dyxs*(x+0),

                            oys - dyys + dyxs*(x+1),

                            oys - dyys + dyxs*(x+2),

                            oys - dyys + dyxs*(x+3) };

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

            asm volatile(

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

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

                "paddw  %2,  %%mm4 \n\t"

                "paddw  %3,  %%mm5 \n\t"

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

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

                "psrlw  $12, %%mm4 \n\t"

                "psrlw  $12, %%mm5 \n\t"

                : "+m"(*dx4), "+m"(*dy4)

                : "m"(*dxy4), "m"(*dyy4)

            );

            asm volatile(

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

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

                "psubw  %%mm4, %%mm2 \n\t"

                "psubw  %%mm5, %%mm1 \n\t"

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

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

                "pmullw %%mm1, %%mm0 \n\t" // (s-dx)*(s-dy)

                "pmullw %%mm5, %%mm3 \n\t" // dx*dy

                "pmullw %%mm5, %%mm2 \n\t" // (s-dx)*dy

                "pmullw %%mm4, %%mm1 \n\t" // dx*(s-dy)

                "movd   %4,    %%mm5 \n\t"

                "movd   %3,    %%mm4 \n\t"

                "punpcklbw %%mm7, %%mm5 \n\t"

                "punpcklbw %%mm7, %%mm4 \n\t"

                "pmullw %%mm5, %%mm3 \n\t" // src[1,1] * dx*dy

                "pmullw %%mm4, %%mm2 \n\t" // src[0,1] * (s-dx)*dy

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

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

                "punpcklbw %%mm7, %%mm5 \n\t"

                "punpcklbw %%mm7, %%mm4 \n\t"

                "pmullw %%mm5, %%mm1 \n\t" // src[1,0] * dx*(s-dy)

                "pmullw %%mm4, %%mm0 \n\t" // src[0,0] * (s-dx)*(s-dy)

                "paddw  %5,    %%mm1 \n\t"

                "paddw  %%mm3, %%mm2 \n\t"

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

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

                "psrlw    %6,    %%mm0 \n\t"

                "packuswb %%mm0, %%mm0 \n\t"

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

                : "=m"(dst[x+y*stride])

                : "m"(src[0]), "m"(src[1]),

                  "m"(src[stride]), "m"(src[stride+1]),

                  "m"(*r4), "m"(shift2)

            );

            src += stride;

        }

        src += 4-h*stride;

    }

}


static av_cold void mdct_end(AC3MDCTContext *mdct)

{

    mdct->nbits = 0;

    av_freep(&mdct->costab);

    av_freep(&mdct->sintab);

    av_freep(&mdct->xcos1);

    av_freep(&mdct->xsin1);

    av_freep(&mdct->rot_tmp);

    av_freep(&mdct->cplx_tmp);

}


static void floor_encode(venc_context_t * venc, floor_t * fc, PutBitContext * pb, int * posts, float * floor, int samples) {

    int range = 255 / fc->multiplier + 1;

    int coded[fc->values]; // first 2 values are unused

    int i, counter;

    int lx, ly;

    put_bits(pb, 1, 1); // non zero

    put_bits(pb, ilog(range - 1), posts[0]);

    put_bits(pb, ilog(range - 1), posts[1]);

    for (i = 2; i < fc->values; i++) {

        int predicted = render_point(fc->list[fc->list[i].low].x,

                                     posts[fc->list[i].low],

                                     fc->list[fc->list[i].high].x,

                                     posts[fc->list[i].high],

                                     fc->list[i].x);

        int highroom = range - predicted;

        int lowroom = predicted;

        int room = FFMIN(highroom, lowroom);

        if (predicted == posts[i]) {

            coded[i] = 0; // must be used later as flag!

            continue;

        } else {

            if (!coded[fc->list[i].low]) coded[fc->list[i].low] = -1;

            if (!coded[fc->list[i].high]) coded[fc->list[i].high] = -1;

        }

        if (posts[i] > predicted) {

            if (posts[i] - predicted > room) coded[i] = posts[i] - predicted + lowroom;

            else coded[i] = (posts[i] - predicted) << 1;

        } else {

            if (predicted - posts[i] > room) coded[i] = predicted - posts[i] + highroom - 1;

            else coded[i] = ((predicted - posts[i]) << 1) - 1;

        }

    }

    counter = 2;

    for (i = 0; i < fc->partitions; i++) {

        floor_class_t * c = &fc->classes[fc->partition_to_class[i]];

        int k, cval = 0, csub = 1<<c->subclass;

        if (c->subclass) {

            codebook_t * book = &venc->codebooks[c->masterbook];

            int cshift = 0;

            for (k = 0; k < c->dim; k++) {

                int l;

                for (l = 0; l < csub; l++) {

                    int maxval = 1;

                    if (c->books[l] != -1) maxval = venc->codebooks[c->books[l]].nentries;

                    // coded could be -1, but this still works, cause thats 0

                    if (coded[counter + k] < maxval) break;

                }

                assert(l != csub);

                cval |= l << cshift;

                cshift += c->subclass;

            }

            assert(cval < book->nentries);

            put_bits(pb, book->entries[cval].len, book->entries[cval].codeword);

        }

        for (k = 0; k < c->dim; k++) {

            int book = c->books[cval & (csub-1)];

            int entry = coded[counter++];

            cval >>= c->subclass;

            if (book == -1) continue;

            if (entry == -1) entry = 0;

            assert(entry < venc->codebooks[book].nentries);

            assert(entry >= 0);

            put_bits(pb, venc->codebooks[book].entries[entry].len, venc->codebooks[book].entries[entry].codeword);

        }

    }

    lx = 0;

    ly = posts[0] * fc->multiplier; // sorted 0 is still 0

    coded[0] = coded[1] = 1;

    for (i = 1; i < fc->values; i++) {

        int pos = fc->list[i].sort;

        if (coded[pos]) {

            render_line(lx, ly, fc->list[pos].x, posts[pos] * fc->multiplier, floor, samples);

            lx = fc->list[pos].x;

            ly = posts[pos] * fc->multiplier;

        }

        if (lx >= samples) break;

    }

    if (lx < samples) render_line(lx, ly, samples, ly, floor, samples);

}


dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,

                    IPin *pin, int *pformat_set)

{

    struct dshow_ctx *ctx = avctx->priv_data;

    IAMStreamConfig *config = NULL;

    AM_MEDIA_TYPE *type = NULL;

    int format_set = 0;

    void *caps = NULL;

    int i, n, size;

    if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)

        return;

    if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)

        goto end;

    caps = av_malloc(size);

    if (!caps)

        goto end;

    for (i = 0; i < n && !format_set; i++) {

        IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);

#if DSHOWDEBUG

        ff_print_AM_MEDIA_TYPE(type);

#endif

        if (devtype == VideoDevice) {

            VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;

            BITMAPINFOHEADER *bih;

            int64_t *fr;

            const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };

#if DSHOWDEBUG

            ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);

#endif

            if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {

                VIDEOINFOHEADER *v = (void *) type->pbFormat;

                fr = &v->AvgTimePerFrame;

                bih = &v->bmiHeader;

            } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {

                VIDEOINFOHEADER2 *v = (void *) type->pbFormat;

                fr = &v->AvgTimePerFrame;

                bih = &v->bmiHeader;

            } else {

                goto next;

            }

            if (!pformat_set) {

                enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);

                if (pix_fmt == AV_PIX_FMT_NONE) {

                    enum AVCodecID codec_id = av_codec_get_id(tags, bih->biCompression);

                    AVCodec *codec = avcodec_find_decoder(codec_id);

                    if (codec_id == AV_CODEC_ID_NONE || !codec) {

                        av_log(avctx, AV_LOG_INFO, "  unknown compression type 0x%X", (int) bih->biCompression);

                    } else {

                        av_log(avctx, AV_LOG_INFO, "  vcodec=%s", codec->name);

                    }

                } else {

                    av_log(avctx, AV_LOG_INFO, "  pixel_format=%s", av_get_pix_fmt_name(pix_fmt));

                }

                av_log(avctx, AV_LOG_INFO, "  min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",

                       vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,

                       1e7 / vcaps->MaxFrameInterval,

                       vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,

                       1e7 / vcaps->MinFrameInterval);

                continue;

            }

            if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {

                if (ctx->video_codec_id != av_codec_get_id(tags, bih->biCompression))

                    goto next;

            }

            if (ctx->pixel_format != AV_PIX_FMT_NONE &&

                ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {

                goto next;

            }

            if (ctx->framerate) {

                int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)

                                            /  ctx->requested_framerate.num;

                if (framerate > vcaps->MaxFrameInterval ||

                    framerate < vcaps->MinFrameInterval)

                    goto next;

                *fr = framerate;

            }

            if (ctx->requested_width && ctx->requested_height) {

                if (ctx->requested_width  > vcaps->MaxOutputSize.cx ||

                    ctx->requested_width  < vcaps->MinOutputSize.cx ||

                    ctx->requested_height > vcaps->MaxOutputSize.cy ||

                    ctx->requested_height < vcaps->MinOutputSize.cy)

                    goto next;

                bih->biWidth  = ctx->requested_width;

                bih->biHeight = ctx->requested_height;

            }

        } else {

            AUDIO_STREAM_CONFIG_CAPS *acaps = caps;

            WAVEFORMATEX *fx;

#if DSHOWDEBUG

            ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);

#endif

            if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {

                fx = (void *) type->pbFormat;

            } else {

                goto next;

            }

            if (!pformat_set) {

                av_log(avctx, AV_LOG_INFO, "  min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",

                       acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,

                       acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);

                continue;

            }

            if (ctx->sample_rate) {

                if (ctx->sample_rate > acaps->MaximumSampleFrequency ||

                    ctx->sample_rate < acaps->MinimumSampleFrequency)

                    goto next;

                fx->nSamplesPerSec = ctx->sample_rate;

            }

            if (ctx->sample_size) {

                if (ctx->sample_size > acaps->MaximumBitsPerSample ||

                    ctx->sample_size < acaps->MinimumBitsPerSample)

                    goto next;

                fx->wBitsPerSample = ctx->sample_size;

            }

            if (ctx->channels) {

                if (ctx->channels > acaps->MaximumChannels ||

                    ctx->channels < acaps->MinimumChannels)

                    goto next;

                fx->nChannels = ctx->channels;

            }

        }

        if (IAMStreamConfig_SetFormat(config, type) != S_OK)

            goto next;

        format_set = 1;

next:

        if (type->pbFormat)

            CoTaskMemFree(type->pbFormat);

        CoTaskMemFree(type);

    }

end:

    IAMStreamConfig_Release(config);

    if (caps)

        av_free(caps);

    if (pformat_set)

        *pformat_set = format_set;

}


static void usbredir_log_data(USBRedirDevice *dev, const char *desc,

    const uint8_t *data, int len)

{

    int i, j, n;

    if (dev->debug < usbredirparser_debug_data) {

        return;

    }

    for (i = 0; i < len; i += j) {

        char buf[128];

        n = sprintf(buf, "%s", desc);

        for (j = 0; j < 8 && i + j < len; j++) {

            n += sprintf(buf + n, " %02X", data[i + j]);

        }

        error_report("%s", buf);

    }

}


static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)

{

    DeviceClass *dc = DEVICE_CLASS(klass);

    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = typhoon_pcihost_init;

    dc->no_user = 1;

}


static int mp_decode_frame(MPADecodeContext *s,

                           OUT_INT *samples, const uint8_t *buf, int buf_size)

{

    int i, nb_frames, ch;

    OUT_INT *samples_ptr;

    init_get_bits(&s->gb, buf + HEADER_SIZE, (buf_size - HEADER_SIZE)*8);

    /* skip error protection field */

    if (s->error_protection)

        skip_bits(&s->gb, 16);

    dprintf(s->avctx, "frame %d:\n", s->frame_count);

    switch(s->layer) {

    case 1:

        s->avctx->frame_size = 384;

        nb_frames = mp_decode_layer1(s);

        break;

    case 2:

        s->avctx->frame_size = 1152;

        nb_frames = mp_decode_layer2(s);

        break;

    case 3:

        s->avctx->frame_size = s->lsf ? 576 : 1152;

    default:

        nb_frames = mp_decode_layer3(s);

        s->last_buf_size=0;

        if(s->in_gb.buffer){

            align_get_bits(&s->gb);

            i= (s->gb.size_in_bits - get_bits_count(&s->gb))>>3;

            if(i >= 0 && i <= BACKSTEP_SIZE){

                memmove(s->last_buf, s->gb.buffer + (get_bits_count(&s->gb)>>3), i);

                s->last_buf_size=i;

            }else

                av_log(s->avctx, AV_LOG_ERROR, "invalid old backstep %d\n", i);

            s->gb= s->in_gb;

            s->in_gb.buffer= NULL;

        }

        align_get_bits(&s->gb);

        assert((get_bits_count(&s->gb) & 7) == 0);

        i= (s->gb.size_in_bits - get_bits_count(&s->gb))>>3;

        if(i<0 || i > BACKSTEP_SIZE || nb_frames<0){

            av_log(s->avctx, AV_LOG_WARNING, "invalid new backstep %d\n", i);

            i= FFMIN(BACKSTEP_SIZE, buf_size - HEADER_SIZE);

        }

        assert(i <= buf_size - HEADER_SIZE && i>= 0);

        memcpy(s->last_buf + s->last_buf_size, s->gb.buffer + buf_size - HEADER_SIZE - i, i);

        s->last_buf_size += i;

        break;

    }

    /* apply the synthesis filter */

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

        samples_ptr = samples + ch;

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

            ff_mpa_synth_filter(s->synth_buf[ch], &(s->synth_buf_offset[ch]),

                         window, &s->dither_state,

                         samples_ptr, s->nb_channels,

                         s->sb_samples[ch][i]);

            samples_ptr += 32 * s->nb_channels;

        }

    }

    return nb_frames * 32 * sizeof(OUT_INT) * s->nb_channels;

}