2447ab6abf9e931e31142233ab31ca34ad85c593
[ffmpeg.git] / libavcodec / i386 / dsputil_mmx.c
1 /*
2  * MMX optimized DSP utils
3  * Copyright (c) 2000, 2001 Fabrice Bellard.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
20  */
21
22 #include "../dsputil.h"
23 #include "../simple_idct.h"
24
25 int mm_flags; /* multimedia extension flags */
26
27 /* pixel operations */
28 static const uint64_t mm_bone __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
29 static const uint64_t mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
30 static const uint64_t mm_wtwo __attribute__ ((aligned(8))) = 0x0002000200020002ULL;
31
32 static const uint64_t ff_pw_20 __attribute__ ((aligned(8))) = 0x0014001400140014ULL;
33 static const uint64_t ff_pw_3  __attribute__ ((aligned(8))) = 0x0003000300030003ULL;
34 static const uint64_t ff_pw_16 __attribute__ ((aligned(8))) = 0x0010001000100010ULL;
35 static const uint64_t ff_pw_15 __attribute__ ((aligned(8))) = 0x000F000F000F000FULL;
36
37 #define JUMPALIGN() __asm __volatile (".balign 8"::)
38 #define MOVQ_ZERO(regd)  __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
39
40 #define MOVQ_WONE(regd) \
41     __asm __volatile ( \
42     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
43     "psrlw $15, %%" #regd ::)
44
45 #define MOVQ_BFE(regd) \
46     __asm __volatile ( \
47     "pcmpeqd %%" #regd ", %%" #regd " \n\t"\
48     "paddb %%" #regd ", %%" #regd " \n\t" ::)
49
50 #ifndef PIC
51 #define MOVQ_BONE(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_bone))
52 #define MOVQ_WTWO(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_wtwo))
53 #else
54 // for shared library it's better to use this way for accessing constants
55 // pcmpeqd -> -1
56 #define MOVQ_BONE(regd) \
57     __asm __volatile ( \
58     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
59     "psrlw $15, %%" #regd " \n\t" \
60     "packuswb %%" #regd ", %%" #regd " \n\t" ::)
61
62 #define MOVQ_WTWO(regd) \
63     __asm __volatile ( \
64     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
65     "psrlw $15, %%" #regd " \n\t" \
66     "psllw $1, %%" #regd " \n\t"::)
67
68 #endif
69
70 // using regr as temporary and for the output result
71 // first argument is unmodifed and second is trashed
72 // regfe is supposed to contain 0xfefefefefefefefe
73 #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \
74     "movq " #rega ", " #regr "  \n\t"\
75     "pand " #regb ", " #regr "  \n\t"\
76     "pxor " #rega ", " #regb "  \n\t"\
77     "pand " #regfe "," #regb "  \n\t"\
78     "psrlq $1, " #regb "        \n\t"\
79     "paddb " #regb ", " #regr " \n\t"
80
81 #define PAVGB_MMX(rega, regb, regr, regfe) \
82     "movq " #rega ", " #regr "  \n\t"\
83     "por  " #regb ", " #regr "  \n\t"\
84     "pxor " #rega ", " #regb "  \n\t"\
85     "pand " #regfe "," #regb "  \n\t"\
86     "psrlq $1, " #regb "        \n\t"\
87     "psubb " #regb ", " #regr " \n\t"
88
89 // mm6 is supposed to contain 0xfefefefefefefefe
90 #define PAVGBP_MMX_NO_RND(rega, regb, regr,  regc, regd, regp) \
91     "movq " #rega ", " #regr "  \n\t"\
92     "movq " #regc ", " #regp "  \n\t"\
93     "pand " #regb ", " #regr "  \n\t"\
94     "pand " #regd ", " #regp "  \n\t"\
95     "pxor " #rega ", " #regb "  \n\t"\
96     "pxor " #regc ", " #regd "  \n\t"\
97     "pand %%mm6, " #regb "      \n\t"\
98     "pand %%mm6, " #regd "      \n\t"\
99     "psrlq $1, " #regb "        \n\t"\
100     "psrlq $1, " #regd "        \n\t"\
101     "paddb " #regb ", " #regr " \n\t"\
102     "paddb " #regd ", " #regp " \n\t"
103
104 #define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \
105     "movq " #rega ", " #regr "  \n\t"\
106     "movq " #regc ", " #regp "  \n\t"\
107     "por  " #regb ", " #regr "  \n\t"\
108     "por  " #regd ", " #regp "  \n\t"\
109     "pxor " #rega ", " #regb "  \n\t"\
110     "pxor " #regc ", " #regd "  \n\t"\
111     "pand %%mm6, " #regb "      \n\t"\
112     "pand %%mm6, " #regd "      \n\t"\
113     "psrlq $1, " #regd "        \n\t"\
114     "psrlq $1, " #regb "        \n\t"\
115     "psubb " #regb ", " #regr " \n\t"\
116     "psubb " #regd ", " #regp " \n\t"
117
118 /***********************************/
119 /* MMX no rounding */
120 #define DEF(x, y) x ## _no_rnd_ ## y ##_mmx
121 #define SET_RND  MOVQ_WONE
122 #define PAVGBP(a, b, c, d, e, f)        PAVGBP_MMX_NO_RND(a, b, c, d, e, f)
123 #define PAVGB(a, b, c, e)               PAVGB_MMX_NO_RND(a, b, c, e)
124
125 #include "dsputil_mmx_rnd.h"
126
127 #undef DEF
128 #undef SET_RND
129 #undef PAVGBP
130 #undef PAVGB
131 /***********************************/
132 /* MMX rounding */
133
134 #define DEF(x, y) x ## _ ## y ##_mmx
135 #define SET_RND  MOVQ_WTWO
136 #define PAVGBP(a, b, c, d, e, f)        PAVGBP_MMX(a, b, c, d, e, f)
137 #define PAVGB(a, b, c, e)               PAVGB_MMX(a, b, c, e)
138
139 #include "dsputil_mmx_rnd.h"
140
141 #undef DEF
142 #undef SET_RND
143 #undef PAVGBP
144 #undef PAVGB
145
146 /***********************************/
147 /* 3Dnow specific */
148
149 #define DEF(x) x ## _3dnow
150 /* for Athlons PAVGUSB is prefered */
151 #define PAVGB "pavgusb"
152
153 #include "dsputil_mmx_avg.h"
154
155 #undef DEF
156 #undef PAVGB
157
158 /***********************************/
159 /* MMX2 specific */
160
161 #define DEF(x) x ## _mmx2
162
163 /* Introduced only in MMX2 set */
164 #define PAVGB "pavgb"
165
166 #include "dsputil_mmx_avg.h"
167
168 #undef DEF
169 #undef PAVGB
170
171 /***********************************/
172 /* standard MMX */
173
174 static void get_pixels_mmx(DCTELEM *block, const uint8_t *pixels, int line_size)
175 {
176     asm volatile(
177         "movl $-128, %%eax      \n\t"
178         "pxor %%mm7, %%mm7      \n\t"
179         ".balign 16             \n\t"
180         "1:                     \n\t"
181         "movq (%0), %%mm0       \n\t"
182         "movq (%0, %2), %%mm2   \n\t"
183         "movq %%mm0, %%mm1      \n\t"
184         "movq %%mm2, %%mm3      \n\t"
185         "punpcklbw %%mm7, %%mm0 \n\t"
186         "punpckhbw %%mm7, %%mm1 \n\t"
187         "punpcklbw %%mm7, %%mm2 \n\t"
188         "punpckhbw %%mm7, %%mm3 \n\t"
189         "movq %%mm0, (%1, %%eax)\n\t"
190         "movq %%mm1, 8(%1, %%eax)\n\t"
191         "movq %%mm2, 16(%1, %%eax)\n\t"
192         "movq %%mm3, 24(%1, %%eax)\n\t"
193         "addl %3, %0            \n\t"
194         "addl $32, %%eax        \n\t"
195         "js 1b                  \n\t"
196         : "+r" (pixels)
197         : "r" (block+64), "r" (line_size), "r" (line_size*2)
198         : "%eax"
199     );
200 }
201
202 static inline void diff_pixels_mmx(DCTELEM *block, const uint8_t *s1, const uint8_t *s2, int stride)
203 {
204     asm volatile(
205         "pxor %%mm7, %%mm7      \n\t"
206         "movl $-128, %%eax      \n\t"
207         ".balign 16             \n\t"
208         "1:                     \n\t"
209         "movq (%0), %%mm0       \n\t"
210         "movq (%1), %%mm2       \n\t"
211         "movq %%mm0, %%mm1      \n\t"
212         "movq %%mm2, %%mm3      \n\t"
213         "punpcklbw %%mm7, %%mm0 \n\t"
214         "punpckhbw %%mm7, %%mm1 \n\t"
215         "punpcklbw %%mm7, %%mm2 \n\t"
216         "punpckhbw %%mm7, %%mm3 \n\t"
217         "psubw %%mm2, %%mm0     \n\t"
218         "psubw %%mm3, %%mm1     \n\t"
219         "movq %%mm0, (%2, %%eax)\n\t"
220         "movq %%mm1, 8(%2, %%eax)\n\t"
221         "addl %3, %0            \n\t"
222         "addl %3, %1            \n\t"
223         "addl $16, %%eax        \n\t"
224         "jnz 1b                 \n\t"
225         : "+r" (s1), "+r" (s2)
226         : "r" (block+64), "r" (stride)
227         : "%eax"
228     );
229 }
230
231 void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
232 {
233     const DCTELEM *p;
234     uint8_t *pix;
235
236     /* read the pixels */
237     p = block;
238     pix = pixels;
239     /* unrolled loop */
240         __asm __volatile(
241                 "movq   %3, %%mm0\n\t"
242                 "movq   8%3, %%mm1\n\t"
243                 "movq   16%3, %%mm2\n\t"
244                 "movq   24%3, %%mm3\n\t"
245                 "movq   32%3, %%mm4\n\t"
246                 "movq   40%3, %%mm5\n\t"
247                 "movq   48%3, %%mm6\n\t"
248                 "movq   56%3, %%mm7\n\t"
249                 "packuswb %%mm1, %%mm0\n\t"
250                 "packuswb %%mm3, %%mm2\n\t"
251                 "packuswb %%mm5, %%mm4\n\t"
252                 "packuswb %%mm7, %%mm6\n\t"
253                 "movq   %%mm0, (%0)\n\t"
254                 "movq   %%mm2, (%0, %1)\n\t"
255                 "movq   %%mm4, (%0, %1, 2)\n\t"
256                 "movq   %%mm6, (%0, %2)\n\t"
257                 ::"r" (pix), "r" (line_size), "r" (line_size*3), "m"(*p)
258                 :"memory");
259         pix += line_size*4;
260         p += 32;
261
262     // if here would be an exact copy of the code above
263     // compiler would generate some very strange code
264     // thus using "r"
265     __asm __volatile(
266             "movq       (%3), %%mm0\n\t"
267             "movq       8(%3), %%mm1\n\t"
268             "movq       16(%3), %%mm2\n\t"
269             "movq       24(%3), %%mm3\n\t"
270             "movq       32(%3), %%mm4\n\t"
271             "movq       40(%3), %%mm5\n\t"
272             "movq       48(%3), %%mm6\n\t"
273             "movq       56(%3), %%mm7\n\t"
274             "packuswb %%mm1, %%mm0\n\t"
275             "packuswb %%mm3, %%mm2\n\t"
276             "packuswb %%mm5, %%mm4\n\t"
277             "packuswb %%mm7, %%mm6\n\t"
278             "movq       %%mm0, (%0)\n\t"
279             "movq       %%mm2, (%0, %1)\n\t"
280             "movq       %%mm4, (%0, %1, 2)\n\t"
281             "movq       %%mm6, (%0, %2)\n\t"
282             ::"r" (pix), "r" (line_size), "r" (line_size*3), "r"(p)
283             :"memory");
284 }
285
286 void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
287 {
288     const DCTELEM *p;
289     uint8_t *pix;
290     int i;
291
292     /* read the pixels */
293     p = block;
294     pix = pixels;
295     MOVQ_ZERO(mm7);
296     i = 4;
297     do {
298         __asm __volatile(
299                 "movq   (%2), %%mm0\n\t"
300                 "movq   8(%2), %%mm1\n\t"
301                 "movq   16(%2), %%mm2\n\t"
302                 "movq   24(%2), %%mm3\n\t"
303                 "movq   %0, %%mm4\n\t"
304                 "movq   %1, %%mm6\n\t"
305                 "movq   %%mm4, %%mm5\n\t"
306                 "punpcklbw %%mm7, %%mm4\n\t"
307                 "punpckhbw %%mm7, %%mm5\n\t"
308                 "paddsw %%mm4, %%mm0\n\t"
309                 "paddsw %%mm5, %%mm1\n\t"
310                 "movq   %%mm6, %%mm5\n\t"
311                 "punpcklbw %%mm7, %%mm6\n\t"
312                 "punpckhbw %%mm7, %%mm5\n\t"
313                 "paddsw %%mm6, %%mm2\n\t"
314                 "paddsw %%mm5, %%mm3\n\t"
315                 "packuswb %%mm1, %%mm0\n\t"
316                 "packuswb %%mm3, %%mm2\n\t"
317                 "movq   %%mm0, %0\n\t"
318                 "movq   %%mm2, %1\n\t"
319                 :"+m"(*pix), "+m"(*(pix+line_size))
320                 :"r"(p)
321                 :"memory");
322         pix += line_size*2;
323         p += 16;
324     } while (--i);
325 }
326
327 static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
328 {
329     __asm __volatile(
330          "lea (%3, %3), %%eax           \n\t"
331          ".balign 8                     \n\t"
332          "1:                            \n\t"
333          "movq (%1), %%mm0              \n\t"
334          "movq (%1, %3), %%mm1          \n\t"
335          "movq %%mm0, (%2)              \n\t"
336          "movq %%mm1, (%2, %3)          \n\t"
337          "addl %%eax, %1                \n\t"
338          "addl %%eax, %2                \n\t"
339          "movq (%1), %%mm0              \n\t"
340          "movq (%1, %3), %%mm1          \n\t"
341          "movq %%mm0, (%2)              \n\t"
342          "movq %%mm1, (%2, %3)          \n\t"
343          "addl %%eax, %1                \n\t"
344          "addl %%eax, %2                \n\t"
345          "subl $4, %0                   \n\t"
346          "jnz 1b                        \n\t"
347          : "+g"(h), "+r" (pixels),  "+r" (block)
348          : "r"(line_size)
349          : "%eax", "memory"
350         );
351 }
352
353 static void put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
354 {
355     __asm __volatile(
356          "lea (%3, %3), %%eax           \n\t"
357          ".balign 8                     \n\t"
358          "1:                            \n\t"
359          "movq (%1), %%mm0              \n\t"
360          "movq 8(%1), %%mm4             \n\t"
361          "movq (%1, %3), %%mm1          \n\t"
362          "movq 8(%1, %3), %%mm5         \n\t"
363          "movq %%mm0, (%2)              \n\t"
364          "movq %%mm4, 8(%2)             \n\t"
365          "movq %%mm1, (%2, %3)          \n\t"
366          "movq %%mm5, 8(%2, %3)         \n\t"
367          "addl %%eax, %1                \n\t"
368          "addl %%eax, %2                \n\t"
369          "movq (%1), %%mm0              \n\t"
370          "movq 8(%1), %%mm4             \n\t"
371          "movq (%1, %3), %%mm1          \n\t"
372          "movq 8(%1, %3), %%mm5         \n\t"
373          "movq %%mm0, (%2)              \n\t"
374          "movq %%mm4, 8(%2)             \n\t"
375          "movq %%mm1, (%2, %3)          \n\t"
376          "movq %%mm5, 8(%2, %3)         \n\t"
377          "addl %%eax, %1                \n\t"
378          "addl %%eax, %2                \n\t"
379          "subl $4, %0                   \n\t"
380          "jnz 1b                        \n\t"
381          : "+g"(h), "+r" (pixels),  "+r" (block)
382          : "r"(line_size)
383          : "%eax", "memory"
384         );
385 }
386
387 static void clear_blocks_mmx(DCTELEM *blocks)
388 {
389     __asm __volatile(
390                 "pxor %%mm7, %%mm7              \n\t"
391                 "movl $-128*6, %%eax            \n\t"
392                 "1:                             \n\t"
393                 "movq %%mm7, (%0, %%eax)        \n\t"
394                 "movq %%mm7, 8(%0, %%eax)       \n\t"
395                 "movq %%mm7, 16(%0, %%eax)      \n\t"
396                 "movq %%mm7, 24(%0, %%eax)      \n\t"
397                 "addl $32, %%eax                \n\t"
398                 " js 1b                         \n\t"
399                 : : "r" (((int)blocks)+128*6)
400                 : "%eax"
401         );
402 }
403
404 static int pix_sum16_mmx(uint8_t * pix, int line_size){
405     const int h=16;
406     int sum;
407     int index= -line_size*h;
408
409     __asm __volatile(
410                 "pxor %%mm7, %%mm7              \n\t"
411                 "pxor %%mm6, %%mm6              \n\t"
412                 "1:                             \n\t"
413                 "movq (%2, %1), %%mm0           \n\t"
414                 "movq (%2, %1), %%mm1           \n\t"
415                 "movq 8(%2, %1), %%mm2          \n\t"
416                 "movq 8(%2, %1), %%mm3          \n\t"
417                 "punpcklbw %%mm7, %%mm0         \n\t"
418                 "punpckhbw %%mm7, %%mm1         \n\t"
419                 "punpcklbw %%mm7, %%mm2         \n\t"
420                 "punpckhbw %%mm7, %%mm3         \n\t"
421                 "paddw %%mm0, %%mm1             \n\t"
422                 "paddw %%mm2, %%mm3             \n\t"
423                 "paddw %%mm1, %%mm3             \n\t"
424                 "paddw %%mm3, %%mm6             \n\t"
425                 "addl %3, %1                    \n\t"
426                 " js 1b                         \n\t"
427                 "movq %%mm6, %%mm5              \n\t"
428                 "psrlq $32, %%mm6               \n\t"
429                 "paddw %%mm5, %%mm6             \n\t"
430                 "movq %%mm6, %%mm5              \n\t"
431                 "psrlq $16, %%mm6               \n\t"
432                 "paddw %%mm5, %%mm6             \n\t"
433                 "movd %%mm6, %0                 \n\t"
434                 "andl $0xFFFF, %0               \n\t"
435                 : "=&r" (sum), "+r" (index)
436                 : "r" (pix - index), "r" (line_size)
437         );
438
439         return sum;
440 }
441
442 static void add_bytes_mmx(uint8_t *dst, uint8_t *src, int w){
443     int i=0;
444     asm volatile(
445         "1:                             \n\t"
446         "movq  (%1, %0), %%mm0          \n\t"
447         "movq  (%2, %0), %%mm1          \n\t"
448         "paddb %%mm0, %%mm1             \n\t"
449         "movq %%mm1, (%2, %0)           \n\t"
450         "movq 8(%1, %0), %%mm0          \n\t"
451         "movq 8(%2, %0), %%mm1          \n\t"
452         "paddb %%mm0, %%mm1             \n\t"
453         "movq %%mm1, 8(%2, %0)          \n\t"
454         "addl $16, %0                   \n\t"
455         "cmpl %3, %0                    \n\t"
456         " jb 1b                         \n\t"
457         : "+r" (i)
458         : "r"(src), "r"(dst), "r"(w-15)
459     );
460     for(; i<w; i++)
461         dst[i+0] += src[i+0];
462 }
463
464 static int pix_norm1_mmx(uint8_t *pix, int line_size) {
465     int tmp;
466   asm volatile (
467       "movl $16,%%ecx\n"
468       "pxor %%mm0,%%mm0\n"
469       "pxor %%mm7,%%mm7\n"
470       "1:\n"
471       "movq (%0),%%mm2\n"       /* mm2 = pix[0-7] */
472       "movq 8(%0),%%mm3\n"      /* mm3 = pix[8-15] */
473
474       "movq %%mm2,%%mm1\n"      /* mm1 = mm2 = pix[0-7] */
475
476       "punpckhbw %%mm0,%%mm1\n" /* mm1 = [pix4-7] */
477       "punpcklbw %%mm0,%%mm2\n" /* mm2 = [pix0-3] */
478
479       "movq %%mm3,%%mm4\n"      /* mm4 = mm3 = pix[8-15] */
480       "punpckhbw %%mm0,%%mm3\n" /* mm3 = [pix12-15] */
481       "punpcklbw %%mm0,%%mm4\n" /* mm4 = [pix8-11] */
482
483       "pmaddwd %%mm1,%%mm1\n"   /* mm1 = (pix0^2+pix1^2,pix2^2+pix3^2) */
484       "pmaddwd %%mm2,%%mm2\n"   /* mm2 = (pix4^2+pix5^2,pix6^2+pix7^2) */
485
486       "pmaddwd %%mm3,%%mm3\n"
487       "pmaddwd %%mm4,%%mm4\n"
488
489       "paddd %%mm1,%%mm2\n"     /* mm2 = (pix0^2+pix1^2+pix4^2+pix5^2,
490                                           pix2^2+pix3^2+pix6^2+pix7^2) */
491       "paddd %%mm3,%%mm4\n"
492       "paddd %%mm2,%%mm7\n"
493
494       "addl %2, %0\n"
495       "paddd %%mm4,%%mm7\n"
496       "dec %%ecx\n"
497       "jnz 1b\n"
498
499       "movq %%mm7,%%mm1\n"
500       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
501       "paddd %%mm7,%%mm1\n"
502       "movd %%mm1,%1\n"
503       : "+r" (pix), "=r"(tmp) : "r" (line_size) : "%ecx" );
504     return tmp;
505 }
506
507 static int sse16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size) {
508     int tmp;
509   asm volatile (
510       "movl $16,%%ecx\n"
511       "pxor %%mm0,%%mm0\n"      /* mm0 = 0 */
512       "pxor %%mm7,%%mm7\n"      /* mm7 holds the sum */
513       "1:\n"
514       "movq (%0),%%mm1\n"       /* mm1 = pix1[0-7] */
515       "movq (%1),%%mm2\n"       /* mm2 = pix2[0-7] */
516       "movq 8(%0),%%mm3\n"      /* mm3 = pix1[8-15] */
517       "movq 8(%1),%%mm4\n"      /* mm4 = pix2[8-15] */
518
519       /* todo: mm1-mm2, mm3-mm4 */
520       /* algo: substract mm1 from mm2 with saturation and vice versa */
521       /*       OR the results to get absolute difference */
522       "movq %%mm1,%%mm5\n"
523       "movq %%mm3,%%mm6\n"
524       "psubusb %%mm2,%%mm1\n"
525       "psubusb %%mm4,%%mm3\n"
526       "psubusb %%mm5,%%mm2\n"
527       "psubusb %%mm6,%%mm4\n"
528
529       "por %%mm1,%%mm2\n"
530       "por %%mm3,%%mm4\n"
531
532       /* now convert to 16-bit vectors so we can square them */
533       "movq %%mm2,%%mm1\n"
534       "movq %%mm4,%%mm3\n"
535
536       "punpckhbw %%mm0,%%mm2\n"
537       "punpckhbw %%mm0,%%mm4\n"
538       "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */
539       "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */
540
541       "pmaddwd %%mm2,%%mm2\n"
542       "pmaddwd %%mm4,%%mm4\n"
543       "pmaddwd %%mm1,%%mm1\n"
544       "pmaddwd %%mm3,%%mm3\n"
545
546       "addl %3,%0\n"
547       "addl %3,%1\n"
548
549       "paddd %%mm2,%%mm1\n"
550       "paddd %%mm4,%%mm3\n"
551       "paddd %%mm1,%%mm7\n"
552       "paddd %%mm3,%%mm7\n"
553
554       "decl %%ecx\n"
555       "jnz 1b\n"
556
557       "movq %%mm7,%%mm1\n"
558       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
559       "paddd %%mm7,%%mm1\n"
560       "movd %%mm1,%2\n"
561       : "+r" (pix1), "+r" (pix2), "=r"(tmp) : "r" (line_size) : "ecx");
562     return tmp;
563 }
564
565 static void diff_bytes_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){
566     int i=0;
567     asm volatile(
568         "1:                             \n\t"
569         "movq  (%2, %0), %%mm0          \n\t"
570         "movq  (%1, %0), %%mm1          \n\t"
571         "psubb %%mm0, %%mm1             \n\t"
572         "movq %%mm1, (%3, %0)           \n\t"
573         "movq 8(%2, %0), %%mm0          \n\t"
574         "movq 8(%1, %0), %%mm1          \n\t"
575         "psubb %%mm0, %%mm1             \n\t"
576         "movq %%mm1, 8(%3, %0)          \n\t"
577         "addl $16, %0                   \n\t"
578         "cmpl %4, %0                    \n\t"
579         " jb 1b                         \n\t"
580         : "+r" (i)
581         : "r"(src1), "r"(src2), "r"(dst), "r"(w-15)
582     );
583     for(; i<w; i++)
584         dst[i+0] = src1[i+0]-src2[i+0];
585 }
586
587 static void sub_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){
588     int i=0;
589     uint8_t l, lt;
590
591     asm volatile(
592         "1:                             \n\t"
593         "movq  -1(%1, %0), %%mm0        \n\t" // LT
594         "movq  (%1, %0), %%mm1          \n\t" // T
595         "movq  -1(%2, %0), %%mm2        \n\t" // L
596         "movq  (%2, %0), %%mm3          \n\t" // X
597         "movq %%mm2, %%mm4              \n\t" // L
598         "psubb %%mm0, %%mm2             \n\t"
599         "paddb %%mm1, %%mm2             \n\t" // L + T - LT
600         "movq %%mm4, %%mm5              \n\t" // L
601         "pmaxub %%mm1, %%mm4            \n\t" // max(T, L)
602         "pminub %%mm5, %%mm1            \n\t" // min(T, L)
603         "pminub %%mm2, %%mm4            \n\t" 
604         "pmaxub %%mm1, %%mm4            \n\t"
605         "psubb %%mm4, %%mm3             \n\t" // dst - pred
606         "movq %%mm3, (%3, %0)           \n\t"
607         "addl $8, %0                    \n\t"
608         "cmpl %4, %0                    \n\t"
609         " jb 1b                         \n\t"
610         : "+r" (i)
611         : "r"(src1), "r"(src2), "r"(dst), "r"(w)
612     );
613
614     l= *left;
615     lt= *left_top;
616     
617     dst[0]= src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt)&0xFF);
618     
619     *left_top= src1[w-1];
620     *left    = src2[w-1];
621 }
622
623 #define LBUTTERFLY2(a1,b1,a2,b2)\
624     "paddw " #b1 ", " #a1 "             \n\t"\
625     "paddw " #b2 ", " #a2 "             \n\t"\
626     "paddw " #b1 ", " #b1 "             \n\t"\
627     "paddw " #b2 ", " #b2 "             \n\t"\
628     "psubw " #a1 ", " #b1 "             \n\t"\
629     "psubw " #a2 ", " #b2 "             \n\t"
630
631 #define HADAMARD48\
632         LBUTTERFLY2(%%mm0, %%mm1, %%mm2, %%mm3)\
633         LBUTTERFLY2(%%mm4, %%mm5, %%mm6, %%mm7)\
634         LBUTTERFLY2(%%mm0, %%mm2, %%mm1, %%mm3)\
635         LBUTTERFLY2(%%mm4, %%mm6, %%mm5, %%mm7)\
636         LBUTTERFLY2(%%mm0, %%mm4, %%mm1, %%mm5)\
637         LBUTTERFLY2(%%mm2, %%mm6, %%mm3, %%mm7)\
638
639 #define MMABS(a,z)\
640     "pxor " #z ", " #z "                \n\t"\
641     "pcmpgtw " #a ", " #z "             \n\t"\
642     "pxor " #z ", " #a "                \n\t"\
643     "psubw " #z ", " #a "               \n\t"
644
645 #define MMABS_SUM(a,z, sum)\
646     "pxor " #z ", " #z "                \n\t"\
647     "pcmpgtw " #a ", " #z "             \n\t"\
648     "pxor " #z ", " #a "                \n\t"\
649     "psubw " #z ", " #a "               \n\t"\
650     "paddusw " #a ", " #sum "           \n\t"
651
652 #define MMABS_MMX2(a,z)\
653     "pxor " #z ", " #z "                \n\t"\
654     "psubw " #a ", " #z "               \n\t"\
655     "pmaxsw " #z ", " #a "              \n\t"
656
657 #define MMABS_SUM_MMX2(a,z, sum)\
658     "pxor " #z ", " #z "                \n\t"\
659     "psubw " #a ", " #z "               \n\t"\
660     "pmaxsw " #z ", " #a "              \n\t"\
661     "paddusw " #a ", " #sum "           \n\t"
662         
663 #define SBUTTERFLY(a,b,t,n)\
664     "movq " #a ", " #t "                \n\t" /* abcd */\
665     "punpckl" #n " " #b ", " #a "       \n\t" /* aebf */\
666     "punpckh" #n " " #b ", " #t "       \n\t" /* cgdh */\
667
668 #define TRANSPOSE4(a,b,c,d,t)\
669     SBUTTERFLY(a,b,t,wd) /* a=aebf t=cgdh */\
670     SBUTTERFLY(c,d,b,wd) /* c=imjn b=kolp */\
671     SBUTTERFLY(a,c,d,dq) /* a=aeim d=bfjn */\
672     SBUTTERFLY(t,b,c,dq) /* t=cgko c=dhlp */
673
674 #define LOAD4(o, a, b, c, d)\
675         "movq "#o"(%1), " #a "          \n\t"\
676         "movq "#o"+16(%1), " #b "       \n\t"\
677         "movq "#o"+32(%1), " #c "       \n\t"\
678         "movq "#o"+48(%1), " #d "       \n\t"
679
680 #define STORE4(o, a, b, c, d)\
681         "movq "#a", "#o"(%1)            \n\t"\
682         "movq "#b", "#o"+16(%1)         \n\t"\
683         "movq "#c", "#o"+32(%1)         \n\t"\
684         "movq "#d", "#o"+48(%1)         \n\t"\
685
686 static int hadamard8_diff_mmx(void *s, uint8_t *src1, uint8_t *src2, int stride){
687     uint64_t temp[16] __align8;
688     int sum=0;
689
690     diff_pixels_mmx((DCTELEM*)temp, src1, src2, stride);
691
692     asm volatile(
693         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
694         LOAD4(64, %%mm4, %%mm5, %%mm6, %%mm7)
695         
696         HADAMARD48
697         
698         "movq %%mm7, 112(%1)            \n\t"
699         
700         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
701         STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)
702         
703         "movq 112(%1), %%mm7            \n\t"
704         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
705         STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)
706
707         LOAD4(8 , %%mm0, %%mm1, %%mm2, %%mm3)
708         LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
709         
710         HADAMARD48
711         
712         "movq %%mm7, 120(%1)            \n\t"
713         
714         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
715         STORE4(8 , %%mm0, %%mm3, %%mm7, %%mm2)
716         
717         "movq 120(%1), %%mm7            \n\t"
718         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
719         "movq %%mm7, %%mm5              \n\t"//FIXME remove
720         "movq %%mm6, %%mm7              \n\t"
721         "movq %%mm0, %%mm6              \n\t"
722 //        STORE4(72, %%mm4, %%mm7, %%mm0, %%mm6) //FIXME remove
723         
724         LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)
725 //        LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
726         
727         HADAMARD48
728         "movq %%mm7, 64(%1)             \n\t"
729         MMABS(%%mm0, %%mm7)
730         MMABS_SUM(%%mm1, %%mm7, %%mm0)
731         MMABS_SUM(%%mm2, %%mm7, %%mm0)
732         MMABS_SUM(%%mm3, %%mm7, %%mm0)
733         MMABS_SUM(%%mm4, %%mm7, %%mm0)
734         MMABS_SUM(%%mm5, %%mm7, %%mm0)
735         MMABS_SUM(%%mm6, %%mm7, %%mm0)
736         "movq 64(%1), %%mm1             \n\t"
737         MMABS_SUM(%%mm1, %%mm7, %%mm0)
738         "movq %%mm0, 64(%1)             \n\t"
739         
740         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
741         LOAD4(8 , %%mm4, %%mm5, %%mm6, %%mm7)
742         
743         HADAMARD48
744         "movq %%mm7, (%1)               \n\t"
745         MMABS(%%mm0, %%mm7)
746         MMABS_SUM(%%mm1, %%mm7, %%mm0)
747         MMABS_SUM(%%mm2, %%mm7, %%mm0)
748         MMABS_SUM(%%mm3, %%mm7, %%mm0)
749         MMABS_SUM(%%mm4, %%mm7, %%mm0)
750         MMABS_SUM(%%mm5, %%mm7, %%mm0)
751         MMABS_SUM(%%mm6, %%mm7, %%mm0)
752         "movq (%1), %%mm1               \n\t"
753         MMABS_SUM(%%mm1, %%mm7, %%mm0)
754         "movq 64(%1), %%mm1             \n\t"
755         MMABS_SUM(%%mm1, %%mm7, %%mm0)
756         
757         "movq %%mm0, %%mm1              \n\t"
758         "psrlq $32, %%mm0               \n\t"
759         "paddusw %%mm1, %%mm0           \n\t"
760         "movq %%mm0, %%mm1              \n\t"
761         "psrlq $16, %%mm0               \n\t"
762         "paddusw %%mm1, %%mm0           \n\t"
763         "movd %%mm0, %0                 \n\t"
764                 
765         : "=r" (sum)
766         : "r"(temp)
767     );
768     return sum&0xFFFF;
769 }
770
771 static int hadamard8_diff_mmx2(void *s, uint8_t *src1, uint8_t *src2, int stride){
772     uint64_t temp[16] __align8;
773     int sum=0;
774
775     diff_pixels_mmx((DCTELEM*)temp, src1, src2, stride);
776
777     asm volatile(
778         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
779         LOAD4(64, %%mm4, %%mm5, %%mm6, %%mm7)
780         
781         HADAMARD48
782         
783         "movq %%mm7, 112(%1)            \n\t"
784         
785         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
786         STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)
787         
788         "movq 112(%1), %%mm7            \n\t"
789         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
790         STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)
791
792         LOAD4(8 , %%mm0, %%mm1, %%mm2, %%mm3)
793         LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
794         
795         HADAMARD48
796         
797         "movq %%mm7, 120(%1)            \n\t"
798         
799         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)
800         STORE4(8 , %%mm0, %%mm3, %%mm7, %%mm2)
801         
802         "movq 120(%1), %%mm7            \n\t"
803         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)
804         "movq %%mm7, %%mm5              \n\t"//FIXME remove
805         "movq %%mm6, %%mm7              \n\t"
806         "movq %%mm0, %%mm6              \n\t"
807 //        STORE4(72, %%mm4, %%mm7, %%mm0, %%mm6) //FIXME remove
808         
809         LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)
810 //        LOAD4(72, %%mm4, %%mm5, %%mm6, %%mm7)
811         
812         HADAMARD48
813         "movq %%mm7, 64(%1)             \n\t"
814         MMABS_MMX2(%%mm0, %%mm7)
815         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
816         MMABS_SUM_MMX2(%%mm2, %%mm7, %%mm0)
817         MMABS_SUM_MMX2(%%mm3, %%mm7, %%mm0)
818         MMABS_SUM_MMX2(%%mm4, %%mm7, %%mm0)
819         MMABS_SUM_MMX2(%%mm5, %%mm7, %%mm0)
820         MMABS_SUM_MMX2(%%mm6, %%mm7, %%mm0)
821         "movq 64(%1), %%mm1             \n\t"
822         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
823         "movq %%mm0, 64(%1)             \n\t"
824         
825         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)
826         LOAD4(8 , %%mm4, %%mm5, %%mm6, %%mm7)
827         
828         HADAMARD48
829         "movq %%mm7, (%1)               \n\t"
830         MMABS_MMX2(%%mm0, %%mm7)
831         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
832         MMABS_SUM_MMX2(%%mm2, %%mm7, %%mm0)
833         MMABS_SUM_MMX2(%%mm3, %%mm7, %%mm0)
834         MMABS_SUM_MMX2(%%mm4, %%mm7, %%mm0)
835         MMABS_SUM_MMX2(%%mm5, %%mm7, %%mm0)
836         MMABS_SUM_MMX2(%%mm6, %%mm7, %%mm0)
837         "movq (%1), %%mm1               \n\t"
838         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
839         "movq 64(%1), %%mm1             \n\t"
840         MMABS_SUM_MMX2(%%mm1, %%mm7, %%mm0)
841         
842         "movq %%mm0, %%mm1              \n\t"
843         "psrlq $32, %%mm0               \n\t"
844         "paddusw %%mm1, %%mm0           \n\t"
845         "movq %%mm0, %%mm1              \n\t"
846         "psrlq $16, %%mm0               \n\t"
847         "paddusw %%mm1, %%mm0           \n\t"
848         "movd %%mm0, %0                 \n\t"
849                 
850         : "=r" (sum)
851         : "r"(temp)
852     );
853     return sum&0xFFFF;
854 }
855
856
857 WARPER88_1616(hadamard8_diff_mmx, hadamard8_diff16_mmx)
858 WARPER88_1616(hadamard8_diff_mmx2, hadamard8_diff16_mmx2)
859
860 #define put_no_rnd_pixels8_mmx(a,b,c,d) put_pixels8_mmx(a,b,c,d)
861 #define put_no_rnd_pixels16_mmx(a,b,c,d) put_pixels16_mmx(a,b,c,d)
862
863 #define QPEL_V_LOW(m3,m4,m5,m6, pw_20, pw_3, rnd, in0, in1, in2, in7, out, OP)\
864         "paddw " #m4 ", " #m3 "         \n\t" /* x1 */\
865         "movq "MANGLE(ff_pw_20)", %%mm4         \n\t" /* 20 */\
866         "pmullw " #m3 ", %%mm4          \n\t" /* 20x1 */\
867         "movq "#in7", " #m3 "           \n\t" /* d */\
868         "movq "#in0", %%mm5             \n\t" /* D */\
869         "paddw " #m3 ", %%mm5           \n\t" /* x4 */\
870         "psubw %%mm5, %%mm4             \n\t" /* 20x1 - x4 */\
871         "movq "#in1", %%mm5             \n\t" /* C */\
872         "movq "#in2", %%mm6             \n\t" /* B */\
873         "paddw " #m6 ", %%mm5           \n\t" /* x3 */\
874         "paddw " #m5 ", %%mm6           \n\t" /* x2 */\
875         "paddw %%mm6, %%mm6             \n\t" /* 2x2 */\
876         "psubw %%mm6, %%mm5             \n\t" /* -2x2 + x3 */\
877         "pmullw "MANGLE(ff_pw_3)", %%mm5        \n\t" /* -6x2 + 3x3 */\
878         "paddw " #rnd ", %%mm4          \n\t" /* x2 */\
879         "paddw %%mm4, %%mm5             \n\t" /* 20x1 - 6x2 + 3x3 - x4 */\
880         "psraw $5, %%mm5                \n\t"\
881         "packuswb %%mm5, %%mm5          \n\t"\
882         OP(%%mm5, out, %%mm7, d)
883
884 #define QPEL_BASE(OPNAME, ROUNDER, RND, OP_MMX2, OP_3DNOW)\
885 static void OPNAME ## mpeg4_qpel16_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
886     uint64_t temp;\
887 \
888     asm volatile(\
889         "pxor %%mm7, %%mm7              \n\t"\
890         "1:                             \n\t"\
891         "movq  (%0), %%mm0              \n\t" /* ABCDEFGH */\
892         "movq %%mm0, %%mm1              \n\t" /* ABCDEFGH */\
893         "movq %%mm0, %%mm2              \n\t" /* ABCDEFGH */\
894         "punpcklbw %%mm7, %%mm0         \n\t" /* 0A0B0C0D */\
895         "punpckhbw %%mm7, %%mm1         \n\t" /* 0E0F0G0H */\
896         "pshufw $0x90, %%mm0, %%mm5     \n\t" /* 0A0A0B0C */\
897         "pshufw $0x41, %%mm0, %%mm6     \n\t" /* 0B0A0A0B */\
898         "movq %%mm2, %%mm3              \n\t" /* ABCDEFGH */\
899         "movq %%mm2, %%mm4              \n\t" /* ABCDEFGH */\
900         "psllq $8, %%mm2                \n\t" /* 0ABCDEFG */\
901         "psllq $16, %%mm3               \n\t" /* 00ABCDEF */\
902         "psllq $24, %%mm4               \n\t" /* 000ABCDE */\
903         "punpckhbw %%mm7, %%mm2         \n\t" /* 0D0E0F0G */\
904         "punpckhbw %%mm7, %%mm3         \n\t" /* 0C0D0E0F */\
905         "punpckhbw %%mm7, %%mm4         \n\t" /* 0B0C0D0E */\
906         "paddw %%mm3, %%mm5             \n\t" /* b */\
907         "paddw %%mm2, %%mm6             \n\t" /* c */\
908         "paddw %%mm5, %%mm5             \n\t" /* 2b */\
909         "psubw %%mm5, %%mm6             \n\t" /* c - 2b */\
910         "pshufw $0x06, %%mm0, %%mm5     \n\t" /* 0C0B0A0A */\
911         "pmullw "MANGLE(ff_pw_3)", %%mm6                \n\t" /* 3c - 6b */\
912         "paddw %%mm4, %%mm0             \n\t" /* a */\
913         "paddw %%mm1, %%mm5             \n\t" /* d */\
914         "pmullw "MANGLE(ff_pw_20)", %%mm0               \n\t" /* 20a */\
915         "psubw %%mm5, %%mm0             \n\t" /* 20a - d */\
916         "paddw %6, %%mm6                \n\t"\
917         "paddw %%mm6, %%mm0             \n\t" /* 20a - 6b + 3c - d */\
918         "psraw $5, %%mm0                \n\t"\
919         "movq %%mm0, %5                 \n\t"\
920         /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\
921         \
922         "movq 5(%0), %%mm0              \n\t" /* FGHIJKLM */\
923         "movq %%mm0, %%mm5              \n\t" /* FGHIJKLM */\
924         "movq %%mm0, %%mm6              \n\t" /* FGHIJKLM */\
925         "psrlq $8, %%mm0                \n\t" /* GHIJKLM0 */\
926         "psrlq $16, %%mm5               \n\t" /* HIJKLM00 */\
927         "punpcklbw %%mm7, %%mm0         \n\t" /* 0G0H0I0J */\
928         "punpcklbw %%mm7, %%mm5         \n\t" /* 0H0I0J0K */\
929         "paddw %%mm0, %%mm2             \n\t" /* b */\
930         "paddw %%mm5, %%mm3             \n\t" /* c */\
931         "paddw %%mm2, %%mm2             \n\t" /* 2b */\
932         "psubw %%mm2, %%mm3             \n\t" /* c - 2b */\
933         "movq %%mm6, %%mm2              \n\t" /* FGHIJKLM */\
934         "psrlq $24, %%mm6               \n\t" /* IJKLM000 */\
935         "punpcklbw %%mm7, %%mm2         \n\t" /* 0F0G0H0I */\
936         "punpcklbw %%mm7, %%mm6         \n\t" /* 0I0J0K0L */\
937         "pmullw "MANGLE(ff_pw_3)", %%mm3                \n\t" /* 3c - 6b */\
938         "paddw %%mm2, %%mm1             \n\t" /* a */\
939         "paddw %%mm6, %%mm4             \n\t" /* d */\
940         "pmullw "MANGLE(ff_pw_20)", %%mm1               \n\t" /* 20a */\
941         "psubw %%mm4, %%mm3             \n\t" /* - 6b +3c - d */\
942         "paddw %6, %%mm1                \n\t"\
943         "paddw %%mm1, %%mm3             \n\t" /* 20a - 6b +3c - d */\
944         "psraw $5, %%mm3                \n\t"\
945         "movq %5, %%mm1                 \n\t"\
946         "packuswb %%mm3, %%mm1          \n\t"\
947         OP_MMX2(%%mm1, (%1),%%mm4, q)\
948         /* mm0= GHIJ, mm2=FGHI, mm5=HIJK, mm6=IJKL, mm7=0 */\
949         \
950         "movq 9(%0), %%mm1              \n\t" /* JKLMNOPQ */\
951         "movq %%mm1, %%mm4              \n\t" /* JKLMNOPQ */\
952         "movq %%mm1, %%mm3              \n\t" /* JKLMNOPQ */\
953         "psrlq $8, %%mm1                \n\t" /* KLMNOPQ0 */\
954         "psrlq $16, %%mm4               \n\t" /* LMNOPQ00 */\
955         "punpcklbw %%mm7, %%mm1         \n\t" /* 0K0L0M0N */\
956         "punpcklbw %%mm7, %%mm4         \n\t" /* 0L0M0N0O */\
957         "paddw %%mm1, %%mm5             \n\t" /* b */\
958         "paddw %%mm4, %%mm0             \n\t" /* c */\
959         "paddw %%mm5, %%mm5             \n\t" /* 2b */\
960         "psubw %%mm5, %%mm0             \n\t" /* c - 2b */\
961         "movq %%mm3, %%mm5              \n\t" /* JKLMNOPQ */\
962         "psrlq $24, %%mm3               \n\t" /* MNOPQ000 */\
963         "pmullw "MANGLE(ff_pw_3)", %%mm0                \n\t" /* 3c - 6b */\
964         "punpcklbw %%mm7, %%mm3         \n\t" /* 0M0N0O0P */\
965         "paddw %%mm3, %%mm2             \n\t" /* d */\
966         "psubw %%mm2, %%mm0             \n\t" /* -6b + 3c - d */\
967         "movq %%mm5, %%mm2              \n\t" /* JKLMNOPQ */\
968         "punpcklbw %%mm7, %%mm2         \n\t" /* 0J0K0L0M */\
969         "punpckhbw %%mm7, %%mm5         \n\t" /* 0N0O0P0Q */\
970         "paddw %%mm2, %%mm6             \n\t" /* a */\
971         "pmullw "MANGLE(ff_pw_20)", %%mm6               \n\t" /* 20a */\
972         "paddw %6, %%mm0                \n\t"\
973         "paddw %%mm6, %%mm0             \n\t" /* 20a - 6b + 3c - d */\
974         "psraw $5, %%mm0                \n\t"\
975         /* mm1=KLMN, mm2=JKLM, mm3=MNOP, mm4=LMNO, mm5=NOPQ mm7=0 */\
976         \
977         "paddw %%mm5, %%mm3             \n\t" /* a */\
978         "pshufw $0xF9, %%mm5, %%mm6     \n\t" /* 0O0P0Q0Q */\
979         "paddw %%mm4, %%mm6             \n\t" /* b */\
980         "pshufw $0xBE, %%mm5, %%mm4     \n\t" /* 0P0Q0Q0P */\
981         "pshufw $0x6F, %%mm5, %%mm5     \n\t" /* 0Q0Q0P0O */\
982         "paddw %%mm1, %%mm4             \n\t" /* c */\
983         "paddw %%mm2, %%mm5             \n\t" /* d */\
984         "paddw %%mm6, %%mm6             \n\t" /* 2b */\
985         "psubw %%mm6, %%mm4             \n\t" /* c - 2b */\
986         "pmullw "MANGLE(ff_pw_20)", %%mm3               \n\t" /* 20a */\
987         "pmullw "MANGLE(ff_pw_3)", %%mm4                \n\t" /* 3c - 6b */\
988         "psubw %%mm5, %%mm3             \n\t" /* -6b + 3c - d */\
989         "paddw %6, %%mm4                \n\t"\
990         "paddw %%mm3, %%mm4             \n\t" /* 20a - 6b + 3c - d */\
991         "psraw $5, %%mm4                \n\t"\
992         "packuswb %%mm4, %%mm0          \n\t"\
993         OP_MMX2(%%mm0, 8(%1), %%mm4, q)\
994         \
995         "addl %3, %0                    \n\t"\
996         "addl %4, %1                    \n\t"\
997         "decl %2                        \n\t"\
998         " jnz 1b                                \n\t"\
999         : "+a"(src), "+c"(dst), "+m"(h)\
1000         : "d"(srcStride), "S"(dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\
1001         : "memory"\
1002     );\
1003 }\
1004 \
1005 static void OPNAME ## mpeg4_qpel16_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
1006     int i;\
1007     int16_t temp[16];\
1008     /* quick HACK, XXX FIXME MUST be optimized */\
1009     for(i=0; i<h; i++)\
1010     {\
1011         temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\
1012         temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\
1013         temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\
1014         temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\
1015         temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\
1016         temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 9]);\
1017         temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 9])*3 - (src[ 3]+src[10]);\
1018         temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 9])*6 + (src[ 5]+src[10])*3 - (src[ 4]+src[11]);\
1019         temp[ 8]= (src[ 8]+src[ 9])*20 - (src[ 7]+src[10])*6 + (src[ 6]+src[11])*3 - (src[ 5]+src[12]);\
1020         temp[ 9]= (src[ 9]+src[10])*20 - (src[ 8]+src[11])*6 + (src[ 7]+src[12])*3 - (src[ 6]+src[13]);\
1021         temp[10]= (src[10]+src[11])*20 - (src[ 9]+src[12])*6 + (src[ 8]+src[13])*3 - (src[ 7]+src[14]);\
1022         temp[11]= (src[11]+src[12])*20 - (src[10]+src[13])*6 + (src[ 9]+src[14])*3 - (src[ 8]+src[15]);\
1023         temp[12]= (src[12]+src[13])*20 - (src[11]+src[14])*6 + (src[10]+src[15])*3 - (src[ 9]+src[16]);\
1024         temp[13]= (src[13]+src[14])*20 - (src[12]+src[15])*6 + (src[11]+src[16])*3 - (src[10]+src[16]);\
1025         temp[14]= (src[14]+src[15])*20 - (src[13]+src[16])*6 + (src[12]+src[16])*3 - (src[11]+src[15]);\
1026         temp[15]= (src[15]+src[16])*20 - (src[14]+src[16])*6 + (src[13]+src[15])*3 - (src[12]+src[14]);\
1027         asm volatile(\
1028             "movq (%0), %%mm0           \n\t"\
1029             "movq 8(%0), %%mm1          \n\t"\
1030             "paddw %2, %%mm0            \n\t"\
1031             "paddw %2, %%mm1            \n\t"\
1032             "psraw $5, %%mm0            \n\t"\
1033             "psraw $5, %%mm1            \n\t"\
1034             "packuswb %%mm1, %%mm0      \n\t"\
1035             OP_3DNOW(%%mm0, (%1), %%mm1, q)\
1036             "movq 16(%0), %%mm0         \n\t"\
1037             "movq 24(%0), %%mm1         \n\t"\
1038             "paddw %2, %%mm0            \n\t"\
1039             "paddw %2, %%mm1            \n\t"\
1040             "psraw $5, %%mm0            \n\t"\
1041             "psraw $5, %%mm1            \n\t"\
1042             "packuswb %%mm1, %%mm0      \n\t"\
1043             OP_3DNOW(%%mm0, 8(%1), %%mm1, q)\
1044             :: "r"(temp), "r"(dst), "m"(ROUNDER)\
1045             : "memory"\
1046         );\
1047         dst+=dstStride;\
1048         src+=srcStride;\
1049     }\
1050 }\
1051 \
1052 static void OPNAME ## mpeg4_qpel8_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
1053     uint64_t temp;\
1054 \
1055     asm volatile(\
1056         "pxor %%mm7, %%mm7              \n\t"\
1057         "1:                             \n\t"\
1058         "movq  (%0), %%mm0              \n\t" /* ABCDEFGH */\
1059         "movq %%mm0, %%mm1              \n\t" /* ABCDEFGH */\
1060         "movq %%mm0, %%mm2              \n\t" /* ABCDEFGH */\
1061         "punpcklbw %%mm7, %%mm0         \n\t" /* 0A0B0C0D */\
1062         "punpckhbw %%mm7, %%mm1         \n\t" /* 0E0F0G0H */\
1063         "pshufw $0x90, %%mm0, %%mm5     \n\t" /* 0A0A0B0C */\
1064         "pshufw $0x41, %%mm0, %%mm6     \n\t" /* 0B0A0A0B */\
1065         "movq %%mm2, %%mm3              \n\t" /* ABCDEFGH */\
1066         "movq %%mm2, %%mm4              \n\t" /* ABCDEFGH */\
1067         "psllq $8, %%mm2                \n\t" /* 0ABCDEFG */\
1068         "psllq $16, %%mm3               \n\t" /* 00ABCDEF */\
1069         "psllq $24, %%mm4               \n\t" /* 000ABCDE */\
1070         "punpckhbw %%mm7, %%mm2         \n\t" /* 0D0E0F0G */\
1071         "punpckhbw %%mm7, %%mm3         \n\t" /* 0C0D0E0F */\
1072         "punpckhbw %%mm7, %%mm4         \n\t" /* 0B0C0D0E */\
1073         "paddw %%mm3, %%mm5             \n\t" /* b */\
1074         "paddw %%mm2, %%mm6             \n\t" /* c */\
1075         "paddw %%mm5, %%mm5             \n\t" /* 2b */\
1076         "psubw %%mm5, %%mm6             \n\t" /* c - 2b */\
1077         "pshufw $0x06, %%mm0, %%mm5     \n\t" /* 0C0B0A0A */\
1078         "pmullw "MANGLE(ff_pw_3)", %%mm6                \n\t" /* 3c - 6b */\
1079         "paddw %%mm4, %%mm0             \n\t" /* a */\
1080         "paddw %%mm1, %%mm5             \n\t" /* d */\
1081         "pmullw "MANGLE(ff_pw_20)", %%mm0               \n\t" /* 20a */\
1082         "psubw %%mm5, %%mm0             \n\t" /* 20a - d */\
1083         "paddw %6, %%mm6                \n\t"\
1084         "paddw %%mm6, %%mm0             \n\t" /* 20a - 6b + 3c - d */\
1085         "psraw $5, %%mm0                \n\t"\
1086         /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\
1087         \
1088         "movd 5(%0), %%mm5              \n\t" /* FGHI */\
1089         "punpcklbw %%mm7, %%mm5         \n\t" /* 0F0G0H0I */\
1090         "pshufw $0xF9, %%mm5, %%mm6     \n\t" /* 0G0H0I0I */\
1091         "paddw %%mm5, %%mm1             \n\t" /* a */\
1092         "paddw %%mm6, %%mm2             \n\t" /* b */\
1093         "pshufw $0xBE, %%mm5, %%mm6     \n\t" /* 0H0I0I0H */\
1094         "pshufw $0x6F, %%mm5, %%mm5     \n\t" /* 0I0I0H0G */\
1095         "paddw %%mm6, %%mm3             \n\t" /* c */\
1096         "paddw %%mm5, %%mm4             \n\t" /* d */\
1097         "paddw %%mm2, %%mm2             \n\t" /* 2b */\
1098         "psubw %%mm2, %%mm3             \n\t" /* c - 2b */\
1099         "pmullw "MANGLE(ff_pw_20)", %%mm1               \n\t" /* 20a */\
1100         "pmullw "MANGLE(ff_pw_3)", %%mm3                \n\t" /* 3c - 6b */\
1101         "psubw %%mm4, %%mm3             \n\t" /* -6b + 3c - d */\
1102         "paddw %6, %%mm1                \n\t"\
1103         "paddw %%mm1, %%mm3             \n\t" /* 20a - 6b + 3c - d */\
1104         "psraw $5, %%mm3                \n\t"\
1105         "packuswb %%mm3, %%mm0          \n\t"\
1106         OP_MMX2(%%mm0, (%1), %%mm4, q)\
1107         \
1108         "addl %3, %0                    \n\t"\
1109         "addl %4, %1                    \n\t"\
1110         "decl %2                        \n\t"\
1111         " jnz 1b                        \n\t"\
1112         : "+a"(src), "+c"(dst), "+m"(h)\
1113         : "S"(srcStride), "D"(dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\
1114         : "memory"\
1115     );\
1116 }\
1117 \
1118 static void OPNAME ## mpeg4_qpel8_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
1119     int i;\
1120     int16_t temp[8];\
1121     /* quick HACK, XXX FIXME MUST be optimized */\
1122     for(i=0; i<h; i++)\
1123     {\
1124         temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\
1125         temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\
1126         temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\
1127         temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\
1128         temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\
1129         temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 8]);\
1130         temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 8])*3 - (src[ 3]+src[ 7]);\
1131         temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 8])*6 + (src[ 5]+src[ 7])*3 - (src[ 4]+src[ 6]);\
1132         asm volatile(\
1133             "movq (%0), %%mm0           \n\t"\
1134             "movq 8(%0), %%mm1          \n\t"\
1135             "paddw %2, %%mm0            \n\t"\
1136             "paddw %2, %%mm1            \n\t"\
1137             "psraw $5, %%mm0            \n\t"\
1138             "psraw $5, %%mm1            \n\t"\
1139             "packuswb %%mm1, %%mm0      \n\t"\
1140             OP_3DNOW(%%mm0, (%1), %%mm1, q)\
1141             :: "r"(temp), "r"(dst), "m"(ROUNDER)\
1142             :"memory"\
1143         );\
1144         dst+=dstStride;\
1145         src+=srcStride;\
1146     }\
1147 }
1148
1149 #define QPEL_OP(OPNAME, ROUNDER, RND, OP, MMX)\
1150 \
1151 static void OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
1152     uint64_t temp[17*4];\
1153     uint64_t *temp_ptr= temp;\
1154     int count= 17;\
1155 \
1156     /*FIXME unroll */\
1157     asm volatile(\
1158         "pxor %%mm7, %%mm7              \n\t"\
1159         "1:                             \n\t"\
1160         "movq (%0), %%mm0               \n\t"\
1161         "movq (%0), %%mm1               \n\t"\
1162         "movq 8(%0), %%mm2              \n\t"\
1163         "movq 8(%0), %%mm3              \n\t"\
1164         "punpcklbw %%mm7, %%mm0         \n\t"\
1165         "punpckhbw %%mm7, %%mm1         \n\t"\
1166         "punpcklbw %%mm7, %%mm2         \n\t"\
1167         "punpckhbw %%mm7, %%mm3         \n\t"\
1168         "movq %%mm0, (%1)               \n\t"\
1169         "movq %%mm1, 17*8(%1)           \n\t"\
1170         "movq %%mm2, 2*17*8(%1)         \n\t"\
1171         "movq %%mm3, 3*17*8(%1)         \n\t"\
1172         "addl $8, %1                    \n\t"\
1173         "addl %3, %0                    \n\t"\
1174         "decl %2                        \n\t"\
1175         " jnz 1b                        \n\t"\
1176         : "+r" (src), "+r" (temp_ptr), "+r"(count)\
1177         : "r" (srcStride)\
1178         : "memory"\
1179     );\
1180     \
1181     temp_ptr= temp;\
1182     count=4;\
1183     \
1184 /*FIXME reorder for speed */\
1185     asm volatile(\
1186         /*"pxor %%mm7, %%mm7            \n\t"*/\
1187         "1:                             \n\t"\
1188         "movq (%0), %%mm0               \n\t"\
1189         "movq 8(%0), %%mm1              \n\t"\
1190         "movq 16(%0), %%mm2             \n\t"\
1191         "movq 24(%0), %%mm3             \n\t"\
1192         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)\
1193         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)\
1194         "addl %4, %1                    \n\t"\
1195         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)\
1196         \
1197         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)\
1198         "addl %4, %1                    \n\t"\
1199         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\
1200         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 72(%0), (%1, %3), OP)\
1201         "addl %4, %1                    \n\t"\
1202         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 80(%0), (%1), OP)\
1203         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 88(%0), (%1, %3), OP)\
1204         "addl %4, %1                    \n\t"\
1205         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 40(%0), 48(%0), 56(%0), 96(%0), (%1), OP)\
1206         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 48(%0), 56(%0), 64(%0),104(%0), (%1, %3), OP)\
1207         "addl %4, %1                    \n\t"\
1208         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 56(%0), 64(%0), 72(%0),112(%0), (%1), OP)\
1209         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 64(%0), 72(%0), 80(%0),120(%0), (%1, %3), OP)\
1210         "addl %4, %1                    \n\t"\
1211         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 72(%0), 80(%0), 88(%0),128(%0), (%1), OP)\
1212         \
1213         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 80(%0), 88(%0), 96(%0),128(%0), (%1, %3), OP)\
1214         "addl %4, %1                    \n\t"  \
1215         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 88(%0), 96(%0),104(%0),120(%0), (%1), OP)\
1216         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 96(%0),104(%0),112(%0),112(%0), (%1, %3), OP)\
1217         \
1218         "addl $136, %0                  \n\t"\
1219         "addl %6, %1                    \n\t"\
1220         "decl %2                        \n\t"\
1221         " jnz 1b                        \n\t"\
1222         \
1223         : "+r"(temp_ptr), "+r"(dst), "+g"(count)\
1224         : "r"(dstStride), "r"(2*dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-14*dstStride)\
1225         :"memory"\
1226     );\
1227 }\
1228 \
1229 static void OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
1230     uint64_t temp[9*4];\
1231     uint64_t *temp_ptr= temp;\
1232     int count= 9;\
1233 \
1234     /*FIXME unroll */\
1235     asm volatile(\
1236         "pxor %%mm7, %%mm7              \n\t"\
1237         "1:                             \n\t"\
1238         "movq (%0), %%mm0               \n\t"\
1239         "movq (%0), %%mm1               \n\t"\
1240         "punpcklbw %%mm7, %%mm0         \n\t"\
1241         "punpckhbw %%mm7, %%mm1         \n\t"\
1242         "movq %%mm0, (%1)               \n\t"\
1243         "movq %%mm1, 9*8(%1)            \n\t"\
1244         "addl $8, %1                    \n\t"\
1245         "addl %3, %0                    \n\t"\
1246         "decl %2                        \n\t"\
1247         " jnz 1b                        \n\t"\
1248         : "+r" (src), "+r" (temp_ptr), "+r"(count)\
1249         : "r" (srcStride)\
1250         : "memory"\
1251     );\
1252     \
1253     temp_ptr= temp;\
1254     count=2;\
1255     \
1256 /*FIXME reorder for speed */\
1257     asm volatile(\
1258         /*"pxor %%mm7, %%mm7            \n\t"*/\
1259         "1:                             \n\t"\
1260         "movq (%0), %%mm0               \n\t"\
1261         "movq 8(%0), %%mm1              \n\t"\
1262         "movq 16(%0), %%mm2             \n\t"\
1263         "movq 24(%0), %%mm3             \n\t"\
1264         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)\
1265         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)\
1266         "addl %4, %1                    \n\t"\
1267         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)\
1268         \
1269         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)\
1270         "addl %4, %1                    \n\t"\
1271         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\
1272         \
1273         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 64(%0), (%1, %3), OP)\
1274         "addl %4, %1                    \n\t"\
1275         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 56(%0), (%1), OP)\
1276         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 48(%0), (%1, %3), OP)\
1277                 \
1278         "addl $72, %0                   \n\t"\
1279         "addl %6, %1                    \n\t"\
1280         "decl %2                        \n\t"\
1281         " jnz 1b                        \n\t"\
1282          \
1283         : "+r"(temp_ptr), "+r"(dst), "+g"(count)\
1284         : "r"(dstStride), "r"(2*dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-6*dstStride)\
1285         : "memory"\
1286    );\
1287 }\
1288 \
1289 static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
1290     OPNAME ## pixels8_mmx(dst, src, stride, 8);\
1291 }\
1292 \
1293 static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1294     uint64_t temp[8];\
1295     uint8_t * const half= (uint8_t*)temp;\
1296     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
1297     OPNAME ## pixels8_l2_mmx(dst, src, half, stride, stride, 8);\
1298 }\
1299 \
1300 static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1301     OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, stride, 8);\
1302 }\
1303 \
1304 static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1305     uint64_t temp[8];\
1306     uint8_t * const half= (uint8_t*)temp;\
1307     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
1308     OPNAME ## pixels8_l2_mmx(dst, src+1, half, stride, stride, 8);\
1309 }\
1310 \
1311 static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1312     uint64_t temp[8];\
1313     uint8_t * const half= (uint8_t*)temp;\
1314     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
1315     OPNAME ## pixels8_l2_mmx(dst, src, half, stride, stride, 8);\
1316 }\
1317 \
1318 static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1319     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, stride, stride);\
1320 }\
1321 \
1322 static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1323     uint64_t temp[8];\
1324     uint8_t * const half= (uint8_t*)temp;\
1325     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
1326     OPNAME ## pixels8_l2_mmx(dst, src+stride, half, stride, stride, 8);\
1327 }\
1328 static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1329     uint64_t half[8 + 9];\
1330     uint8_t * const halfH= ((uint8_t*)half) + 64;\
1331     uint8_t * const halfHV= ((uint8_t*)half);\
1332     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1333     put ## RND ## pixels8_l2_mmx(halfH, src, halfH, 8, stride, 9);\
1334     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
1335     OPNAME ## pixels8_l2_mmx(dst, halfH, halfHV, stride, 8, 8);\
1336 }\
1337 static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1338     uint64_t half[8 + 9];\
1339     uint8_t * const halfH= ((uint8_t*)half) + 64;\
1340     uint8_t * const halfHV= ((uint8_t*)half);\
1341     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1342     put ## RND ## pixels8_l2_mmx(halfH, src+1, halfH, 8, stride, 9);\
1343     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
1344     OPNAME ## pixels8_l2_mmx(dst, halfH, halfHV, stride, 8, 8);\
1345 }\
1346 static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1347     uint64_t half[8 + 9];\
1348     uint8_t * const halfH= ((uint8_t*)half) + 64;\
1349     uint8_t * const halfHV= ((uint8_t*)half);\
1350     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1351     put ## RND ## pixels8_l2_mmx(halfH, src, halfH, 8, stride, 9);\
1352     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
1353     OPNAME ## pixels8_l2_mmx(dst, halfH+8, halfHV, stride, 8, 8);\
1354 }\
1355 static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1356     uint64_t half[8 + 9];\
1357     uint8_t * const halfH= ((uint8_t*)half) + 64;\
1358     uint8_t * const halfHV= ((uint8_t*)half);\
1359     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1360     put ## RND ## pixels8_l2_mmx(halfH, src+1, halfH, 8, stride, 9);\
1361     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
1362     OPNAME ## pixels8_l2_mmx(dst, halfH+8, halfHV, stride, 8, 8);\
1363 }\
1364 static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1365     uint64_t half[8 + 9];\
1366     uint8_t * const halfH= ((uint8_t*)half) + 64;\
1367     uint8_t * const halfHV= ((uint8_t*)half);\
1368     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1369     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
1370     OPNAME ## pixels8_l2_mmx(dst, halfH, halfHV, stride, 8, 8);\
1371 }\
1372 static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1373     uint64_t half[8 + 9];\
1374     uint8_t * const halfH= ((uint8_t*)half) + 64;\
1375     uint8_t * const halfHV= ((uint8_t*)half);\
1376     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1377     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
1378     OPNAME ## pixels8_l2_mmx(dst, halfH+8, halfHV, stride, 8, 8);\
1379 }\
1380 static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1381     uint64_t half[8 + 9];\
1382     uint8_t * const halfH= ((uint8_t*)half);\
1383     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1384     put ## RND ## pixels8_l2_mmx(halfH, src, halfH, 8, stride, 9);\
1385     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
1386 }\
1387 static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1388     uint64_t half[8 + 9];\
1389     uint8_t * const halfH= ((uint8_t*)half);\
1390     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1391     put ## RND ## pixels8_l2_mmx(halfH, src+1, halfH, 8, stride, 9);\
1392     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
1393 }\
1394 static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1395     uint64_t half[9];\
1396     uint8_t * const halfH= ((uint8_t*)half);\
1397     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
1398     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
1399 }\
1400 static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
1401     OPNAME ## pixels16_mmx(dst, src, stride, 16);\
1402 }\
1403 \
1404 static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1405     uint64_t temp[32];\
1406     uint8_t * const half= (uint8_t*)temp;\
1407     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
1408     OPNAME ## pixels16_l2_mmx(dst, src, half, stride, stride, 16);\
1409 }\
1410 \
1411 static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1412     OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, stride, stride, 16);\
1413 }\
1414 \
1415 static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1416     uint64_t temp[32];\
1417     uint8_t * const half= (uint8_t*)temp;\
1418     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
1419     OPNAME ## pixels16_l2_mmx(dst, src+1, half, stride, stride, 16);\
1420 }\
1421 \
1422 static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1423     uint64_t temp[32];\
1424     uint8_t * const half= (uint8_t*)temp;\
1425     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
1426     OPNAME ## pixels16_l2_mmx(dst, src, half, stride, stride, 16);\
1427 }\
1428 \
1429 static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1430     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, stride, stride);\
1431 }\
1432 \
1433 static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1434     uint64_t temp[32];\
1435     uint8_t * const half= (uint8_t*)temp;\
1436     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
1437     OPNAME ## pixels16_l2_mmx(dst, src+stride, half, stride, stride, 16);\
1438 }\
1439 static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1440     uint64_t half[16*2 + 17*2];\
1441     uint8_t * const halfH= ((uint8_t*)half) + 256;\
1442     uint8_t * const halfHV= ((uint8_t*)half);\
1443     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1444     put ## RND ## pixels16_l2_mmx(halfH, src, halfH, 16, stride, 17);\
1445     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
1446     OPNAME ## pixels16_l2_mmx(dst, halfH, halfHV, stride, 16, 16);\
1447 }\
1448 static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1449     uint64_t half[16*2 + 17*2];\
1450     uint8_t * const halfH= ((uint8_t*)half) + 256;\
1451     uint8_t * const halfHV= ((uint8_t*)half);\
1452     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1453     put ## RND ## pixels16_l2_mmx(halfH, src+1, halfH, 16, stride, 17);\
1454     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
1455     OPNAME ## pixels16_l2_mmx(dst, halfH, halfHV, stride, 16, 16);\
1456 }\
1457 static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1458     uint64_t half[16*2 + 17*2];\
1459     uint8_t * const halfH= ((uint8_t*)half) + 256;\
1460     uint8_t * const halfHV= ((uint8_t*)half);\
1461     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1462     put ## RND ## pixels16_l2_mmx(halfH, src, halfH, 16, stride, 17);\
1463     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
1464     OPNAME ## pixels16_l2_mmx(dst, halfH+16, halfHV, stride, 16, 16);\
1465 }\
1466 static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1467     uint64_t half[16*2 + 17*2];\
1468     uint8_t * const halfH= ((uint8_t*)half) + 256;\
1469     uint8_t * const halfHV= ((uint8_t*)half);\
1470     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1471     put ## RND ## pixels16_l2_mmx(halfH, src+1, halfH, 16, stride, 17);\
1472     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
1473     OPNAME ## pixels16_l2_mmx(dst, halfH+16, halfHV, stride, 16, 16);\
1474 }\
1475 static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1476     uint64_t half[16*2 + 17*2];\
1477     uint8_t * const halfH= ((uint8_t*)half) + 256;\
1478     uint8_t * const halfHV= ((uint8_t*)half);\
1479     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1480     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
1481     OPNAME ## pixels16_l2_mmx(dst, halfH, halfHV, stride, 16, 16);\
1482 }\
1483 static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1484     uint64_t half[16*2 + 17*2];\
1485     uint8_t * const halfH= ((uint8_t*)half) + 256;\
1486     uint8_t * const halfHV= ((uint8_t*)half);\
1487     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1488     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
1489     OPNAME ## pixels16_l2_mmx(dst, halfH+16, halfHV, stride, 16, 16);\
1490 }\
1491 static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1492     uint64_t half[17*2];\
1493     uint8_t * const halfH= ((uint8_t*)half);\
1494     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1495     put ## RND ## pixels16_l2_mmx(halfH, src, halfH, 16, stride, 17);\
1496     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
1497 }\
1498 static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1499     uint64_t half[17*2];\
1500     uint8_t * const halfH= ((uint8_t*)half);\
1501     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1502     put ## RND ## pixels16_l2_mmx(halfH, src+1, halfH, 16, stride, 17);\
1503     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
1504 }\
1505 static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
1506     uint64_t half[17*2];\
1507     uint8_t * const halfH= ((uint8_t*)half);\
1508     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
1509     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
1510 }
1511
1512
1513 #define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b "     \n\t"
1514 #define AVG_3DNOW_OP(a,b,temp, size) \
1515 "mov" #size " " #b ", " #temp " \n\t"\
1516 "pavgusb " #temp ", " #a "      \n\t"\
1517 "mov" #size " " #a ", " #b "    \n\t"
1518 #define AVG_MMX2_OP(a,b,temp, size) \
1519 "mov" #size " " #b ", " #temp " \n\t"\
1520 "pavgb " #temp ", " #a "        \n\t"\
1521 "mov" #size " " #a ", " #b "    \n\t"
1522
1523 QPEL_BASE(put_       , ff_pw_16, _       , PUT_OP, PUT_OP)
1524 QPEL_BASE(avg_       , ff_pw_16, _       , AVG_MMX2_OP, AVG_3DNOW_OP)
1525 QPEL_BASE(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, PUT_OP)
1526 QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, 3dnow)
1527 QPEL_OP(avg_       , ff_pw_16, _       , AVG_3DNOW_OP, 3dnow)
1528 QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, 3dnow)
1529 QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, mmx2)
1530 QPEL_OP(avg_       , ff_pw_16, _       , AVG_MMX2_OP, mmx2)
1531 QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, mmx2)
1532
1533 #if 0
1534 static void just_return() { return; }
1535 #endif
1536
1537 #define SET_QPEL_FUNC(postfix1, postfix2) \
1538     c->put_ ## postfix1 = put_ ## postfix2;\
1539     c->put_no_rnd_ ## postfix1 = put_no_rnd_ ## postfix2;\
1540     c->avg_ ## postfix1 = avg_ ## postfix2;
1541
1542 /* external functions, from idct_mmx.c */
1543 void ff_mmx_idct(DCTELEM *block);
1544 void ff_mmxext_idct(DCTELEM *block);
1545
1546 /* XXX: those functions should be suppressed ASAP when all IDCTs are
1547    converted */
1548 static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
1549 {
1550     ff_mmx_idct (block);
1551     put_pixels_clamped_mmx(block, dest, line_size);
1552 }
1553 static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
1554 {
1555     ff_mmx_idct (block);
1556     add_pixels_clamped_mmx(block, dest, line_size);
1557 }
1558 static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
1559 {
1560     ff_mmxext_idct (block);
1561     put_pixels_clamped_mmx(block, dest, line_size);
1562 }
1563 static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
1564 {
1565     ff_mmxext_idct (block);
1566     add_pixels_clamped_mmx(block, dest, line_size);
1567 }
1568     
1569 void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
1570 {
1571     mm_flags = mm_support();
1572
1573     if (avctx->dsp_mask) {
1574         if (avctx->dsp_mask & FF_MM_FORCE)
1575             mm_flags |= (avctx->dsp_mask & 0xffff);
1576         else
1577             mm_flags &= ~(avctx->dsp_mask & 0xffff);
1578     }
1579
1580 #if 0
1581     fprintf(stderr, "libavcodec: CPU flags:");
1582     if (mm_flags & MM_MMX)
1583         fprintf(stderr, " mmx");
1584     if (mm_flags & MM_MMXEXT)
1585         fprintf(stderr, " mmxext");
1586     if (mm_flags & MM_3DNOW)
1587         fprintf(stderr, " 3dnow");
1588     if (mm_flags & MM_SSE)
1589         fprintf(stderr, " sse");
1590     if (mm_flags & MM_SSE2)
1591         fprintf(stderr, " sse2");
1592     fprintf(stderr, "\n");
1593 #endif
1594
1595     if (mm_flags & MM_MMX) {
1596         const int dct_algo = avctx->dct_algo;
1597         const int idct_algo= avctx->idct_algo;
1598
1599 #ifdef CONFIG_ENCODERS
1600         if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX)
1601             c->fdct = ff_fdct_mmx;
1602 #endif //CONFIG_ENCODERS
1603
1604         if(idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SIMPLEMMX){
1605             c->idct_put= ff_simple_idct_put_mmx;
1606             c->idct_add= ff_simple_idct_add_mmx;
1607             c->idct    = ff_simple_idct_mmx;
1608             c->idct_permutation_type= FF_SIMPLE_IDCT_PERM;
1609         }else if(idct_algo==FF_IDCT_LIBMPEG2MMX){
1610             if(mm_flags & MM_MMXEXT){
1611                 c->idct_put= ff_libmpeg2mmx2_idct_put;
1612                 c->idct_add= ff_libmpeg2mmx2_idct_add;
1613                 c->idct    = ff_mmxext_idct;
1614             }else{
1615                 c->idct_put= ff_libmpeg2mmx_idct_put;
1616                 c->idct_add= ff_libmpeg2mmx_idct_add;
1617                 c->idct    = ff_mmx_idct;
1618             }
1619             c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
1620         }
1621         
1622         c->get_pixels = get_pixels_mmx;
1623         c->diff_pixels = diff_pixels_mmx;
1624         c->put_pixels_clamped = put_pixels_clamped_mmx;
1625         c->add_pixels_clamped = add_pixels_clamped_mmx;
1626         c->clear_blocks = clear_blocks_mmx;
1627         c->pix_sum = pix_sum16_mmx;
1628
1629         c->put_pixels_tab[0][0] = put_pixels16_mmx;
1630         c->put_pixels_tab[0][1] = put_pixels16_x2_mmx;
1631         c->put_pixels_tab[0][2] = put_pixels16_y2_mmx;
1632         c->put_pixels_tab[0][3] = put_pixels16_xy2_mmx;
1633
1634         c->put_no_rnd_pixels_tab[0][0] = put_pixels16_mmx;
1635         c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx;
1636         c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx;
1637         c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_mmx;
1638
1639         c->avg_pixels_tab[0][0] = avg_pixels16_mmx;
1640         c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx;
1641         c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx;
1642         c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmx;
1643
1644         c->avg_no_rnd_pixels_tab[0][0] = avg_no_rnd_pixels16_mmx;
1645         c->avg_no_rnd_pixels_tab[0][1] = avg_no_rnd_pixels16_x2_mmx;
1646         c->avg_no_rnd_pixels_tab[0][2] = avg_no_rnd_pixels16_y2_mmx;
1647         c->avg_no_rnd_pixels_tab[0][3] = avg_no_rnd_pixels16_xy2_mmx;
1648
1649         c->put_pixels_tab[1][0] = put_pixels8_mmx;
1650         c->put_pixels_tab[1][1] = put_pixels8_x2_mmx;
1651         c->put_pixels_tab[1][2] = put_pixels8_y2_mmx;
1652         c->put_pixels_tab[1][3] = put_pixels8_xy2_mmx;
1653
1654         c->put_no_rnd_pixels_tab[1][0] = put_pixels8_mmx;
1655         c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_mmx;
1656         c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_mmx;
1657         c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_mmx;
1658
1659         c->avg_pixels_tab[1][0] = avg_pixels8_mmx;
1660         c->avg_pixels_tab[1][1] = avg_pixels8_x2_mmx;
1661         c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx;
1662         c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mmx;
1663
1664         c->avg_no_rnd_pixels_tab[1][0] = avg_no_rnd_pixels8_mmx;
1665         c->avg_no_rnd_pixels_tab[1][1] = avg_no_rnd_pixels8_x2_mmx;
1666         c->avg_no_rnd_pixels_tab[1][2] = avg_no_rnd_pixels8_y2_mmx;
1667         c->avg_no_rnd_pixels_tab[1][3] = avg_no_rnd_pixels8_xy2_mmx;
1668                 
1669         c->add_bytes= add_bytes_mmx;
1670         c->diff_bytes= diff_bytes_mmx;
1671         
1672         c->hadamard8_diff[0]= hadamard8_diff16_mmx;
1673         c->hadamard8_diff[1]= hadamard8_diff_mmx;
1674         
1675         c->pix_norm1 = pix_norm1_mmx;
1676         c->sse[0] = sse16_mmx;
1677         
1678         if (mm_flags & MM_MMXEXT) {
1679             c->put_pixels_tab[0][1] = put_pixels16_x2_mmx2;
1680             c->put_pixels_tab[0][2] = put_pixels16_y2_mmx2;
1681
1682             c->avg_pixels_tab[0][0] = avg_pixels16_mmx2;
1683             c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx2;
1684             c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx2;
1685
1686             c->put_pixels_tab[1][1] = put_pixels8_x2_mmx2;
1687             c->put_pixels_tab[1][2] = put_pixels8_y2_mmx2;
1688
1689             c->avg_pixels_tab[1][0] = avg_pixels8_mmx2;
1690             c->avg_pixels_tab[1][1] = avg_pixels8_x2_mmx2;
1691             c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx2;
1692
1693             c->hadamard8_diff[0]= hadamard8_diff16_mmx2;
1694             c->hadamard8_diff[1]= hadamard8_diff_mmx2;
1695
1696             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1697                 c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx2;
1698                 c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx2;
1699                 c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_mmx2;
1700                 c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_mmx2;
1701                 c->avg_pixels_tab[0][3] = avg_pixels16_xy2_mmx2;
1702                 c->avg_pixels_tab[1][3] = avg_pixels8_xy2_mmx2;
1703             }
1704
1705 #if 1
1706             SET_QPEL_FUNC(qpel_pixels_tab[0][ 0], qpel16_mc00_mmx2)
1707             SET_QPEL_FUNC(qpel_pixels_tab[0][ 1], qpel16_mc10_mmx2)
1708             SET_QPEL_FUNC(qpel_pixels_tab[0][ 2], qpel16_mc20_mmx2)
1709             SET_QPEL_FUNC(qpel_pixels_tab[0][ 3], qpel16_mc30_mmx2)
1710             SET_QPEL_FUNC(qpel_pixels_tab[0][ 4], qpel16_mc01_mmx2)
1711             SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_mmx2)
1712             SET_QPEL_FUNC(qpel_pixels_tab[0][ 6], qpel16_mc21_mmx2)
1713             SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_mmx2)
1714             SET_QPEL_FUNC(qpel_pixels_tab[0][ 8], qpel16_mc02_mmx2)
1715             SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_mmx2)
1716             SET_QPEL_FUNC(qpel_pixels_tab[0][10], qpel16_mc22_mmx2)
1717             SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_mmx2)
1718             SET_QPEL_FUNC(qpel_pixels_tab[0][12], qpel16_mc03_mmx2)
1719             SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_mmx2)
1720             SET_QPEL_FUNC(qpel_pixels_tab[0][14], qpel16_mc23_mmx2)
1721             SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_mmx2)
1722             SET_QPEL_FUNC(qpel_pixels_tab[1][ 0], qpel8_mc00_mmx2)
1723             SET_QPEL_FUNC(qpel_pixels_tab[1][ 1], qpel8_mc10_mmx2)
1724             SET_QPEL_FUNC(qpel_pixels_tab[1][ 2], qpel8_mc20_mmx2)
1725             SET_QPEL_FUNC(qpel_pixels_tab[1][ 3], qpel8_mc30_mmx2)
1726             SET_QPEL_FUNC(qpel_pixels_tab[1][ 4], qpel8_mc01_mmx2)
1727             SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_mmx2)
1728             SET_QPEL_FUNC(qpel_pixels_tab[1][ 6], qpel8_mc21_mmx2)
1729             SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_mmx2)
1730             SET_QPEL_FUNC(qpel_pixels_tab[1][ 8], qpel8_mc02_mmx2)
1731             SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_mmx2)
1732             SET_QPEL_FUNC(qpel_pixels_tab[1][10], qpel8_mc22_mmx2)
1733             SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_mmx2)
1734             SET_QPEL_FUNC(qpel_pixels_tab[1][12], qpel8_mc03_mmx2)
1735             SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_mmx2)
1736             SET_QPEL_FUNC(qpel_pixels_tab[1][14], qpel8_mc23_mmx2)
1737             SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_mmx2)
1738 #endif
1739
1740             c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_mmx2;
1741         } else if (mm_flags & MM_3DNOW) {
1742             c->put_pixels_tab[0][1] = put_pixels16_x2_3dnow;
1743             c->put_pixels_tab[0][2] = put_pixels16_y2_3dnow;
1744
1745             c->avg_pixels_tab[0][0] = avg_pixels16_3dnow;
1746             c->avg_pixels_tab[0][1] = avg_pixels16_x2_3dnow;
1747             c->avg_pixels_tab[0][2] = avg_pixels16_y2_3dnow;
1748
1749             c->put_pixels_tab[1][1] = put_pixels8_x2_3dnow;
1750             c->put_pixels_tab[1][2] = put_pixels8_y2_3dnow;
1751
1752             c->avg_pixels_tab[1][0] = avg_pixels8_3dnow;
1753             c->avg_pixels_tab[1][1] = avg_pixels8_x2_3dnow;
1754             c->avg_pixels_tab[1][2] = avg_pixels8_y2_3dnow;
1755
1756             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1757                 c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_3dnow;
1758                 c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_3dnow;
1759                 c->put_no_rnd_pixels_tab[1][1] = put_no_rnd_pixels8_x2_3dnow;
1760                 c->put_no_rnd_pixels_tab[1][2] = put_no_rnd_pixels8_y2_3dnow;
1761                 c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow;
1762                 c->avg_pixels_tab[1][3] = avg_pixels8_xy2_3dnow;
1763             }
1764
1765             SET_QPEL_FUNC(qpel_pixels_tab[0][ 0], qpel16_mc00_3dnow)
1766             SET_QPEL_FUNC(qpel_pixels_tab[0][ 1], qpel16_mc10_3dnow)
1767             SET_QPEL_FUNC(qpel_pixels_tab[0][ 2], qpel16_mc20_3dnow)
1768             SET_QPEL_FUNC(qpel_pixels_tab[0][ 3], qpel16_mc30_3dnow)
1769             SET_QPEL_FUNC(qpel_pixels_tab[0][ 4], qpel16_mc01_3dnow)
1770             SET_QPEL_FUNC(qpel_pixels_tab[0][ 5], qpel16_mc11_3dnow)
1771             SET_QPEL_FUNC(qpel_pixels_tab[0][ 6], qpel16_mc21_3dnow)
1772             SET_QPEL_FUNC(qpel_pixels_tab[0][ 7], qpel16_mc31_3dnow)
1773             SET_QPEL_FUNC(qpel_pixels_tab[0][ 8], qpel16_mc02_3dnow)
1774             SET_QPEL_FUNC(qpel_pixels_tab[0][ 9], qpel16_mc12_3dnow)
1775             SET_QPEL_FUNC(qpel_pixels_tab[0][10], qpel16_mc22_3dnow)
1776             SET_QPEL_FUNC(qpel_pixels_tab[0][11], qpel16_mc32_3dnow)
1777             SET_QPEL_FUNC(qpel_pixels_tab[0][12], qpel16_mc03_3dnow)
1778             SET_QPEL_FUNC(qpel_pixels_tab[0][13], qpel16_mc13_3dnow)
1779             SET_QPEL_FUNC(qpel_pixels_tab[0][14], qpel16_mc23_3dnow)
1780             SET_QPEL_FUNC(qpel_pixels_tab[0][15], qpel16_mc33_3dnow)
1781             SET_QPEL_FUNC(qpel_pixels_tab[1][ 0], qpel8_mc00_3dnow)
1782             SET_QPEL_FUNC(qpel_pixels_tab[1][ 1], qpel8_mc10_3dnow)
1783             SET_QPEL_FUNC(qpel_pixels_tab[1][ 2], qpel8_mc20_3dnow)
1784             SET_QPEL_FUNC(qpel_pixels_tab[1][ 3], qpel8_mc30_3dnow)
1785             SET_QPEL_FUNC(qpel_pixels_tab[1][ 4], qpel8_mc01_3dnow)
1786             SET_QPEL_FUNC(qpel_pixels_tab[1][ 5], qpel8_mc11_3dnow)
1787             SET_QPEL_FUNC(qpel_pixels_tab[1][ 6], qpel8_mc21_3dnow)
1788             SET_QPEL_FUNC(qpel_pixels_tab[1][ 7], qpel8_mc31_3dnow)
1789             SET_QPEL_FUNC(qpel_pixels_tab[1][ 8], qpel8_mc02_3dnow)
1790             SET_QPEL_FUNC(qpel_pixels_tab[1][ 9], qpel8_mc12_3dnow)
1791             SET_QPEL_FUNC(qpel_pixels_tab[1][10], qpel8_mc22_3dnow)
1792             SET_QPEL_FUNC(qpel_pixels_tab[1][11], qpel8_mc32_3dnow)
1793             SET_QPEL_FUNC(qpel_pixels_tab[1][12], qpel8_mc03_3dnow)
1794             SET_QPEL_FUNC(qpel_pixels_tab[1][13], qpel8_mc13_3dnow)
1795             SET_QPEL_FUNC(qpel_pixels_tab[1][14], qpel8_mc23_3dnow)
1796             SET_QPEL_FUNC(qpel_pixels_tab[1][15], qpel8_mc33_3dnow)
1797         }
1798     }
1799         
1800     dsputil_init_pix_mmx(c, avctx);
1801 #if 0
1802     // for speed testing
1803     get_pixels = just_return;
1804     put_pixels_clamped = just_return;
1805     add_pixels_clamped = just_return;
1806
1807     pix_abs16x16 = just_return;
1808     pix_abs16x16_x2 = just_return;
1809     pix_abs16x16_y2 = just_return;
1810     pix_abs16x16_xy2 = just_return;
1811
1812     put_pixels_tab[0] = just_return;
1813     put_pixels_tab[1] = just_return;
1814     put_pixels_tab[2] = just_return;
1815     put_pixels_tab[3] = just_return;
1816
1817     put_no_rnd_pixels_tab[0] = just_return;
1818     put_no_rnd_pixels_tab[1] = just_return;
1819     put_no_rnd_pixels_tab[2] = just_return;
1820     put_no_rnd_pixels_tab[3] = just_return;
1821
1822     avg_pixels_tab[0] = just_return;
1823     avg_pixels_tab[1] = just_return;
1824     avg_pixels_tab[2] = just_return;
1825     avg_pixels_tab[3] = just_return;
1826
1827     avg_no_rnd_pixels_tab[0] = just_return;
1828     avg_no_rnd_pixels_tab[1] = just_return;
1829     avg_no_rnd_pixels_tab[2] = just_return;
1830     avg_no_rnd_pixels_tab[3] = just_return;
1831
1832     //av_fdct = just_return;
1833     //ff_idct = just_return;
1834 #endif
1835 }