]> git.sesse.net Git - vlc/blob - modules/codec/xvmc/motion_comp_mmx.c
Support for UDP-Lite (with full checksum coverage only atm)
[vlc] / modules / codec / xvmc / motion_comp_mmx.c
1 /* $Id$
2  * motion_comp_mmx.c
3  * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
4  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
5  *
6  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
7  * See http://libmpeg2.sourceforge.net/ for updates.
8  *
9  * mpeg2dec is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * mpeg2dec is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25
26 #include <inttypes.h>
27
28 #include "mpeg2.h"
29 #include "attributes.h"
30 #include "mpeg2_internal.h"
31 #include "mmx.h"
32
33 #define CPU_MMXEXT 0
34 #define CPU_3DNOW 1
35
36 /* MMX code - needs a rewrite */
37
38 /*
39  * Motion Compensation frequently needs to average values using the
40  * formula (x+y+1)>>1. Both MMXEXT and 3Dnow include one instruction
41  * to compute this, but it's been left out of classic MMX.
42  *
43  * We need to be careful of overflows when doing this computation.
44  * Rather than unpacking data to 16-bits, which reduces parallelism,
45  * we use the following formulas:
46  *
47  * (x+y)>>1 == (x&y)+((x^y)>>1)
48  * (x+y+1)>>1 == (x|y)-((x^y)>>1)
49  */
50
51 /* some rounding constants */
52 static mmx_t mask1 = {0xfefefefefefefefeLL};
53 static mmx_t round4 = {0x0002000200020002LL};
54
55 /*
56  * This code should probably be compiled with loop unrolling
57  * (ie, -funroll-loops in gcc)becuase some of the loops
58  * use a small static number of iterations. This was written
59  * with the assumption the compiler knows best about when
60  * unrolling will help
61  */
62
63 static inline void mmx_zero_reg ()
64 {
65     /* load 0 into mm0 */
66     pxor_r2r (mm0, mm0);
67 }
68
69 static inline void mmx_average_2_U8 (uint8_t * dest, const uint8_t * src1,
70                                      const uint8_t * src2)
71 {
72     /* *dest = (*src1 + *src2 + 1)/ 2; */
73
74     movq_m2r (*src1, mm1);      /* load 8 src1 bytes */
75     movq_r2r (mm1, mm2);        /* copy 8 src1 bytes */
76
77     movq_m2r (*src2, mm3);      /* load 8 src2 bytes */
78     movq_r2r (mm3, mm4);        /* copy 8 src2 bytes */
79
80     pxor_r2r (mm1, mm3);        /* xor src1 and src2 */
81     pand_m2r (mask1, mm3);      /* mask lower bits */
82     psrlq_i2r (1, mm3);         /* /2 */
83     por_r2r (mm2, mm4);         /* or src1 and src2 */
84     psubb_r2r (mm3, mm4);       /* subtract subresults */
85     movq_r2m (mm4, *dest);      /* store result in dest */
86 }
87
88 static inline void mmx_interp_average_2_U8 (uint8_t * dest,
89                                             const uint8_t * src1,
90                                             const uint8_t * src2)
91 {
92     /* *dest = (*dest + (*src1 + *src2 + 1)/ 2 + 1)/ 2; */
93
94     movq_m2r (*dest, mm1);      /* load 8 dest bytes */
95     movq_r2r (mm1, mm2);        /* copy 8 dest bytes */
96
97     movq_m2r (*src1, mm3);      /* load 8 src1 bytes */
98     movq_r2r (mm3, mm4);        /* copy 8 src1 bytes */
99
100     movq_m2r (*src2, mm5);      /* load 8 src2 bytes */
101     movq_r2r (mm5, mm6);        /* copy 8 src2 bytes */
102
103     pxor_r2r (mm3, mm5);        /* xor src1 and src2 */
104     pand_m2r (mask1, mm5);      /* mask lower bits */
105     psrlq_i2r (1, mm5);         /* /2 */
106     por_r2r (mm4, mm6);         /* or src1 and src2 */
107     psubb_r2r (mm5, mm6);       /* subtract subresults */
108     movq_r2r (mm6, mm5);        /* copy subresult */
109
110     pxor_r2r (mm1, mm5);        /* xor srcavg and dest */
111     pand_m2r (mask1, mm5);      /* mask lower bits */
112     psrlq_i2r (1, mm5);         /* /2 */
113     por_r2r (mm2, mm6);         /* or srcavg and dest */
114     psubb_r2r (mm5, mm6);       /* subtract subresults */
115     movq_r2m (mm6, *dest);      /* store result in dest */
116 }
117
118 static inline void mmx_average_4_U8 (uint8_t * dest, const uint8_t * src1,
119                                      const uint8_t * src2,
120                                      const uint8_t * src3,
121                                      const uint8_t * src4)
122 {
123     /* *dest = (*src1 + *src2 + *src3 + *src4 + 2)/ 4; */
124
125     movq_m2r (*src1, mm1);      /* load 8 src1 bytes */
126     movq_r2r (mm1, mm2);        /* copy 8 src1 bytes */
127
128     punpcklbw_r2r (mm0, mm1);   /* unpack low src1 bytes */
129     punpckhbw_r2r (mm0, mm2);   /* unpack high src1 bytes */
130
131     movq_m2r (*src2, mm3);      /* load 8 src2 bytes */
132     movq_r2r (mm3, mm4);        /* copy 8 src2 bytes */
133
134     punpcklbw_r2r (mm0, mm3);   /* unpack low src2 bytes */
135     punpckhbw_r2r (mm0, mm4);   /* unpack high src2 bytes */
136
137     paddw_r2r (mm3, mm1);       /* add lows */
138     paddw_r2r (mm4, mm2);       /* add highs */
139
140     /* now have partials in mm1 and mm2 */
141
142     movq_m2r (*src3, mm3);      /* load 8 src3 bytes */
143     movq_r2r (mm3, mm4);        /* copy 8 src3 bytes */
144
145     punpcklbw_r2r (mm0, mm3);   /* unpack low src3 bytes */
146     punpckhbw_r2r (mm0, mm4);   /* unpack high src3 bytes */
147
148     paddw_r2r (mm3, mm1);       /* add lows */
149     paddw_r2r (mm4, mm2);       /* add highs */
150
151     movq_m2r (*src4, mm5);      /* load 8 src4 bytes */
152     movq_r2r (mm5, mm6);        /* copy 8 src4 bytes */
153
154     punpcklbw_r2r (mm0, mm5);   /* unpack low src4 bytes */
155     punpckhbw_r2r (mm0, mm6);   /* unpack high src4 bytes */
156
157     paddw_r2r (mm5, mm1);       /* add lows */
158     paddw_r2r (mm6, mm2);       /* add highs */
159
160     /* now have subtotal in mm1 and mm2 */
161
162     paddw_m2r (round4, mm1);
163     psraw_i2r (2, mm1);         /* /4 */
164     paddw_m2r (round4, mm2);
165     psraw_i2r (2, mm2);         /* /4 */
166
167     packuswb_r2r (mm2, mm1);    /* pack (w/ saturation) */
168     movq_r2m (mm1, *dest);      /* store result in dest */
169 }
170
171 static inline void mmx_interp_average_4_U8 (uint8_t * dest,
172                                             const uint8_t * src1,
173                                             const uint8_t * src2,
174                                             const uint8_t * src3,
175                                             const uint8_t * src4)
176 {
177     /* *dest = (*dest + (*src1 + *src2 + *src3 + *src4 + 2)/ 4 + 1)/ 2; */
178
179     movq_m2r (*src1, mm1);      /* load 8 src1 bytes */
180     movq_r2r (mm1, mm2);        /* copy 8 src1 bytes */
181
182     punpcklbw_r2r (mm0, mm1);   /* unpack low src1 bytes */
183     punpckhbw_r2r (mm0, mm2);   /* unpack high src1 bytes */
184
185     movq_m2r (*src2, mm3);      /* load 8 src2 bytes */
186     movq_r2r (mm3, mm4);        /* copy 8 src2 bytes */
187
188     punpcklbw_r2r (mm0, mm3);   /* unpack low src2 bytes */
189     punpckhbw_r2r (mm0, mm4);   /* unpack high src2 bytes */
190
191     paddw_r2r (mm3, mm1);       /* add lows */
192     paddw_r2r (mm4, mm2);       /* add highs */
193
194     /* now have partials in mm1 and mm2 */
195
196     movq_m2r (*src3, mm3);      /* load 8 src3 bytes */
197     movq_r2r (mm3, mm4);        /* copy 8 src3 bytes */
198
199     punpcklbw_r2r (mm0, mm3);   /* unpack low src3 bytes */
200     punpckhbw_r2r (mm0, mm4);   /* unpack high src3 bytes */
201
202     paddw_r2r (mm3, mm1);       /* add lows */
203     paddw_r2r (mm4, mm2);       /* add highs */
204
205     movq_m2r (*src4, mm5);      /* load 8 src4 bytes */
206     movq_r2r (mm5, mm6);        /* copy 8 src4 bytes */
207
208     punpcklbw_r2r (mm0, mm5);   /* unpack low src4 bytes */
209     punpckhbw_r2r (mm0, mm6);   /* unpack high src4 bytes */
210
211     paddw_r2r (mm5, mm1);       /* add lows */
212     paddw_r2r (mm6, mm2);       /* add highs */
213
214     paddw_m2r (round4, mm1);
215     psraw_i2r (2, mm1);         /* /4 */
216     paddw_m2r (round4, mm2);
217     psraw_i2r (2, mm2);         /* /4 */
218
219     /* now have subtotal/4 in mm1 and mm2 */
220
221     movq_m2r (*dest, mm3);      /* load 8 dest bytes */
222     movq_r2r (mm3, mm4);        /* copy 8 dest bytes */
223
224     packuswb_r2r (mm2, mm1);    /* pack (w/ saturation) */
225     movq_r2r (mm1,mm2);         /* copy subresult */
226
227     pxor_r2r (mm1, mm3);        /* xor srcavg and dest */
228     pand_m2r (mask1, mm3);      /* mask lower bits */
229     psrlq_i2r (1, mm3);         /* /2 */
230     por_r2r (mm2, mm4);         /* or srcavg and dest */
231     psubb_r2r (mm3, mm4);       /* subtract subresults */
232     movq_r2m (mm4, *dest);      /* store result in dest */
233 }
234
235 /*-----------------------------------------------------------------------*/
236
237 static inline void MC_avg_mmx (const int width, int height, uint8_t * dest,
238                                const uint8_t * ref, const int stride)
239 {
240     mmx_zero_reg ();
241
242     do
243     {
244         mmx_average_2_U8 (dest, dest, ref);
245
246         if (width == 16)
247             mmx_average_2_U8 (dest+8, dest+8, ref+8);
248
249         dest += stride;
250         ref += stride;
251     } while( --height );
252 }
253
254 static void MC_avg_o_16_mmx (uint8_t * dest, const uint8_t * ref,
255                              int stride, int height)
256 {
257     MC_avg_mmx (16, height, dest, ref, stride);
258 }
259
260 static void MC_avg_o_8_mmx (uint8_t * dest, const uint8_t * ref,
261                             int stride, int height)
262 {
263     MC_avg_mmx (8, height, dest, ref, stride);
264 }
265
266 /*-----------------------------------------------------------------------*/
267
268 static inline void MC_put_mmx (const int width, int height, uint8_t * dest,
269                                const uint8_t * ref, const int stride)
270 {
271     mmx_zero_reg ();
272
273     do
274     {
275         movq_m2r (* ref, mm1);  /* load 8 ref bytes */
276         movq_r2m (mm1,* dest);  /* store 8 bytes at curr */
277
278         if( width == 16 )
279         {
280             movq_m2r (* (ref+8), mm1);  /* load 8 ref bytes */
281             movq_r2m (mm1,* (dest+8));  /* store 8 bytes at curr */
282         }
283         dest += stride;
284         ref += stride;
285     } while( --height );
286 }
287
288 static void MC_put_o_16_mmx (uint8_t * dest, const uint8_t * ref,
289                              int stride, int height)
290 {
291     MC_put_mmx (16, height, dest, ref, stride);
292 }
293
294 static void MC_put_o_8_mmx (uint8_t * dest, const uint8_t * ref,
295                             int stride, int height)
296 {
297     MC_put_mmx (8, height, dest, ref, stride);
298 }
299
300 /*-----------------------------------------------------------------------*/
301
302 /* Half pixel interpolation in the x direction */
303 static inline void MC_avg_x_mmx (const int width, int height, uint8_t * dest,
304                                  const uint8_t * ref, const int stride)
305 {
306     mmx_zero_reg ();
307
308     do
309     {
310         mmx_interp_average_2_U8 (dest, ref, ref+1);
311
312         if (width == 16)
313             mmx_interp_average_2_U8 (dest+8, ref+8, ref+9);
314
315         dest += stride;
316         ref += stride;
317     } while( --height );
318 }
319
320 static void MC_avg_x_16_mmx (uint8_t * dest, const uint8_t * ref,
321                              int stride, int height)
322 {
323     MC_avg_x_mmx (16, height, dest, ref, stride);
324 }
325
326 static void MC_avg_x_8_mmx (uint8_t * dest, const uint8_t * ref,
327                             int stride, int height)
328 {
329     MC_avg_x_mmx (8, height, dest, ref, stride);
330 }
331
332 /*-----------------------------------------------------------------------*/
333
334 static inline void MC_put_x_mmx (const int width, int height, uint8_t * dest,
335                                  const uint8_t * ref, const int stride)
336 {
337     mmx_zero_reg ();
338
339     do
340     {
341         mmx_average_2_U8 (dest, ref, ref+1);
342
343         if (width == 16)
344             mmx_average_2_U8 (dest+8, ref+8, ref+9);
345
346         dest += stride;
347         ref += stride;
348     } while (--height);
349 }
350
351 static void MC_put_x_16_mmx (uint8_t * dest, const uint8_t * ref,
352                              int stride, int height)
353 {
354     MC_put_x_mmx (16, height, dest, ref, stride);
355 }
356
357 static void MC_put_x_8_mmx (uint8_t * dest, const uint8_t * ref,
358                             int stride, int height)
359 {
360     MC_put_x_mmx (8, height, dest, ref, stride);
361 }
362
363 /*-----------------------------------------------------------------------*/
364
365 static inline void MC_avg_xy_mmx (const int width, int height, uint8_t * dest,
366                                   const uint8_t * ref, const int stride)
367 {
368     const uint8_t * ref_next = ref + stride;
369
370     mmx_zero_reg ();
371
372     do
373     {
374         mmx_interp_average_4_U8 (dest, ref, ref+1, ref_next, ref_next+1);
375
376         if (width == 16)
377             mmx_interp_average_4_U8( dest+8, ref+8, ref+9,
378                                      ref_next+8, ref_next+9 );
379
380         dest += stride;
381         ref += stride;
382         ref_next += stride;
383     } while( --height );
384 }
385
386 static void MC_avg_xy_16_mmx (uint8_t * dest, const uint8_t * ref,
387                               int stride, int height)
388 {
389     MC_avg_xy_mmx (16, height, dest, ref, stride);
390 }
391
392 static void MC_avg_xy_8_mmx (uint8_t * dest, const uint8_t * ref,
393                              int stride, int height)
394 {
395     MC_avg_xy_mmx (8, height, dest, ref, stride);
396 }
397
398 /*-----------------------------------------------------------------------*/
399
400 static inline void MC_put_xy_mmx (const int width, int height, uint8_t * dest,
401                                   const uint8_t * ref, const int stride)
402 {
403     const uint8_t * ref_next = ref + stride;
404
405     mmx_zero_reg ();
406
407     do
408     {
409         mmx_average_4_U8 (dest, ref, ref+1, ref_next, ref_next+1);
410
411         if (width == 16)
412             mmx_average_4_U8( dest+8, ref+8, ref+9, ref_next+8, ref_next+9 );
413
414         dest += stride;
415         ref += stride;
416         ref_next += stride;
417     } while (--height);
418 }
419
420 static void MC_put_xy_16_mmx (uint8_t * dest, const uint8_t * ref,
421                               int stride, int height)
422 {
423     MC_put_xy_mmx (16, height, dest, ref, stride);
424 }
425
426 static void MC_put_xy_8_mmx (uint8_t * dest, const uint8_t * ref,
427                              int stride, int height)
428 {
429     MC_put_xy_mmx (8, height, dest, ref, stride);
430 }
431
432 /*-----------------------------------------------------------------------*/
433
434 static inline void MC_avg_y_mmx (const int width, int height, uint8_t * dest,
435                                  const uint8_t * ref, const int stride)
436 {
437     const uint8_t * ref_next = ref + stride;
438
439     mmx_zero_reg ();
440
441     do
442     {
443         mmx_interp_average_2_U8 (dest, ref, ref_next);
444
445         if (width == 16)
446             mmx_interp_average_2_U8( dest+8, ref+8, ref_next+8 );
447
448         dest += stride;
449         ref += stride;
450         ref_next += stride;
451     } while (--height);
452 }
453
454 static void MC_avg_y_16_mmx (uint8_t * dest, const uint8_t * ref,
455                              int stride, int height)
456 {
457     MC_avg_y_mmx (16, height, dest, ref, stride);
458 }
459
460 static void MC_avg_y_8_mmx (uint8_t * dest, const uint8_t * ref,
461                             int stride, int height)
462 {
463     MC_avg_y_mmx (8, height, dest, ref, stride);
464 }
465
466 /*-----------------------------------------------------------------------*/
467
468 static inline void MC_put_y_mmx (const int width, int height, uint8_t * dest,
469                                  const uint8_t * ref, const int stride)
470 {
471     const uint8_t * ref_next = ref + stride;
472
473     mmx_zero_reg ();
474
475     do
476     {
477         mmx_average_2_U8 (dest, ref, ref_next);
478
479         if (width == 16)
480             mmx_average_2_U8( dest+8, ref+8, ref_next+8 );
481
482         dest += stride;
483         ref += stride;
484         ref_next += stride;
485     } while (--height);
486 }
487
488 static void MC_put_y_16_mmx (uint8_t * dest, const uint8_t * ref,
489                              int stride, int height)
490 {
491     MC_put_y_mmx (16, height, dest, ref, stride);
492 }
493
494 static void MC_put_y_8_mmx (uint8_t * dest, const uint8_t * ref,
495                             int stride, int height)
496 {
497     MC_put_y_mmx (8, height, dest, ref, stride);
498 }
499
500
501 MPEG2_MC_EXTERN (mmx)
502
503 /* CPU_MMXEXT/CPU_3DNOW adaptation layer */
504
505 #define pavg_r2r(src,dest)              \
506 do {                                    \
507     if (cpu == CPU_MMXEXT)              \
508         pavgb_r2r (src, dest);          \
509     else                                \
510         pavgusb_r2r (src, dest);        \
511 } while (0)
512
513 #define pavg_m2r(src,dest)              \
514 do {                                    \
515     if (cpu == CPU_MMXEXT)              \
516         pavgb_m2r (src, dest);          \
517     else                                \
518         pavgusb_m2r (src, dest);        \
519 } while (0)
520
521
522 /* CPU_MMXEXT code */
523
524
525 static inline void MC_put1_8 (int height, uint8_t * dest, const uint8_t * ref,
526                               const int stride)
527 {
528     do {
529         movq_m2r (*ref, mm0);
530         movq_r2m (mm0, *dest);
531         ref += stride;
532         dest += stride;
533     } while (--height);
534 }
535
536 static inline void MC_put1_16 (int height, uint8_t * dest, const uint8_t * ref,
537                                const int stride)
538 {
539     do {
540         movq_m2r (*ref, mm0);
541         movq_m2r (*(ref+8), mm1);
542         ref += stride;
543         movq_r2m (mm0, *dest);
544         movq_r2m (mm1, *(dest+8));
545         dest += stride;
546     } while (--height);
547 }
548
549 static inline void MC_avg1_8 (int height, uint8_t * dest, const uint8_t * ref,
550                               const int stride, const int cpu)
551 {
552     do {
553         movq_m2r (*ref, mm0);
554         pavg_m2r (*dest, mm0);
555         ref += stride;
556         movq_r2m (mm0, *dest);
557         dest += stride;
558     } while (--height);
559 }
560
561 static inline void MC_avg1_16 (int height, uint8_t * dest, const uint8_t * ref,
562                                const int stride, const int cpu)
563 {
564     do {
565         movq_m2r (*ref, mm0);
566         movq_m2r (*(ref+8), mm1);
567         pavg_m2r (*dest, mm0);
568         pavg_m2r (*(dest+8), mm1);
569         movq_r2m (mm0, *dest);
570         ref += stride;
571         movq_r2m (mm1, *(dest+8));
572         dest += stride;
573     } while (--height);
574 }
575
576 static inline void MC_put2_8 (int height, uint8_t * dest, const uint8_t * ref,
577                               const int stride, const int offset,
578                               const int cpu)
579 {
580     do {
581         movq_m2r (*ref, mm0);
582         pavg_m2r (*(ref+offset), mm0);
583         ref += stride;
584         movq_r2m (mm0, *dest);
585         dest += stride;
586     } while (--height);
587 }
588
589 static inline void MC_put2_16 (int height, uint8_t * dest, const uint8_t * ref,
590                                const int stride, const int offset,
591                                const int cpu)
592 {
593     do {
594         movq_m2r (*ref, mm0);
595         movq_m2r (*(ref+8), mm1);
596         pavg_m2r (*(ref+offset), mm0);
597         pavg_m2r (*(ref+offset+8), mm1);
598         movq_r2m (mm0, *dest);
599         ref += stride;
600         movq_r2m (mm1, *(dest+8));
601         dest += stride;
602     } while (--height);
603 }
604
605 static inline void MC_avg2_8 (int height, uint8_t * dest, const uint8_t * ref,
606                               const int stride, const int offset,
607                               const int cpu)
608 {
609     do {
610         movq_m2r (*ref, mm0);
611         pavg_m2r (*(ref+offset), mm0);
612         pavg_m2r (*dest, mm0);
613         ref += stride;
614         movq_r2m (mm0, *dest);
615         dest += stride;
616     } while (--height);
617 }
618
619 static inline void MC_avg2_16 (int height, uint8_t * dest, const uint8_t * ref,
620                                const int stride, const int offset,
621                                const int cpu)
622 {
623     do {
624         movq_m2r (*ref, mm0);
625         movq_m2r (*(ref+8), mm1);
626         pavg_m2r (*(ref+offset), mm0);
627         pavg_m2r (*(ref+offset+8), mm1);
628         pavg_m2r (*dest, mm0);
629         pavg_m2r (*(dest+8), mm1);
630         ref += stride;
631         movq_r2m (mm0, *dest);
632         movq_r2m (mm1, *(dest+8));
633         dest += stride;
634     } while (--height);
635 }
636
637 static mmx_t mask_one = {0x0101010101010101LL};
638
639 static inline void MC_put4_8 (int height, uint8_t * dest, const uint8_t * ref,
640                               const int stride, const int cpu)
641 {
642     movq_m2r (*ref, mm0);
643     movq_m2r (*(ref+1), mm1);
644     movq_r2r (mm0, mm7);
645     pxor_r2r (mm1, mm7);
646     pavg_r2r (mm1, mm0);
647     ref += stride;
648
649     do {
650         movq_m2r (*ref, mm2);
651         movq_r2r (mm0, mm5);
652
653         movq_m2r (*(ref+1), mm3);
654         movq_r2r (mm2, mm6);
655
656         pxor_r2r (mm3, mm6);
657         pavg_r2r (mm3, mm2);
658
659         por_r2r (mm6, mm7);
660         pxor_r2r (mm2, mm5);
661
662         pand_r2r (mm5, mm7);
663         pavg_r2r (mm2, mm0);
664
665         pand_m2r (mask_one, mm7);
666
667         psubusb_r2r (mm7, mm0);
668
669         ref += stride;
670         movq_r2m (mm0, *dest);
671         dest += stride;
672
673         movq_r2r (mm6, mm7);    /* unroll ! */
674         movq_r2r (mm2, mm0);    /* unroll ! */
675     } while (--height);
676 }
677
678 static inline void MC_put4_16 (int height, uint8_t * dest, const uint8_t * ref,
679                                const int stride, const int cpu)
680 {
681     do {
682         movq_m2r (*ref, mm0);
683         movq_m2r (*(ref+stride+1), mm1);
684         movq_r2r (mm0, mm7);
685         movq_m2r (*(ref+1), mm2);
686         pxor_r2r (mm1, mm7);
687         movq_m2r (*(ref+stride), mm3);
688         movq_r2r (mm2, mm6);
689         pxor_r2r (mm3, mm6);
690         pavg_r2r (mm1, mm0);
691         pavg_r2r (mm3, mm2);
692         por_r2r (mm6, mm7);
693         movq_r2r (mm0, mm6);
694         pxor_r2r (mm2, mm6);
695         pand_r2r (mm6, mm7);
696         pand_m2r (mask_one, mm7);
697         pavg_r2r (mm2, mm0);
698         psubusb_r2r (mm7, mm0);
699         movq_r2m (mm0, *dest);
700
701         movq_m2r (*(ref+8), mm0);
702         movq_m2r (*(ref+stride+9), mm1);
703         movq_r2r (mm0, mm7);
704         movq_m2r (*(ref+9), mm2);
705         pxor_r2r (mm1, mm7);
706         movq_m2r (*(ref+stride+8), mm3);
707         movq_r2r (mm2, mm6);
708         pxor_r2r (mm3, mm6);
709         pavg_r2r (mm1, mm0);
710         pavg_r2r (mm3, mm2);
711         por_r2r (mm6, mm7);
712         movq_r2r (mm0, mm6);
713         pxor_r2r (mm2, mm6);
714         pand_r2r (mm6, mm7);
715         pand_m2r (mask_one, mm7);
716         pavg_r2r (mm2, mm0);
717         psubusb_r2r (mm7, mm0);
718         ref += stride;
719         movq_r2m (mm0, *(dest+8));
720         dest += stride;
721     } while (--height);
722 }
723
724 static inline void MC_avg4_8 (int height, uint8_t * dest, const uint8_t * ref,
725                               const int stride, const int cpu)
726 {
727     do {
728         movq_m2r (*ref, mm0);
729         movq_m2r (*(ref+stride+1), mm1);
730         movq_r2r (mm0, mm7);
731         movq_m2r (*(ref+1), mm2);
732         pxor_r2r (mm1, mm7);
733         movq_m2r (*(ref+stride), mm3);
734         movq_r2r (mm2, mm6);
735         pxor_r2r (mm3, mm6);
736         pavg_r2r (mm1, mm0);
737         pavg_r2r (mm3, mm2);
738         por_r2r (mm6, mm7);
739         movq_r2r (mm0, mm6);
740         pxor_r2r (mm2, mm6);
741         pand_r2r (mm6, mm7);
742         pand_m2r (mask_one, mm7);
743         pavg_r2r (mm2, mm0);
744         psubusb_r2r (mm7, mm0);
745         movq_m2r (*dest, mm1);
746         pavg_r2r (mm1, mm0);
747         ref += stride;
748         movq_r2m (mm0, *dest);
749         dest += stride;
750     } while (--height);
751 }
752
753 static inline void MC_avg4_16 (int height, uint8_t * dest, const uint8_t * ref,
754                                const int stride, const int cpu)
755 {
756     do {
757         movq_m2r (*ref, mm0);
758         movq_m2r (*(ref+stride+1), mm1);
759         movq_r2r (mm0, mm7);
760         movq_m2r (*(ref+1), mm2);
761         pxor_r2r (mm1, mm7);
762         movq_m2r (*(ref+stride), mm3);
763         movq_r2r (mm2, mm6);
764         pxor_r2r (mm3, mm6);
765         pavg_r2r (mm1, mm0);
766         pavg_r2r (mm3, mm2);
767         por_r2r (mm6, mm7);
768         movq_r2r (mm0, mm6);
769         pxor_r2r (mm2, mm6);
770         pand_r2r (mm6, mm7);
771         pand_m2r (mask_one, mm7);
772         pavg_r2r (mm2, mm0);
773         psubusb_r2r (mm7, mm0);
774         movq_m2r (*dest, mm1);
775         pavg_r2r (mm1, mm0);
776         movq_r2m (mm0, *dest);
777
778         movq_m2r (*(ref+8), mm0);
779         movq_m2r (*(ref+stride+9), mm1);
780         movq_r2r (mm0, mm7);
781         movq_m2r (*(ref+9), mm2);
782         pxor_r2r (mm1, mm7);
783         movq_m2r (*(ref+stride+8), mm3);
784         movq_r2r (mm2, mm6);
785         pxor_r2r (mm3, mm6);
786         pavg_r2r (mm1, mm0);
787         pavg_r2r (mm3, mm2);
788         por_r2r (mm6, mm7);
789         movq_r2r (mm0, mm6);
790         pxor_r2r (mm2, mm6);
791         pand_r2r (mm6, mm7);
792         pand_m2r (mask_one, mm7);
793         pavg_r2r (mm2, mm0);
794         psubusb_r2r (mm7, mm0);
795         movq_m2r (*(dest+8), mm1);
796         pavg_r2r (mm1, mm0);
797         ref += stride;
798         movq_r2m (mm0, *(dest+8));
799         dest += stride;
800     } while (--height);
801 }
802
803 static void MC_avg_o_16_mmxext (uint8_t * dest, const uint8_t * ref,
804                                 int stride, int height)
805 {
806     MC_avg1_16 (height, dest, ref, stride, CPU_MMXEXT);
807 }
808
809 static void MC_avg_o_8_mmxext (uint8_t * dest, const uint8_t * ref,
810                                int stride, int height)
811 {
812     MC_avg1_8 (height, dest, ref, stride, CPU_MMXEXT);
813 }
814
815 static void MC_put_o_16_mmxext (uint8_t * dest, const uint8_t * ref,
816                                 int stride, int height)
817 {
818     MC_put1_16 (height, dest, ref, stride);
819 }
820
821 static void MC_put_o_8_mmxext (uint8_t * dest, const uint8_t * ref,
822                                int stride, int height)
823 {
824     MC_put1_8 (height, dest, ref, stride);
825 }
826
827 static void MC_avg_x_16_mmxext (uint8_t * dest, const uint8_t * ref,
828                                 int stride, int height)
829 {
830     MC_avg2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
831 }
832
833 static void MC_avg_x_8_mmxext (uint8_t * dest, const uint8_t * ref,
834                                int stride, int height)
835 {
836     MC_avg2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
837 }
838
839 static void MC_put_x_16_mmxext (uint8_t * dest, const uint8_t * ref,
840                                 int stride, int height)
841 {
842     MC_put2_16 (height, dest, ref, stride, 1, CPU_MMXEXT);
843 }
844
845 static void MC_put_x_8_mmxext (uint8_t * dest, const uint8_t * ref,
846                                int stride, int height)
847 {
848     MC_put2_8 (height, dest, ref, stride, 1, CPU_MMXEXT);
849 }
850
851 static void MC_avg_y_16_mmxext (uint8_t * dest, const uint8_t * ref,
852                                 int stride, int height)
853 {
854     MC_avg2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
855 }
856
857 static void MC_avg_y_8_mmxext (uint8_t * dest, const uint8_t * ref,
858                                int stride, int height)
859 {
860     MC_avg2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
861 }
862
863 static void MC_put_y_16_mmxext (uint8_t * dest, const uint8_t * ref,
864                                 int stride, int height)
865 {
866     MC_put2_16 (height, dest, ref, stride, stride, CPU_MMXEXT);
867 }
868
869 static void MC_put_y_8_mmxext (uint8_t * dest, const uint8_t * ref,
870                                int stride, int height)
871 {
872     MC_put2_8 (height, dest, ref, stride, stride, CPU_MMXEXT);
873 }
874
875 static void MC_avg_xy_16_mmxext (uint8_t * dest, const uint8_t * ref,
876                                  int stride, int height)
877 {
878     MC_avg4_16 (height, dest, ref, stride, CPU_MMXEXT);
879 }
880
881 static void MC_avg_xy_8_mmxext (uint8_t * dest, const uint8_t * ref,
882                                 int stride, int height)
883 {
884     MC_avg4_8 (height, dest, ref, stride, CPU_MMXEXT);
885 }
886
887 static void MC_put_xy_16_mmxext (uint8_t * dest, const uint8_t * ref,
888                                  int stride, int height)
889 {
890     MC_put4_16 (height, dest, ref, stride, CPU_MMXEXT);
891 }
892
893 static void MC_put_xy_8_mmxext (uint8_t * dest, const uint8_t * ref,
894                                 int stride, int height)
895 {
896     MC_put4_8 (height, dest, ref, stride, CPU_MMXEXT);
897 }
898
899 MPEG2_MC_EXTERN (mmxext)
900
901 static void MC_avg_o_16_3dnow (uint8_t * dest, const uint8_t * ref,
902                                int stride, int height)
903 {
904     MC_avg1_16 (height, dest, ref, stride, CPU_3DNOW);
905 }
906
907 static void MC_avg_o_8_3dnow (uint8_t * dest, const uint8_t * ref,
908                               int stride, int height)
909 {
910     MC_avg1_8 (height, dest, ref, stride, CPU_3DNOW);
911 }
912
913 static void MC_put_o_16_3dnow (uint8_t * dest, const uint8_t * ref,
914                                int stride, int height)
915 {
916     MC_put1_16 (height, dest, ref, stride);
917 }
918
919 static void MC_put_o_8_3dnow (uint8_t * dest, const uint8_t * ref,
920                               int stride, int height)
921 {
922     MC_put1_8 (height, dest, ref, stride);
923 }
924
925 static void MC_avg_x_16_3dnow (uint8_t * dest, const uint8_t * ref,
926                                int stride, int height)
927 {
928     MC_avg2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
929 }
930
931 static void MC_avg_x_8_3dnow (uint8_t * dest, const uint8_t * ref,
932                               int stride, int height)
933 {
934     MC_avg2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
935 }
936
937 static void MC_put_x_16_3dnow (uint8_t * dest, const uint8_t * ref,
938                                int stride, int height)
939 {
940     MC_put2_16 (height, dest, ref, stride, 1, CPU_3DNOW);
941 }
942
943 static void MC_put_x_8_3dnow (uint8_t * dest, const uint8_t * ref,
944                               int stride, int height)
945 {
946     MC_put2_8 (height, dest, ref, stride, 1, CPU_3DNOW);
947 }
948
949 static void MC_avg_y_16_3dnow (uint8_t * dest, const uint8_t * ref,
950                                int stride, int height)
951 {
952     MC_avg2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
953 }
954
955 static void MC_avg_y_8_3dnow (uint8_t * dest, const uint8_t * ref,
956                               int stride, int height)
957 {
958     MC_avg2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
959 }
960
961 static void MC_put_y_16_3dnow (uint8_t * dest, const uint8_t * ref,
962                                int stride, int height)
963 {
964     MC_put2_16 (height, dest, ref, stride, stride, CPU_3DNOW);
965 }
966
967 static void MC_put_y_8_3dnow (uint8_t * dest, const uint8_t * ref,
968                               int stride, int height)
969 {
970     MC_put2_8 (height, dest, ref, stride, stride, CPU_3DNOW);
971 }
972
973 static void MC_avg_xy_16_3dnow (uint8_t * dest, const uint8_t * ref,
974                                 int stride, int height)
975 {
976     MC_avg4_16 (height, dest, ref, stride, CPU_3DNOW);
977 }
978
979 static void MC_avg_xy_8_3dnow (uint8_t * dest, const uint8_t * ref,
980                                int stride, int height)
981 {
982     MC_avg4_8 (height, dest, ref, stride, CPU_3DNOW);
983 }
984
985 static void MC_put_xy_16_3dnow (uint8_t * dest, const uint8_t * ref,
986                                 int stride, int height)
987 {
988     MC_put4_16 (height, dest, ref, stride, CPU_3DNOW);
989 }
990
991 static void MC_put_xy_8_3dnow (uint8_t * dest, const uint8_t * ref,
992                                int stride, int height)
993 {
994     MC_put4_8 (height, dest, ref, stride, CPU_3DNOW);
995 }
996
997 MPEG2_MC_EXTERN (3dnow)
998