better separation of vp3dsp functions from dsputil_mmx.c
[ffmpeg.git] / libavcodec / i386 / dsputil_mmx.c
1 /*
2  * MMX optimized DSP utils
3  * Copyright (c) 2000, 2001 Fabrice Bellard.
4  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
23  */
24
25 #include "dsputil.h"
26 #include "simple_idct.h"
27 #include "mpegvideo.h"
28 #include "x86_cpu.h"
29 #include "mmx.h"
30 #include "vp3dsp_mmx.h"
31 #include "vp3dsp_sse2.h"
32
33 //#undef NDEBUG
34 //#include <assert.h>
35
36 extern void ff_idct_xvid_mmx(short *block);
37 extern void ff_idct_xvid_mmx2(short *block);
38
39 int mm_flags; /* multimedia extension flags */
40
41 /* pixel operations */
42 static const uint64_t mm_bone attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
43 static const uint64_t mm_wone attribute_used __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
44 static const uint64_t mm_wtwo attribute_used __attribute__ ((aligned(8))) = 0x0002000200020002ULL;
45
46 static const uint64_t ff_pdw_80000000[2] attribute_used __attribute__ ((aligned(16))) =
47 {0x8000000080000000ULL, 0x8000000080000000ULL};
48
49 static const uint64_t ff_pw_20 attribute_used __attribute__ ((aligned(8))) = 0x0014001400140014ULL;
50 static const uint64_t ff_pw_3  attribute_used __attribute__ ((aligned(8))) = 0x0003000300030003ULL;
51 static const uint64_t ff_pw_4  attribute_used __attribute__ ((aligned(8))) = 0x0004000400040004ULL;
52 static const uint64_t ff_pw_5  attribute_used __attribute__ ((aligned(8))) = 0x0005000500050005ULL;
53 static const uint64_t ff_pw_8  attribute_used __attribute__ ((aligned(8))) = 0x0008000800080008ULL;
54 static const uint64_t ff_pw_16 attribute_used __attribute__ ((aligned(8))) = 0x0010001000100010ULL;
55 static const uint64_t ff_pw_32 attribute_used __attribute__ ((aligned(8))) = 0x0020002000200020ULL;
56 static const uint64_t ff_pw_64 attribute_used __attribute__ ((aligned(8))) = 0x0040004000400040ULL;
57 static const uint64_t ff_pw_15 attribute_used __attribute__ ((aligned(8))) = 0x000F000F000F000FULL;
58
59 static const uint64_t ff_pb_1  attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
60 static const uint64_t ff_pb_3  attribute_used __attribute__ ((aligned(8))) = 0x0303030303030303ULL;
61 static const uint64_t ff_pb_7  attribute_used __attribute__ ((aligned(8))) = 0x0707070707070707ULL;
62 static const uint64_t ff_pb_3F attribute_used __attribute__ ((aligned(8))) = 0x3F3F3F3F3F3F3F3FULL;
63 static const uint64_t ff_pb_A1 attribute_used __attribute__ ((aligned(8))) = 0xA1A1A1A1A1A1A1A1ULL;
64 static const uint64_t ff_pb_5F attribute_used __attribute__ ((aligned(8))) = 0x5F5F5F5F5F5F5F5FULL;
65 static const uint64_t ff_pb_FC attribute_used __attribute__ ((aligned(8))) = 0xFCFCFCFCFCFCFCFCULL;
66
67 #define JUMPALIGN() __asm __volatile (ASMALIGN(3)::)
68 #define MOVQ_ZERO(regd)  __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
69
70 #define MOVQ_WONE(regd) \
71     __asm __volatile ( \
72     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
73     "psrlw $15, %%" #regd ::)
74
75 #define MOVQ_BFE(regd) \
76     __asm __volatile ( \
77     "pcmpeqd %%" #regd ", %%" #regd " \n\t"\
78     "paddb %%" #regd ", %%" #regd " \n\t" ::)
79
80 #ifndef PIC
81 #define MOVQ_BONE(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_bone))
82 #define MOVQ_WTWO(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_wtwo))
83 #else
84 // for shared library it's better to use this way for accessing constants
85 // pcmpeqd -> -1
86 #define MOVQ_BONE(regd) \
87     __asm __volatile ( \
88     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
89     "psrlw $15, %%" #regd " \n\t" \
90     "packuswb %%" #regd ", %%" #regd " \n\t" ::)
91
92 #define MOVQ_WTWO(regd) \
93     __asm __volatile ( \
94     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
95     "psrlw $15, %%" #regd " \n\t" \
96     "psllw $1, %%" #regd " \n\t"::)
97
98 #endif
99
100 // using regr as temporary and for the output result
101 // first argument is unmodifed and second is trashed
102 // regfe is supposed to contain 0xfefefefefefefefe
103 #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \
104     "movq " #rega ", " #regr "  \n\t"\
105     "pand " #regb ", " #regr "  \n\t"\
106     "pxor " #rega ", " #regb "  \n\t"\
107     "pand " #regfe "," #regb "  \n\t"\
108     "psrlq $1, " #regb "        \n\t"\
109     "paddb " #regb ", " #regr " \n\t"
110
111 #define PAVGB_MMX(rega, regb, regr, regfe) \
112     "movq " #rega ", " #regr "  \n\t"\
113     "por  " #regb ", " #regr "  \n\t"\
114     "pxor " #rega ", " #regb "  \n\t"\
115     "pand " #regfe "," #regb "  \n\t"\
116     "psrlq $1, " #regb "        \n\t"\
117     "psubb " #regb ", " #regr " \n\t"
118
119 // mm6 is supposed to contain 0xfefefefefefefefe
120 #define PAVGBP_MMX_NO_RND(rega, regb, regr,  regc, regd, regp) \
121     "movq " #rega ", " #regr "  \n\t"\
122     "movq " #regc ", " #regp "  \n\t"\
123     "pand " #regb ", " #regr "  \n\t"\
124     "pand " #regd ", " #regp "  \n\t"\
125     "pxor " #rega ", " #regb "  \n\t"\
126     "pxor " #regc ", " #regd "  \n\t"\
127     "pand %%mm6, " #regb "      \n\t"\
128     "pand %%mm6, " #regd "      \n\t"\
129     "psrlq $1, " #regb "        \n\t"\
130     "psrlq $1, " #regd "        \n\t"\
131     "paddb " #regb ", " #regr " \n\t"\
132     "paddb " #regd ", " #regp " \n\t"
133
134 #define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \
135     "movq " #rega ", " #regr "  \n\t"\
136     "movq " #regc ", " #regp "  \n\t"\
137     "por  " #regb ", " #regr "  \n\t"\
138     "por  " #regd ", " #regp "  \n\t"\
139     "pxor " #rega ", " #regb "  \n\t"\
140     "pxor " #regc ", " #regd "  \n\t"\
141     "pand %%mm6, " #regb "      \n\t"\
142     "pand %%mm6, " #regd "      \n\t"\
143     "psrlq $1, " #regd "        \n\t"\
144     "psrlq $1, " #regb "        \n\t"\
145     "psubb " #regb ", " #regr " \n\t"\
146     "psubb " #regd ", " #regp " \n\t"
147
148 /***********************************/
149 /* MMX no rounding */
150 #define DEF(x, y) x ## _no_rnd_ ## y ##_mmx
151 #define SET_RND  MOVQ_WONE
152 #define PAVGBP(a, b, c, d, e, f)        PAVGBP_MMX_NO_RND(a, b, c, d, e, f)
153 #define PAVGB(a, b, c, e)               PAVGB_MMX_NO_RND(a, b, c, e)
154
155 #include "dsputil_mmx_rnd.h"
156
157 #undef DEF
158 #undef SET_RND
159 #undef PAVGBP
160 #undef PAVGB
161 /***********************************/
162 /* MMX rounding */
163
164 #define DEF(x, y) x ## _ ## y ##_mmx
165 #define SET_RND  MOVQ_WTWO
166 #define PAVGBP(a, b, c, d, e, f)        PAVGBP_MMX(a, b, c, d, e, f)
167 #define PAVGB(a, b, c, e)               PAVGB_MMX(a, b, c, e)
168
169 #include "dsputil_mmx_rnd.h"
170
171 #undef DEF
172 #undef SET_RND
173 #undef PAVGBP
174 #undef PAVGB
175
176 /***********************************/
177 /* 3Dnow specific */
178
179 #define DEF(x) x ## _3dnow
180 /* for Athlons PAVGUSB is preferred */
181 #define PAVGB "pavgusb"
182
183 #include "dsputil_mmx_avg.h"
184
185 #undef DEF
186 #undef PAVGB
187
188 /***********************************/
189 /* MMX2 specific */
190
191 #define DEF(x) x ## _mmx2
192
193 /* Introduced only in MMX2 set */
194 #define PAVGB "pavgb"
195
196 #include "dsputil_mmx_avg.h"
197
198 #undef DEF
199 #undef PAVGB
200
201 #define SBUTTERFLY(a,b,t,n,m)\
202     "mov" #m " " #a ", " #t "         \n\t" /* abcd */\
203     "punpckl" #n " " #b ", " #a "     \n\t" /* aebf */\
204     "punpckh" #n " " #b ", " #t "     \n\t" /* cgdh */\
205
206 #define TRANSPOSE4(a,b,c,d,t)\
207     SBUTTERFLY(a,b,t,wd,q) /* a=aebf t=cgdh */\
208     SBUTTERFLY(c,d,b,wd,q) /* c=imjn b=kolp */\
209     SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\
210     SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */
211
212 /***********************************/
213 /* standard MMX */
214
215 #ifdef CONFIG_ENCODERS
216 static void get_pixels_mmx(DCTELEM *block, const uint8_t *pixels, int line_size)
217 {
218     asm volatile(
219         "mov $-128, %%"REG_a"           \n\t"
220         "pxor %%mm7, %%mm7              \n\t"
221         ASMALIGN(4)
222         "1:                             \n\t"
223         "movq (%0), %%mm0               \n\t"
224         "movq (%0, %2), %%mm2           \n\t"
225         "movq %%mm0, %%mm1              \n\t"
226         "movq %%mm2, %%mm3              \n\t"
227         "punpcklbw %%mm7, %%mm0         \n\t"
228         "punpckhbw %%mm7, %%mm1         \n\t"
229         "punpcklbw %%mm7, %%mm2         \n\t"
230         "punpckhbw %%mm7, %%mm3         \n\t"
231         "movq %%mm0, (%1, %%"REG_a")    \n\t"
232         "movq %%mm1, 8(%1, %%"REG_a")   \n\t"
233         "movq %%mm2, 16(%1, %%"REG_a")  \n\t"
234         "movq %%mm3, 24(%1, %%"REG_a")  \n\t"
235         "add %3, %0                     \n\t"
236         "add $32, %%"REG_a"             \n\t"
237         "js 1b                          \n\t"
238         : "+r" (pixels)
239         : "r" (block+64), "r" ((long)line_size), "r" ((long)line_size*2)
240         : "%"REG_a
241     );
242 }
243
244 static inline void diff_pixels_mmx(DCTELEM *block, const uint8_t *s1, const uint8_t *s2, int stride)
245 {
246     asm volatile(
247         "pxor %%mm7, %%mm7              \n\t"
248         "mov $-128, %%"REG_a"           \n\t"
249         ASMALIGN(4)
250         "1:                             \n\t"
251         "movq (%0), %%mm0               \n\t"
252         "movq (%1), %%mm2               \n\t"
253         "movq %%mm0, %%mm1              \n\t"
254         "movq %%mm2, %%mm3              \n\t"
255         "punpcklbw %%mm7, %%mm0         \n\t"
256         "punpckhbw %%mm7, %%mm1         \n\t"
257         "punpcklbw %%mm7, %%mm2         \n\t"
258         "punpckhbw %%mm7, %%mm3         \n\t"
259         "psubw %%mm2, %%mm0             \n\t"
260         "psubw %%mm3, %%mm1             \n\t"
261         "movq %%mm0, (%2, %%"REG_a")    \n\t"
262         "movq %%mm1, 8(%2, %%"REG_a")   \n\t"
263         "add %3, %0                     \n\t"
264         "add %3, %1                     \n\t"
265         "add $16, %%"REG_a"             \n\t"
266         "jnz 1b                         \n\t"
267         : "+r" (s1), "+r" (s2)
268         : "r" (block+64), "r" ((long)stride)
269         : "%"REG_a
270     );
271 }
272 #endif //CONFIG_ENCODERS
273
274 void put_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
275 {
276     const DCTELEM *p;
277     uint8_t *pix;
278
279     /* read the pixels */
280     p = block;
281     pix = pixels;
282     /* unrolled loop */
283         __asm __volatile(
284                 "movq   %3, %%mm0               \n\t"
285                 "movq   8%3, %%mm1              \n\t"
286                 "movq   16%3, %%mm2             \n\t"
287                 "movq   24%3, %%mm3             \n\t"
288                 "movq   32%3, %%mm4             \n\t"
289                 "movq   40%3, %%mm5             \n\t"
290                 "movq   48%3, %%mm6             \n\t"
291                 "movq   56%3, %%mm7             \n\t"
292                 "packuswb %%mm1, %%mm0          \n\t"
293                 "packuswb %%mm3, %%mm2          \n\t"
294                 "packuswb %%mm5, %%mm4          \n\t"
295                 "packuswb %%mm7, %%mm6          \n\t"
296                 "movq   %%mm0, (%0)             \n\t"
297                 "movq   %%mm2, (%0, %1)         \n\t"
298                 "movq   %%mm4, (%0, %1, 2)      \n\t"
299                 "movq   %%mm6, (%0, %2)         \n\t"
300                 ::"r" (pix), "r" ((long)line_size), "r" ((long)line_size*3), "m"(*p)
301                 :"memory");
302         pix += line_size*4;
303         p += 32;
304
305     // if here would be an exact copy of the code above
306     // compiler would generate some very strange code
307     // thus using "r"
308     __asm __volatile(
309             "movq       (%3), %%mm0             \n\t"
310             "movq       8(%3), %%mm1            \n\t"
311             "movq       16(%3), %%mm2           \n\t"
312             "movq       24(%3), %%mm3           \n\t"
313             "movq       32(%3), %%mm4           \n\t"
314             "movq       40(%3), %%mm5           \n\t"
315             "movq       48(%3), %%mm6           \n\t"
316             "movq       56(%3), %%mm7           \n\t"
317             "packuswb %%mm1, %%mm0              \n\t"
318             "packuswb %%mm3, %%mm2              \n\t"
319             "packuswb %%mm5, %%mm4              \n\t"
320             "packuswb %%mm7, %%mm6              \n\t"
321             "movq       %%mm0, (%0)             \n\t"
322             "movq       %%mm2, (%0, %1)         \n\t"
323             "movq       %%mm4, (%0, %1, 2)      \n\t"
324             "movq       %%mm6, (%0, %2)         \n\t"
325             ::"r" (pix), "r" ((long)line_size), "r" ((long)line_size*3), "r"(p)
326             :"memory");
327 }
328
329 static DECLARE_ALIGNED_8(const unsigned char, vector128[8]) =
330   { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
331
332 void put_signed_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
333 {
334     int i;
335
336     movq_m2r(*vector128, mm1);
337     for (i = 0; i < 8; i++) {
338         movq_m2r(*(block), mm0);
339         packsswb_m2r(*(block + 4), mm0);
340         block += 8;
341         paddb_r2r(mm1, mm0);
342         movq_r2m(mm0, *pixels);
343         pixels += line_size;
344     }
345 }
346
347 void add_pixels_clamped_mmx(const DCTELEM *block, uint8_t *pixels, int line_size)
348 {
349     const DCTELEM *p;
350     uint8_t *pix;
351     int i;
352
353     /* read the pixels */
354     p = block;
355     pix = pixels;
356     MOVQ_ZERO(mm7);
357     i = 4;
358     do {
359         __asm __volatile(
360                 "movq   (%2), %%mm0     \n\t"
361                 "movq   8(%2), %%mm1    \n\t"
362                 "movq   16(%2), %%mm2   \n\t"
363                 "movq   24(%2), %%mm3   \n\t"
364                 "movq   %0, %%mm4       \n\t"
365                 "movq   %1, %%mm6       \n\t"
366                 "movq   %%mm4, %%mm5    \n\t"
367                 "punpcklbw %%mm7, %%mm4 \n\t"
368                 "punpckhbw %%mm7, %%mm5 \n\t"
369                 "paddsw %%mm4, %%mm0    \n\t"
370                 "paddsw %%mm5, %%mm1    \n\t"
371                 "movq   %%mm6, %%mm5    \n\t"
372                 "punpcklbw %%mm7, %%mm6 \n\t"
373                 "punpckhbw %%mm7, %%mm5 \n\t"
374                 "paddsw %%mm6, %%mm2    \n\t"
375                 "paddsw %%mm5, %%mm3    \n\t"
376                 "packuswb %%mm1, %%mm0  \n\t"
377                 "packuswb %%mm3, %%mm2  \n\t"
378                 "movq   %%mm0, %0       \n\t"
379                 "movq   %%mm2, %1       \n\t"
380                 :"+m"(*pix), "+m"(*(pix+line_size))
381                 :"r"(p)
382                 :"memory");
383         pix += line_size*2;
384         p += 16;
385     } while (--i);
386 }
387
388 static void put_pixels4_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
389 {
390     __asm __volatile(
391          "lea (%3, %3), %%"REG_a"       \n\t"
392          ASMALIGN(3)
393          "1:                            \n\t"
394          "movd (%1), %%mm0              \n\t"
395          "movd (%1, %3), %%mm1          \n\t"
396          "movd %%mm0, (%2)              \n\t"
397          "movd %%mm1, (%2, %3)          \n\t"
398          "add %%"REG_a", %1             \n\t"
399          "add %%"REG_a", %2             \n\t"
400          "movd (%1), %%mm0              \n\t"
401          "movd (%1, %3), %%mm1          \n\t"
402          "movd %%mm0, (%2)              \n\t"
403          "movd %%mm1, (%2, %3)          \n\t"
404          "add %%"REG_a", %1             \n\t"
405          "add %%"REG_a", %2             \n\t"
406          "subl $4, %0                   \n\t"
407          "jnz 1b                        \n\t"
408          : "+g"(h), "+r" (pixels),  "+r" (block)
409          : "r"((long)line_size)
410          : "%"REG_a, "memory"
411         );
412 }
413
414 static void put_pixels8_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
415 {
416     __asm __volatile(
417          "lea (%3, %3), %%"REG_a"       \n\t"
418          ASMALIGN(3)
419          "1:                            \n\t"
420          "movq (%1), %%mm0              \n\t"
421          "movq (%1, %3), %%mm1          \n\t"
422          "movq %%mm0, (%2)              \n\t"
423          "movq %%mm1, (%2, %3)          \n\t"
424          "add %%"REG_a", %1             \n\t"
425          "add %%"REG_a", %2             \n\t"
426          "movq (%1), %%mm0              \n\t"
427          "movq (%1, %3), %%mm1          \n\t"
428          "movq %%mm0, (%2)              \n\t"
429          "movq %%mm1, (%2, %3)          \n\t"
430          "add %%"REG_a", %1             \n\t"
431          "add %%"REG_a", %2             \n\t"
432          "subl $4, %0                   \n\t"
433          "jnz 1b                        \n\t"
434          : "+g"(h), "+r" (pixels),  "+r" (block)
435          : "r"((long)line_size)
436          : "%"REG_a, "memory"
437         );
438 }
439
440 static void put_pixels16_mmx(uint8_t *block, const uint8_t *pixels, int line_size, int h)
441 {
442     __asm __volatile(
443          "lea (%3, %3), %%"REG_a"       \n\t"
444          ASMALIGN(3)
445          "1:                            \n\t"
446          "movq (%1), %%mm0              \n\t"
447          "movq 8(%1), %%mm4             \n\t"
448          "movq (%1, %3), %%mm1          \n\t"
449          "movq 8(%1, %3), %%mm5         \n\t"
450          "movq %%mm0, (%2)              \n\t"
451          "movq %%mm4, 8(%2)             \n\t"
452          "movq %%mm1, (%2, %3)          \n\t"
453          "movq %%mm5, 8(%2, %3)         \n\t"
454          "add %%"REG_a", %1             \n\t"
455          "add %%"REG_a", %2             \n\t"
456          "movq (%1), %%mm0              \n\t"
457          "movq 8(%1), %%mm4             \n\t"
458          "movq (%1, %3), %%mm1          \n\t"
459          "movq 8(%1, %3), %%mm5         \n\t"
460          "movq %%mm0, (%2)              \n\t"
461          "movq %%mm4, 8(%2)             \n\t"
462          "movq %%mm1, (%2, %3)          \n\t"
463          "movq %%mm5, 8(%2, %3)         \n\t"
464          "add %%"REG_a", %1             \n\t"
465          "add %%"REG_a", %2             \n\t"
466          "subl $4, %0                   \n\t"
467          "jnz 1b                        \n\t"
468          : "+g"(h), "+r" (pixels),  "+r" (block)
469          : "r"((long)line_size)
470          : "%"REG_a, "memory"
471         );
472 }
473
474 static void clear_blocks_mmx(DCTELEM *blocks)
475 {
476     __asm __volatile(
477                 "pxor %%mm7, %%mm7              \n\t"
478                 "mov $-128*6, %%"REG_a"         \n\t"
479                 "1:                             \n\t"
480                 "movq %%mm7, (%0, %%"REG_a")    \n\t"
481                 "movq %%mm7, 8(%0, %%"REG_a")   \n\t"
482                 "movq %%mm7, 16(%0, %%"REG_a")  \n\t"
483                 "movq %%mm7, 24(%0, %%"REG_a")  \n\t"
484                 "add $32, %%"REG_a"             \n\t"
485                 " js 1b                         \n\t"
486                 : : "r" (((uint8_t *)blocks)+128*6)
487                 : "%"REG_a
488         );
489 }
490
491 #ifdef CONFIG_ENCODERS
492 static int pix_sum16_mmx(uint8_t * pix, int line_size){
493     const int h=16;
494     int sum;
495     long index= -line_size*h;
496
497     __asm __volatile(
498                 "pxor %%mm7, %%mm7              \n\t"
499                 "pxor %%mm6, %%mm6              \n\t"
500                 "1:                             \n\t"
501                 "movq (%2, %1), %%mm0           \n\t"
502                 "movq (%2, %1), %%mm1           \n\t"
503                 "movq 8(%2, %1), %%mm2          \n\t"
504                 "movq 8(%2, %1), %%mm3          \n\t"
505                 "punpcklbw %%mm7, %%mm0         \n\t"
506                 "punpckhbw %%mm7, %%mm1         \n\t"
507                 "punpcklbw %%mm7, %%mm2         \n\t"
508                 "punpckhbw %%mm7, %%mm3         \n\t"
509                 "paddw %%mm0, %%mm1             \n\t"
510                 "paddw %%mm2, %%mm3             \n\t"
511                 "paddw %%mm1, %%mm3             \n\t"
512                 "paddw %%mm3, %%mm6             \n\t"
513                 "add %3, %1                     \n\t"
514                 " js 1b                         \n\t"
515                 "movq %%mm6, %%mm5              \n\t"
516                 "psrlq $32, %%mm6               \n\t"
517                 "paddw %%mm5, %%mm6             \n\t"
518                 "movq %%mm6, %%mm5              \n\t"
519                 "psrlq $16, %%mm6               \n\t"
520                 "paddw %%mm5, %%mm6             \n\t"
521                 "movd %%mm6, %0                 \n\t"
522                 "andl $0xFFFF, %0               \n\t"
523                 : "=&r" (sum), "+r" (index)
524                 : "r" (pix - index), "r" ((long)line_size)
525         );
526
527         return sum;
528 }
529 #endif //CONFIG_ENCODERS
530
531 static void add_bytes_mmx(uint8_t *dst, uint8_t *src, int w){
532     long i=0;
533     asm volatile(
534         "1:                             \n\t"
535         "movq  (%1, %0), %%mm0          \n\t"
536         "movq  (%2, %0), %%mm1          \n\t"
537         "paddb %%mm0, %%mm1             \n\t"
538         "movq %%mm1, (%2, %0)           \n\t"
539         "movq 8(%1, %0), %%mm0          \n\t"
540         "movq 8(%2, %0), %%mm1          \n\t"
541         "paddb %%mm0, %%mm1             \n\t"
542         "movq %%mm1, 8(%2, %0)          \n\t"
543         "add $16, %0                    \n\t"
544         "cmp %3, %0                     \n\t"
545         " jb 1b                         \n\t"
546         : "+r" (i)
547         : "r"(src), "r"(dst), "r"((long)w-15)
548     );
549     for(; i<w; i++)
550         dst[i+0] += src[i+0];
551 }
552
553 #define H263_LOOP_FILTER \
554         "pxor %%mm7, %%mm7              \n\t"\
555         "movq  %0, %%mm0                \n\t"\
556         "movq  %0, %%mm1                \n\t"\
557         "movq  %3, %%mm2                \n\t"\
558         "movq  %3, %%mm3                \n\t"\
559         "punpcklbw %%mm7, %%mm0         \n\t"\
560         "punpckhbw %%mm7, %%mm1         \n\t"\
561         "punpcklbw %%mm7, %%mm2         \n\t"\
562         "punpckhbw %%mm7, %%mm3         \n\t"\
563         "psubw %%mm2, %%mm0             \n\t"\
564         "psubw %%mm3, %%mm1             \n\t"\
565         "movq  %1, %%mm2                \n\t"\
566         "movq  %1, %%mm3                \n\t"\
567         "movq  %2, %%mm4                \n\t"\
568         "movq  %2, %%mm5                \n\t"\
569         "punpcklbw %%mm7, %%mm2         \n\t"\
570         "punpckhbw %%mm7, %%mm3         \n\t"\
571         "punpcklbw %%mm7, %%mm4         \n\t"\
572         "punpckhbw %%mm7, %%mm5         \n\t"\
573         "psubw %%mm2, %%mm4             \n\t"\
574         "psubw %%mm3, %%mm5             \n\t"\
575         "psllw $2, %%mm4                \n\t"\
576         "psllw $2, %%mm5                \n\t"\
577         "paddw %%mm0, %%mm4             \n\t"\
578         "paddw %%mm1, %%mm5             \n\t"\
579         "pxor %%mm6, %%mm6              \n\t"\
580         "pcmpgtw %%mm4, %%mm6           \n\t"\
581         "pcmpgtw %%mm5, %%mm7           \n\t"\
582         "pxor %%mm6, %%mm4              \n\t"\
583         "pxor %%mm7, %%mm5              \n\t"\
584         "psubw %%mm6, %%mm4             \n\t"\
585         "psubw %%mm7, %%mm5             \n\t"\
586         "psrlw $3, %%mm4                \n\t"\
587         "psrlw $3, %%mm5                \n\t"\
588         "packuswb %%mm5, %%mm4          \n\t"\
589         "packsswb %%mm7, %%mm6          \n\t"\
590         "pxor %%mm7, %%mm7              \n\t"\
591         "movd %4, %%mm2                 \n\t"\
592         "punpcklbw %%mm2, %%mm2         \n\t"\
593         "punpcklbw %%mm2, %%mm2         \n\t"\
594         "punpcklbw %%mm2, %%mm2         \n\t"\
595         "psubusb %%mm4, %%mm2           \n\t"\
596         "movq %%mm2, %%mm3              \n\t"\
597         "psubusb %%mm4, %%mm3           \n\t"\
598         "psubb %%mm3, %%mm2             \n\t"\
599         "movq %1, %%mm3                 \n\t"\
600         "movq %2, %%mm4                 \n\t"\
601         "pxor %%mm6, %%mm3              \n\t"\
602         "pxor %%mm6, %%mm4              \n\t"\
603         "paddusb %%mm2, %%mm3           \n\t"\
604         "psubusb %%mm2, %%mm4           \n\t"\
605         "pxor %%mm6, %%mm3              \n\t"\
606         "pxor %%mm6, %%mm4              \n\t"\
607         "paddusb %%mm2, %%mm2           \n\t"\
608         "packsswb %%mm1, %%mm0          \n\t"\
609         "pcmpgtb %%mm0, %%mm7           \n\t"\
610         "pxor %%mm7, %%mm0              \n\t"\
611         "psubb %%mm7, %%mm0             \n\t"\
612         "movq %%mm0, %%mm1              \n\t"\
613         "psubusb %%mm2, %%mm0           \n\t"\
614         "psubb %%mm0, %%mm1             \n\t"\
615         "pand %5, %%mm1                 \n\t"\
616         "psrlw $2, %%mm1                \n\t"\
617         "pxor %%mm7, %%mm1              \n\t"\
618         "psubb %%mm7, %%mm1             \n\t"\
619         "movq %0, %%mm5                 \n\t"\
620         "movq %3, %%mm6                 \n\t"\
621         "psubb %%mm1, %%mm5             \n\t"\
622         "paddb %%mm1, %%mm6             \n\t"
623
624 static void h263_v_loop_filter_mmx(uint8_t *src, int stride, int qscale){
625     const int strength= ff_h263_loop_filter_strength[qscale];
626
627     asm volatile(
628
629         H263_LOOP_FILTER
630
631         "movq %%mm3, %1                 \n\t"
632         "movq %%mm4, %2                 \n\t"
633         "movq %%mm5, %0                 \n\t"
634         "movq %%mm6, %3                 \n\t"
635         : "+m" (*(uint64_t*)(src - 2*stride)),
636           "+m" (*(uint64_t*)(src - 1*stride)),
637           "+m" (*(uint64_t*)(src + 0*stride)),
638           "+m" (*(uint64_t*)(src + 1*stride))
639         : "g" (2*strength), "m"(ff_pb_FC)
640     );
641 }
642
643 static inline void transpose4x4(uint8_t *dst, uint8_t *src, int dst_stride, int src_stride){
644     asm volatile( //FIXME could save 1 instruction if done as 8x4 ...
645         "movd  %4, %%mm0                \n\t"
646         "movd  %5, %%mm1                \n\t"
647         "movd  %6, %%mm2                \n\t"
648         "movd  %7, %%mm3                \n\t"
649         "punpcklbw %%mm1, %%mm0         \n\t"
650         "punpcklbw %%mm3, %%mm2         \n\t"
651         "movq %%mm0, %%mm1              \n\t"
652         "punpcklwd %%mm2, %%mm0         \n\t"
653         "punpckhwd %%mm2, %%mm1         \n\t"
654         "movd  %%mm0, %0                \n\t"
655         "punpckhdq %%mm0, %%mm0         \n\t"
656         "movd  %%mm0, %1                \n\t"
657         "movd  %%mm1, %2                \n\t"
658         "punpckhdq %%mm1, %%mm1         \n\t"
659         "movd  %%mm1, %3                \n\t"
660
661         : "=m" (*(uint32_t*)(dst + 0*dst_stride)),
662           "=m" (*(uint32_t*)(dst + 1*dst_stride)),
663           "=m" (*(uint32_t*)(dst + 2*dst_stride)),
664           "=m" (*(uint32_t*)(dst + 3*dst_stride))
665         :  "m" (*(uint32_t*)(src + 0*src_stride)),
666            "m" (*(uint32_t*)(src + 1*src_stride)),
667            "m" (*(uint32_t*)(src + 2*src_stride)),
668            "m" (*(uint32_t*)(src + 3*src_stride))
669     );
670 }
671
672 static void h263_h_loop_filter_mmx(uint8_t *src, int stride, int qscale){
673     const int strength= ff_h263_loop_filter_strength[qscale];
674     uint64_t temp[4] __attribute__ ((aligned(8)));
675     uint8_t *btemp= (uint8_t*)temp;
676
677     src -= 2;
678
679     transpose4x4(btemp  , src           , 8, stride);
680     transpose4x4(btemp+4, src + 4*stride, 8, stride);
681     asm volatile(
682         H263_LOOP_FILTER // 5 3 4 6
683
684         : "+m" (temp[0]),
685           "+m" (temp[1]),
686           "+m" (temp[2]),
687           "+m" (temp[3])
688         : "g" (2*strength), "m"(ff_pb_FC)
689     );
690
691     asm volatile(
692         "movq %%mm5, %%mm1              \n\t"
693         "movq %%mm4, %%mm0              \n\t"
694         "punpcklbw %%mm3, %%mm5         \n\t"
695         "punpcklbw %%mm6, %%mm4         \n\t"
696         "punpckhbw %%mm3, %%mm1         \n\t"
697         "punpckhbw %%mm6, %%mm0         \n\t"
698         "movq %%mm5, %%mm3              \n\t"
699         "movq %%mm1, %%mm6              \n\t"
700         "punpcklwd %%mm4, %%mm5         \n\t"
701         "punpcklwd %%mm0, %%mm1         \n\t"
702         "punpckhwd %%mm4, %%mm3         \n\t"
703         "punpckhwd %%mm0, %%mm6         \n\t"
704         "movd %%mm5, (%0)               \n\t"
705         "punpckhdq %%mm5, %%mm5         \n\t"
706         "movd %%mm5, (%0,%2)            \n\t"
707         "movd %%mm3, (%0,%2,2)          \n\t"
708         "punpckhdq %%mm3, %%mm3         \n\t"
709         "movd %%mm3, (%0,%3)            \n\t"
710         "movd %%mm1, (%1)               \n\t"
711         "punpckhdq %%mm1, %%mm1         \n\t"
712         "movd %%mm1, (%1,%2)            \n\t"
713         "movd %%mm6, (%1,%2,2)          \n\t"
714         "punpckhdq %%mm6, %%mm6         \n\t"
715         "movd %%mm6, (%1,%3)            \n\t"
716         :: "r" (src),
717            "r" (src + 4*stride),
718            "r" ((long)   stride ),
719            "r" ((long)(3*stride))
720     );
721 }
722
723 #ifdef CONFIG_ENCODERS
724 static int pix_norm1_mmx(uint8_t *pix, int line_size) {
725     int tmp;
726   asm volatile (
727       "movl $16,%%ecx\n"
728       "pxor %%mm0,%%mm0\n"
729       "pxor %%mm7,%%mm7\n"
730       "1:\n"
731       "movq (%0),%%mm2\n"       /* mm2 = pix[0-7] */
732       "movq 8(%0),%%mm3\n"      /* mm3 = pix[8-15] */
733
734       "movq %%mm2,%%mm1\n"      /* mm1 = mm2 = pix[0-7] */
735
736       "punpckhbw %%mm0,%%mm1\n" /* mm1 = [pix4-7] */
737       "punpcklbw %%mm0,%%mm2\n" /* mm2 = [pix0-3] */
738
739       "movq %%mm3,%%mm4\n"      /* mm4 = mm3 = pix[8-15] */
740       "punpckhbw %%mm0,%%mm3\n" /* mm3 = [pix12-15] */
741       "punpcklbw %%mm0,%%mm4\n" /* mm4 = [pix8-11] */
742
743       "pmaddwd %%mm1,%%mm1\n"   /* mm1 = (pix0^2+pix1^2,pix2^2+pix3^2) */
744       "pmaddwd %%mm2,%%mm2\n"   /* mm2 = (pix4^2+pix5^2,pix6^2+pix7^2) */
745
746       "pmaddwd %%mm3,%%mm3\n"
747       "pmaddwd %%mm4,%%mm4\n"
748
749       "paddd %%mm1,%%mm2\n"     /* mm2 = (pix0^2+pix1^2+pix4^2+pix5^2,
750                                           pix2^2+pix3^2+pix6^2+pix7^2) */
751       "paddd %%mm3,%%mm4\n"
752       "paddd %%mm2,%%mm7\n"
753
754       "add %2, %0\n"
755       "paddd %%mm4,%%mm7\n"
756       "dec %%ecx\n"
757       "jnz 1b\n"
758
759       "movq %%mm7,%%mm1\n"
760       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
761       "paddd %%mm7,%%mm1\n"
762       "movd %%mm1,%1\n"
763       : "+r" (pix), "=r"(tmp) : "r" ((long)line_size) : "%ecx" );
764     return tmp;
765 }
766
767 static int sse8_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
768     int tmp;
769   asm volatile (
770       "movl %4,%%ecx\n"
771       "shr $1,%%ecx\n"
772       "pxor %%mm0,%%mm0\n"      /* mm0 = 0 */
773       "pxor %%mm7,%%mm7\n"      /* mm7 holds the sum */
774       "1:\n"
775       "movq (%0),%%mm1\n"       /* mm1 = pix1[0][0-7] */
776       "movq (%1),%%mm2\n"       /* mm2 = pix2[0][0-7] */
777       "movq (%0,%3),%%mm3\n"    /* mm3 = pix1[1][0-7] */
778       "movq (%1,%3),%%mm4\n"    /* mm4 = pix2[1][0-7] */
779
780       /* todo: mm1-mm2, mm3-mm4 */
781       /* algo: substract mm1 from mm2 with saturation and vice versa */
782       /*       OR the results to get absolute difference */
783       "movq %%mm1,%%mm5\n"
784       "movq %%mm3,%%mm6\n"
785       "psubusb %%mm2,%%mm1\n"
786       "psubusb %%mm4,%%mm3\n"
787       "psubusb %%mm5,%%mm2\n"
788       "psubusb %%mm6,%%mm4\n"
789
790       "por %%mm1,%%mm2\n"
791       "por %%mm3,%%mm4\n"
792
793       /* now convert to 16-bit vectors so we can square them */
794       "movq %%mm2,%%mm1\n"
795       "movq %%mm4,%%mm3\n"
796
797       "punpckhbw %%mm0,%%mm2\n"
798       "punpckhbw %%mm0,%%mm4\n"
799       "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */
800       "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */
801
802       "pmaddwd %%mm2,%%mm2\n"
803       "pmaddwd %%mm4,%%mm4\n"
804       "pmaddwd %%mm1,%%mm1\n"
805       "pmaddwd %%mm3,%%mm3\n"
806
807       "lea (%0,%3,2), %0\n"     /* pix1 += 2*line_size */
808       "lea (%1,%3,2), %1\n"     /* pix2 += 2*line_size */
809
810       "paddd %%mm2,%%mm1\n"
811       "paddd %%mm4,%%mm3\n"
812       "paddd %%mm1,%%mm7\n"
813       "paddd %%mm3,%%mm7\n"
814
815       "decl %%ecx\n"
816       "jnz 1b\n"
817
818       "movq %%mm7,%%mm1\n"
819       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
820       "paddd %%mm7,%%mm1\n"
821       "movd %%mm1,%2\n"
822       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
823       : "r" ((long)line_size) , "m" (h)
824       : "%ecx");
825     return tmp;
826 }
827
828 static int sse16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
829     int tmp;
830   asm volatile (
831       "movl %4,%%ecx\n"
832       "pxor %%mm0,%%mm0\n"      /* mm0 = 0 */
833       "pxor %%mm7,%%mm7\n"      /* mm7 holds the sum */
834       "1:\n"
835       "movq (%0),%%mm1\n"       /* mm1 = pix1[0-7] */
836       "movq (%1),%%mm2\n"       /* mm2 = pix2[0-7] */
837       "movq 8(%0),%%mm3\n"      /* mm3 = pix1[8-15] */
838       "movq 8(%1),%%mm4\n"      /* mm4 = pix2[8-15] */
839
840       /* todo: mm1-mm2, mm3-mm4 */
841       /* algo: substract mm1 from mm2 with saturation and vice versa */
842       /*       OR the results to get absolute difference */
843       "movq %%mm1,%%mm5\n"
844       "movq %%mm3,%%mm6\n"
845       "psubusb %%mm2,%%mm1\n"
846       "psubusb %%mm4,%%mm3\n"
847       "psubusb %%mm5,%%mm2\n"
848       "psubusb %%mm6,%%mm4\n"
849
850       "por %%mm1,%%mm2\n"
851       "por %%mm3,%%mm4\n"
852
853       /* now convert to 16-bit vectors so we can square them */
854       "movq %%mm2,%%mm1\n"
855       "movq %%mm4,%%mm3\n"
856
857       "punpckhbw %%mm0,%%mm2\n"
858       "punpckhbw %%mm0,%%mm4\n"
859       "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */
860       "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */
861
862       "pmaddwd %%mm2,%%mm2\n"
863       "pmaddwd %%mm4,%%mm4\n"
864       "pmaddwd %%mm1,%%mm1\n"
865       "pmaddwd %%mm3,%%mm3\n"
866
867       "add %3,%0\n"
868       "add %3,%1\n"
869
870       "paddd %%mm2,%%mm1\n"
871       "paddd %%mm4,%%mm3\n"
872       "paddd %%mm1,%%mm7\n"
873       "paddd %%mm3,%%mm7\n"
874
875       "decl %%ecx\n"
876       "jnz 1b\n"
877
878       "movq %%mm7,%%mm1\n"
879       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
880       "paddd %%mm7,%%mm1\n"
881       "movd %%mm1,%2\n"
882       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
883       : "r" ((long)line_size) , "m" (h)
884       : "%ecx");
885     return tmp;
886 }
887
888 static int sse16_sse2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
889     int tmp;
890   asm volatile (
891       "shr $1,%2\n"
892       "pxor %%xmm0,%%xmm0\n"    /* mm0 = 0 */
893       "pxor %%xmm7,%%xmm7\n"    /* mm7 holds the sum */
894       "1:\n"
895       "movdqu (%0),%%xmm1\n"    /* mm1 = pix1[0][0-15] */
896       "movdqu (%1),%%xmm2\n"    /* mm2 = pix2[0][0-15] */
897       "movdqu (%0,%4),%%xmm3\n" /* mm3 = pix1[1][0-15] */
898       "movdqu (%1,%4),%%xmm4\n" /* mm4 = pix2[1][0-15] */
899
900       /* todo: mm1-mm2, mm3-mm4 */
901       /* algo: substract mm1 from mm2 with saturation and vice versa */
902       /*       OR the results to get absolute difference */
903       "movdqa %%xmm1,%%xmm5\n"
904       "movdqa %%xmm3,%%xmm6\n"
905       "psubusb %%xmm2,%%xmm1\n"
906       "psubusb %%xmm4,%%xmm3\n"
907       "psubusb %%xmm5,%%xmm2\n"
908       "psubusb %%xmm6,%%xmm4\n"
909
910       "por %%xmm1,%%xmm2\n"
911       "por %%xmm3,%%xmm4\n"
912
913       /* now convert to 16-bit vectors so we can square them */
914       "movdqa %%xmm2,%%xmm1\n"
915       "movdqa %%xmm4,%%xmm3\n"
916
917       "punpckhbw %%xmm0,%%xmm2\n"
918       "punpckhbw %%xmm0,%%xmm4\n"
919       "punpcklbw %%xmm0,%%xmm1\n"  /* mm1 now spread over (mm1,mm2) */
920       "punpcklbw %%xmm0,%%xmm3\n"  /* mm4 now spread over (mm3,mm4) */
921
922       "pmaddwd %%xmm2,%%xmm2\n"
923       "pmaddwd %%xmm4,%%xmm4\n"
924       "pmaddwd %%xmm1,%%xmm1\n"
925       "pmaddwd %%xmm3,%%xmm3\n"
926
927       "lea (%0,%4,2), %0\n"        /* pix1 += 2*line_size */
928       "lea (%1,%4,2), %1\n"        /* pix2 += 2*line_size */
929
930       "paddd %%xmm2,%%xmm1\n"
931       "paddd %%xmm4,%%xmm3\n"
932       "paddd %%xmm1,%%xmm7\n"
933       "paddd %%xmm3,%%xmm7\n"
934
935       "decl %2\n"
936       "jnz 1b\n"
937
938       "movdqa %%xmm7,%%xmm1\n"
939       "psrldq $8, %%xmm7\n"        /* shift hi qword to lo */
940       "paddd %%xmm1,%%xmm7\n"
941       "movdqa %%xmm7,%%xmm1\n"
942       "psrldq $4, %%xmm7\n"        /* shift hi dword to lo */
943       "paddd %%xmm1,%%xmm7\n"
944       "movd %%xmm7,%3\n"
945       : "+r" (pix1), "+r" (pix2), "+r"(h), "=r"(tmp)
946       : "r" ((long)line_size));
947     return tmp;
948 }
949
950 static int hf_noise8_mmx(uint8_t * pix1, int line_size, int h) {
951     int tmp;
952   asm volatile (
953       "movl %3,%%ecx\n"
954       "pxor %%mm7,%%mm7\n"
955       "pxor %%mm6,%%mm6\n"
956
957       "movq (%0),%%mm0\n"
958       "movq %%mm0, %%mm1\n"
959       "psllq $8, %%mm0\n"
960       "psrlq $8, %%mm1\n"
961       "psrlq $8, %%mm0\n"
962       "movq %%mm0, %%mm2\n"
963       "movq %%mm1, %%mm3\n"
964       "punpcklbw %%mm7,%%mm0\n"
965       "punpcklbw %%mm7,%%mm1\n"
966       "punpckhbw %%mm7,%%mm2\n"
967       "punpckhbw %%mm7,%%mm3\n"
968       "psubw %%mm1, %%mm0\n"
969       "psubw %%mm3, %%mm2\n"
970
971       "add %2,%0\n"
972
973       "movq (%0),%%mm4\n"
974       "movq %%mm4, %%mm1\n"
975       "psllq $8, %%mm4\n"
976       "psrlq $8, %%mm1\n"
977       "psrlq $8, %%mm4\n"
978       "movq %%mm4, %%mm5\n"
979       "movq %%mm1, %%mm3\n"
980       "punpcklbw %%mm7,%%mm4\n"
981       "punpcklbw %%mm7,%%mm1\n"
982       "punpckhbw %%mm7,%%mm5\n"
983       "punpckhbw %%mm7,%%mm3\n"
984       "psubw %%mm1, %%mm4\n"
985       "psubw %%mm3, %%mm5\n"
986       "psubw %%mm4, %%mm0\n"
987       "psubw %%mm5, %%mm2\n"
988       "pxor %%mm3, %%mm3\n"
989       "pxor %%mm1, %%mm1\n"
990       "pcmpgtw %%mm0, %%mm3\n\t"
991       "pcmpgtw %%mm2, %%mm1\n\t"
992       "pxor %%mm3, %%mm0\n"
993       "pxor %%mm1, %%mm2\n"
994       "psubw %%mm3, %%mm0\n"
995       "psubw %%mm1, %%mm2\n"
996       "paddw %%mm0, %%mm2\n"
997       "paddw %%mm2, %%mm6\n"
998
999       "add %2,%0\n"
1000       "1:\n"
1001
1002       "movq (%0),%%mm0\n"
1003       "movq %%mm0, %%mm1\n"
1004       "psllq $8, %%mm0\n"
1005       "psrlq $8, %%mm1\n"
1006       "psrlq $8, %%mm0\n"
1007       "movq %%mm0, %%mm2\n"
1008       "movq %%mm1, %%mm3\n"
1009       "punpcklbw %%mm7,%%mm0\n"
1010       "punpcklbw %%mm7,%%mm1\n"
1011       "punpckhbw %%mm7,%%mm2\n"
1012       "punpckhbw %%mm7,%%mm3\n"
1013       "psubw %%mm1, %%mm0\n"
1014       "psubw %%mm3, %%mm2\n"
1015       "psubw %%mm0, %%mm4\n"
1016       "psubw %%mm2, %%mm5\n"
1017       "pxor %%mm3, %%mm3\n"
1018       "pxor %%mm1, %%mm1\n"
1019       "pcmpgtw %%mm4, %%mm3\n\t"
1020       "pcmpgtw %%mm5, %%mm1\n\t"
1021       "pxor %%mm3, %%mm4\n"
1022       "pxor %%mm1, %%mm5\n"
1023       "psubw %%mm3, %%mm4\n"
1024       "psubw %%mm1, %%mm5\n"
1025       "paddw %%mm4, %%mm5\n"
1026       "paddw %%mm5, %%mm6\n"
1027
1028       "add %2,%0\n"
1029
1030       "movq (%0),%%mm4\n"
1031       "movq %%mm4, %%mm1\n"
1032       "psllq $8, %%mm4\n"
1033       "psrlq $8, %%mm1\n"
1034       "psrlq $8, %%mm4\n"
1035       "movq %%mm4, %%mm5\n"
1036       "movq %%mm1, %%mm3\n"
1037       "punpcklbw %%mm7,%%mm4\n"
1038       "punpcklbw %%mm7,%%mm1\n"
1039       "punpckhbw %%mm7,%%mm5\n"
1040       "punpckhbw %%mm7,%%mm3\n"
1041       "psubw %%mm1, %%mm4\n"
1042       "psubw %%mm3, %%mm5\n"
1043       "psubw %%mm4, %%mm0\n"
1044       "psubw %%mm5, %%mm2\n"
1045       "pxor %%mm3, %%mm3\n"
1046       "pxor %%mm1, %%mm1\n"
1047       "pcmpgtw %%mm0, %%mm3\n\t"
1048       "pcmpgtw %%mm2, %%mm1\n\t"
1049       "pxor %%mm3, %%mm0\n"
1050       "pxor %%mm1, %%mm2\n"
1051       "psubw %%mm3, %%mm0\n"
1052       "psubw %%mm1, %%mm2\n"
1053       "paddw %%mm0, %%mm2\n"
1054       "paddw %%mm2, %%mm6\n"
1055
1056       "add %2,%0\n"
1057       "subl $2, %%ecx\n"
1058       " jnz 1b\n"
1059
1060       "movq %%mm6, %%mm0\n"
1061       "punpcklwd %%mm7,%%mm0\n"
1062       "punpckhwd %%mm7,%%mm6\n"
1063       "paddd %%mm0, %%mm6\n"
1064
1065       "movq %%mm6,%%mm0\n"
1066       "psrlq $32, %%mm6\n"
1067       "paddd %%mm6,%%mm0\n"
1068       "movd %%mm0,%1\n"
1069       : "+r" (pix1), "=r"(tmp)
1070       : "r" ((long)line_size) , "g" (h-2)
1071       : "%ecx");
1072       return tmp;
1073 }
1074
1075 static int hf_noise16_mmx(uint8_t * pix1, int line_size, int h) {
1076     int tmp;
1077     uint8_t * pix= pix1;
1078   asm volatile (
1079       "movl %3,%%ecx\n"
1080       "pxor %%mm7,%%mm7\n"
1081       "pxor %%mm6,%%mm6\n"
1082
1083       "movq (%0),%%mm0\n"
1084       "movq 1(%0),%%mm1\n"
1085       "movq %%mm0, %%mm2\n"
1086       "movq %%mm1, %%mm3\n"
1087       "punpcklbw %%mm7,%%mm0\n"
1088       "punpcklbw %%mm7,%%mm1\n"
1089       "punpckhbw %%mm7,%%mm2\n"
1090       "punpckhbw %%mm7,%%mm3\n"
1091       "psubw %%mm1, %%mm0\n"
1092       "psubw %%mm3, %%mm2\n"
1093
1094       "add %2,%0\n"
1095
1096       "movq (%0),%%mm4\n"
1097       "movq 1(%0),%%mm1\n"
1098       "movq %%mm4, %%mm5\n"
1099       "movq %%mm1, %%mm3\n"
1100       "punpcklbw %%mm7,%%mm4\n"
1101       "punpcklbw %%mm7,%%mm1\n"
1102       "punpckhbw %%mm7,%%mm5\n"
1103       "punpckhbw %%mm7,%%mm3\n"
1104       "psubw %%mm1, %%mm4\n"
1105       "psubw %%mm3, %%mm5\n"
1106       "psubw %%mm4, %%mm0\n"
1107       "psubw %%mm5, %%mm2\n"
1108       "pxor %%mm3, %%mm3\n"
1109       "pxor %%mm1, %%mm1\n"
1110       "pcmpgtw %%mm0, %%mm3\n\t"
1111       "pcmpgtw %%mm2, %%mm1\n\t"
1112       "pxor %%mm3, %%mm0\n"
1113       "pxor %%mm1, %%mm2\n"
1114       "psubw %%mm3, %%mm0\n"
1115       "psubw %%mm1, %%mm2\n"
1116       "paddw %%mm0, %%mm2\n"
1117       "paddw %%mm2, %%mm6\n"
1118
1119       "add %2,%0\n"
1120       "1:\n"
1121
1122       "movq (%0),%%mm0\n"
1123       "movq 1(%0),%%mm1\n"
1124       "movq %%mm0, %%mm2\n"
1125       "movq %%mm1, %%mm3\n"
1126       "punpcklbw %%mm7,%%mm0\n"
1127       "punpcklbw %%mm7,%%mm1\n"
1128       "punpckhbw %%mm7,%%mm2\n"
1129       "punpckhbw %%mm7,%%mm3\n"
1130       "psubw %%mm1, %%mm0\n"
1131       "psubw %%mm3, %%mm2\n"
1132       "psubw %%mm0, %%mm4\n"
1133       "psubw %%mm2, %%mm5\n"
1134       "pxor %%mm3, %%mm3\n"
1135       "pxor %%mm1, %%mm1\n"
1136       "pcmpgtw %%mm4, %%mm3\n\t"
1137       "pcmpgtw %%mm5, %%mm1\n\t"
1138       "pxor %%mm3, %%mm4\n"
1139       "pxor %%mm1, %%mm5\n"
1140       "psubw %%mm3, %%mm4\n"
1141       "psubw %%mm1, %%mm5\n"
1142       "paddw %%mm4, %%mm5\n"
1143       "paddw %%mm5, %%mm6\n"
1144
1145       "add %2,%0\n"
1146
1147       "movq (%0),%%mm4\n"
1148       "movq 1(%0),%%mm1\n"
1149       "movq %%mm4, %%mm5\n"
1150       "movq %%mm1, %%mm3\n"
1151       "punpcklbw %%mm7,%%mm4\n"
1152       "punpcklbw %%mm7,%%mm1\n"
1153       "punpckhbw %%mm7,%%mm5\n"
1154       "punpckhbw %%mm7,%%mm3\n"
1155       "psubw %%mm1, %%mm4\n"
1156       "psubw %%mm3, %%mm5\n"
1157       "psubw %%mm4, %%mm0\n"
1158       "psubw %%mm5, %%mm2\n"
1159       "pxor %%mm3, %%mm3\n"
1160       "pxor %%mm1, %%mm1\n"
1161       "pcmpgtw %%mm0, %%mm3\n\t"
1162       "pcmpgtw %%mm2, %%mm1\n\t"
1163       "pxor %%mm3, %%mm0\n"
1164       "pxor %%mm1, %%mm2\n"
1165       "psubw %%mm3, %%mm0\n"
1166       "psubw %%mm1, %%mm2\n"
1167       "paddw %%mm0, %%mm2\n"
1168       "paddw %%mm2, %%mm6\n"
1169
1170       "add %2,%0\n"
1171       "subl $2, %%ecx\n"
1172       " jnz 1b\n"
1173
1174       "movq %%mm6, %%mm0\n"
1175       "punpcklwd %%mm7,%%mm0\n"
1176       "punpckhwd %%mm7,%%mm6\n"
1177       "paddd %%mm0, %%mm6\n"
1178
1179       "movq %%mm6,%%mm0\n"
1180       "psrlq $32, %%mm6\n"
1181       "paddd %%mm6,%%mm0\n"
1182       "movd %%mm0,%1\n"
1183       : "+r" (pix1), "=r"(tmp)
1184       : "r" ((long)line_size) , "g" (h-2)
1185       : "%ecx");
1186       return tmp + hf_noise8_mmx(pix+8, line_size, h);
1187 }
1188
1189 static int nsse16_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
1190     MpegEncContext *c = p;
1191     int score1, score2;
1192
1193     if(c) score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h);
1194     else  score1 = sse16_mmx(c, pix1, pix2, line_size, h);
1195     score2= hf_noise16_mmx(pix1, line_size, h) - hf_noise16_mmx(pix2, line_size, h);
1196
1197     if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight;
1198     else  return score1 + FFABS(score2)*8;
1199 }
1200
1201 static int nsse8_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
1202     MpegEncContext *c = p;
1203     int score1= sse8_mmx(c, pix1, pix2, line_size, h);
1204     int score2= hf_noise8_mmx(pix1, line_size, h) - hf_noise8_mmx(pix2, line_size, h);
1205
1206     if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight;
1207     else  return score1 + FFABS(score2)*8;
1208 }
1209
1210 static int vsad_intra16_mmx(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
1211     int tmp;
1212
1213     assert( (((int)pix) & 7) == 0);
1214     assert((line_size &7) ==0);
1215
1216 #define SUM(in0, in1, out0, out1) \
1217       "movq (%0), %%mm2\n"\
1218       "movq 8(%0), %%mm3\n"\
1219       "add %2,%0\n"\
1220       "movq %%mm2, " #out0 "\n"\
1221       "movq %%mm3, " #out1 "\n"\
1222       "psubusb " #in0 ", %%mm2\n"\
1223       "psubusb " #in1 ", %%mm3\n"\
1224       "psubusb " #out0 ", " #in0 "\n"\
1225       "psubusb " #out1 ", " #in1 "\n"\
1226       "por %%mm2, " #in0 "\n"\
1227       "por %%mm3, " #in1 "\n"\
1228       "movq " #in0 ", %%mm2\n"\
1229       "movq " #in1 ", %%mm3\n"\
1230       "punpcklbw %%mm7, " #in0 "\n"\
1231       "punpcklbw %%mm7, " #in1 "\n"\
1232       "punpckhbw %%mm7, %%mm2\n"\
1233       "punpckhbw %%mm7, %%mm3\n"\
1234       "paddw " #in1 ", " #in0 "\n"\
1235       "paddw %%mm3, %%mm2\n"\
1236       "paddw %%mm2, " #in0 "\n"\
1237       "paddw " #in0 ", %%mm6\n"
1238
1239
1240   asm volatile (
1241       "movl %3,%%ecx\n"
1242       "pxor %%mm6,%%mm6\n"
1243       "pxor %%mm7,%%mm7\n"
1244       "movq (%0),%%mm0\n"
1245       "movq 8(%0),%%mm1\n"
1246       "add %2,%0\n"
1247       "subl $2, %%ecx\n"
1248       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1249       "1:\n"
1250
1251       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
1252
1253       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1254
1255       "subl $2, %%ecx\n"
1256       "jnz 1b\n"
1257
1258       "movq %%mm6,%%mm0\n"
1259       "psrlq $32, %%mm6\n"
1260       "paddw %%mm6,%%mm0\n"
1261       "movq %%mm0,%%mm6\n"
1262       "psrlq $16, %%mm0\n"
1263       "paddw %%mm6,%%mm0\n"
1264       "movd %%mm0,%1\n"
1265       : "+r" (pix), "=r"(tmp)
1266       : "r" ((long)line_size) , "m" (h)
1267       : "%ecx");
1268     return tmp & 0xFFFF;
1269 }
1270 #undef SUM
1271
1272 static int vsad_intra16_mmx2(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
1273     int tmp;
1274
1275     assert( (((int)pix) & 7) == 0);
1276     assert((line_size &7) ==0);
1277
1278 #define SUM(in0, in1, out0, out1) \
1279       "movq (%0), " #out0 "\n"\
1280       "movq 8(%0), " #out1 "\n"\
1281       "add %2,%0\n"\
1282       "psadbw " #out0 ", " #in0 "\n"\
1283       "psadbw " #out1 ", " #in1 "\n"\
1284       "paddw " #in1 ", " #in0 "\n"\
1285       "paddw " #in0 ", %%mm6\n"
1286
1287   asm volatile (
1288       "movl %3,%%ecx\n"
1289       "pxor %%mm6,%%mm6\n"
1290       "pxor %%mm7,%%mm7\n"
1291       "movq (%0),%%mm0\n"
1292       "movq 8(%0),%%mm1\n"
1293       "add %2,%0\n"
1294       "subl $2, %%ecx\n"
1295       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1296       "1:\n"
1297
1298       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
1299
1300       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1301
1302       "subl $2, %%ecx\n"
1303       "jnz 1b\n"
1304
1305       "movd %%mm6,%1\n"
1306       : "+r" (pix), "=r"(tmp)
1307       : "r" ((long)line_size) , "m" (h)
1308       : "%ecx");
1309     return tmp;
1310 }
1311 #undef SUM
1312
1313 static int vsad16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
1314     int tmp;
1315
1316     assert( (((int)pix1) & 7) == 0);
1317     assert( (((int)pix2) & 7) == 0);
1318     assert((line_size &7) ==0);
1319
1320 #define SUM(in0, in1, out0, out1) \
1321       "movq (%0),%%mm2\n"\
1322       "movq (%1)," #out0 "\n"\
1323       "movq 8(%0),%%mm3\n"\
1324       "movq 8(%1)," #out1 "\n"\
1325       "add %3,%0\n"\
1326       "add %3,%1\n"\
1327       "psubb " #out0 ", %%mm2\n"\
1328       "psubb " #out1 ", %%mm3\n"\
1329       "pxor %%mm7, %%mm2\n"\
1330       "pxor %%mm7, %%mm3\n"\
1331       "movq %%mm2, " #out0 "\n"\
1332       "movq %%mm3, " #out1 "\n"\
1333       "psubusb " #in0 ", %%mm2\n"\
1334       "psubusb " #in1 ", %%mm3\n"\
1335       "psubusb " #out0 ", " #in0 "\n"\
1336       "psubusb " #out1 ", " #in1 "\n"\
1337       "por %%mm2, " #in0 "\n"\
1338       "por %%mm3, " #in1 "\n"\
1339       "movq " #in0 ", %%mm2\n"\
1340       "movq " #in1 ", %%mm3\n"\
1341       "punpcklbw %%mm7, " #in0 "\n"\
1342       "punpcklbw %%mm7, " #in1 "\n"\
1343       "punpckhbw %%mm7, %%mm2\n"\
1344       "punpckhbw %%mm7, %%mm3\n"\
1345       "paddw " #in1 ", " #in0 "\n"\
1346       "paddw %%mm3, %%mm2\n"\
1347       "paddw %%mm2, " #in0 "\n"\
1348       "paddw " #in0 ", %%mm6\n"
1349
1350
1351   asm volatile (
1352       "movl %4,%%ecx\n"
1353       "pxor %%mm6,%%mm6\n"
1354       "pcmpeqw %%mm7,%%mm7\n"
1355       "psllw $15, %%mm7\n"
1356       "packsswb %%mm7, %%mm7\n"
1357       "movq (%0),%%mm0\n"
1358       "movq (%1),%%mm2\n"
1359       "movq 8(%0),%%mm1\n"
1360       "movq 8(%1),%%mm3\n"
1361       "add %3,%0\n"
1362       "add %3,%1\n"
1363       "subl $2, %%ecx\n"
1364       "psubb %%mm2, %%mm0\n"
1365       "psubb %%mm3, %%mm1\n"
1366       "pxor %%mm7, %%mm0\n"
1367       "pxor %%mm7, %%mm1\n"
1368       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1369       "1:\n"
1370
1371       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
1372
1373       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1374
1375       "subl $2, %%ecx\n"
1376       "jnz 1b\n"
1377
1378       "movq %%mm6,%%mm0\n"
1379       "psrlq $32, %%mm6\n"
1380       "paddw %%mm6,%%mm0\n"
1381       "movq %%mm0,%%mm6\n"
1382       "psrlq $16, %%mm0\n"
1383       "paddw %%mm6,%%mm0\n"
1384       "movd %%mm0,%2\n"
1385       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
1386       : "r" ((long)line_size) , "m" (h)
1387       : "%ecx");
1388     return tmp & 0x7FFF;
1389 }
1390 #undef SUM
1391
1392 static int vsad16_mmx2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
1393     int tmp;
1394
1395     assert( (((int)pix1) & 7) == 0);
1396     assert( (((int)pix2) & 7) == 0);
1397     assert((line_size &7) ==0);
1398
1399 #define SUM(in0, in1, out0, out1) \
1400       "movq (%0)," #out0 "\n"\
1401       "movq (%1),%%mm2\n"\
1402       "movq 8(%0)," #out1 "\n"\
1403       "movq 8(%1),%%mm3\n"\
1404       "add %3,%0\n"\
1405       "add %3,%1\n"\
1406       "psubb %%mm2, " #out0 "\n"\
1407       "psubb %%mm3, " #out1 "\n"\
1408       "pxor %%mm7, " #out0 "\n"\
1409       "pxor %%mm7, " #out1 "\n"\
1410       "psadbw " #out0 ", " #in0 "\n"\
1411       "psadbw " #out1 ", " #in1 "\n"\
1412       "paddw " #in1 ", " #in0 "\n"\
1413       "paddw " #in0 ", %%mm6\n"
1414
1415   asm volatile (
1416       "movl %4,%%ecx\n"
1417       "pxor %%mm6,%%mm6\n"
1418       "pcmpeqw %%mm7,%%mm7\n"
1419       "psllw $15, %%mm7\n"
1420       "packsswb %%mm7, %%mm7\n"
1421       "movq (%0),%%mm0\n"
1422       "movq (%1),%%mm2\n"
1423       "movq 8(%0),%%mm1\n"
1424       "movq 8(%1),%%mm3\n"
1425       "add %3,%0\n"
1426       "add %3,%1\n"
1427       "subl $2, %%ecx\n"
1428       "psubb %%mm2, %%mm0\n"
1429       "psubb %%mm3, %%mm1\n"
1430       "pxor %%mm7, %%mm0\n"
1431       "pxor %%mm7, %%mm1\n"
1432       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1433       "1:\n"
1434
1435       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
1436
1437       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
1438
1439       "subl $2, %%ecx\n"
1440       "jnz 1b\n"
1441
1442       "movd %%mm6,%2\n"
1443       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
1444       : "r" ((long)line_size) , "m" (h)
1445       : "%ecx");
1446     return tmp;
1447 }
1448 #undef SUM
1449
1450 static void diff_bytes_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){
1451     long i=0;
1452     asm volatile(
1453         "1:                             \n\t"
1454         "movq  (%2, %0), %%mm0          \n\t"
1455         "movq  (%1, %0), %%mm1          \n\t"
1456         "psubb %%mm0, %%mm1             \n\t"
1457         "movq %%mm1, (%3, %0)           \n\t"
1458         "movq 8(%2, %0), %%mm0          \n\t"
1459         "movq 8(%1, %0), %%mm1          \n\t"
1460         "psubb %%mm0, %%mm1             \n\t"
1461         "movq %%mm1, 8(%3, %0)          \n\t"
1462         "add $16, %0                    \n\t"
1463         "cmp %4, %0                     \n\t"
1464         " jb 1b                         \n\t"
1465         : "+r" (i)
1466         : "r"(src1), "r"(src2), "r"(dst), "r"((long)w-15)
1467     );
1468     for(; i<w; i++)
1469         dst[i+0] = src1[i+0]-src2[i+0];
1470 }
1471
1472 static void sub_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){
1473     long i=0;
1474     uint8_t l, lt;
1475
1476     asm volatile(
1477         "1:                             \n\t"
1478         "movq  -1(%1, %0), %%mm0        \n\t" // LT
1479         "movq  (%1, %0), %%mm1          \n\t" // T
1480         "movq  -1(%2, %0), %%mm2        \n\t" // L
1481         "movq  (%2, %0), %%mm3          \n\t" // X
1482         "movq %%mm2, %%mm4              \n\t" // L
1483         "psubb %%mm0, %%mm2             \n\t"
1484         "paddb %%mm1, %%mm2             \n\t" // L + T - LT
1485         "movq %%mm4, %%mm5              \n\t" // L
1486         "pmaxub %%mm1, %%mm4            \n\t" // max(T, L)
1487         "pminub %%mm5, %%mm1            \n\t" // min(T, L)
1488         "pminub %%mm2, %%mm4            \n\t"
1489         "pmaxub %%mm1, %%mm4            \n\t"
1490         "psubb %%mm4, %%mm3             \n\t" // dst - pred
1491         "movq %%mm3, (%3, %0)           \n\t"
1492         "add $8, %0                     \n\t"
1493         "cmp %4, %0                     \n\t"
1494         " jb 1b                         \n\t"
1495         : "+r" (i)
1496         : "r"(src1), "r"(src2), "r"(dst), "r"((long)w)
1497     );
1498
1499     l= *left;
1500     lt= *left_top;
1501
1502     dst[0]= src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt)&0xFF);
1503
1504     *left_top= src1[w-1];
1505     *left    = src2[w-1];
1506 }
1507
1508 #define DIFF_PIXELS_1(m,a,t,p1,p2)\
1509     "mov"#m" "#p1", "#a"              \n\t"\
1510     "mov"#m" "#p2", "#t"              \n\t"\
1511     "punpcklbw "#a", "#t"             \n\t"\
1512     "punpcklbw "#a", "#a"             \n\t"\
1513     "psubw     "#t", "#a"             \n\t"\
1514
1515 #define DIFF_PIXELS_8(m0,m1,mm,p1,p2,stride,temp) {\
1516     uint8_t *p1b=p1, *p2b=p2;\
1517     asm volatile(\
1518         DIFF_PIXELS_1(m0, mm##0, mm##7, (%1), (%2))\
1519         DIFF_PIXELS_1(m0, mm##1, mm##7, (%1,%3), (%2,%3))\
1520         DIFF_PIXELS_1(m0, mm##2, mm##7, (%1,%3,2), (%2,%3,2))\
1521         "add %4, %1                   \n\t"\
1522         "add %4, %2                   \n\t"\
1523         DIFF_PIXELS_1(m0, mm##3, mm##7, (%1), (%2))\
1524         DIFF_PIXELS_1(m0, mm##4, mm##7, (%1,%3), (%2,%3))\
1525         DIFF_PIXELS_1(m0, mm##5, mm##7, (%1,%3,2), (%2,%3,2))\
1526         DIFF_PIXELS_1(m0, mm##6, mm##7, (%1,%4), (%2,%4))\
1527         "mov"#m1" "#mm"0, %0          \n\t"\
1528         DIFF_PIXELS_1(m0, mm##7, mm##0, (%1,%3,4), (%2,%3,4))\
1529         "mov"#m1" %0, "#mm"0          \n\t"\
1530         : "=m"(temp), "+r"(p1b), "+r"(p2b)\
1531         : "r"((long)stride), "r"((long)stride*3)\
1532     );\
1533 }
1534
1535 #define DIFF_PIXELS_4x8(p1,p2,stride,temp) DIFF_PIXELS_8(d, q,   %%mm,  p1, p2, stride, temp)
1536 #define DIFF_PIXELS_8x8(p1,p2,stride,temp) DIFF_PIXELS_8(q, dqa, %%xmm, p1, p2, stride, temp)
1537
1538 #ifdef ARCH_X86_64
1539 // permutes 01234567 -> 05736421
1540 #define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
1541     SBUTTERFLY(a,b,%%xmm8,wd,dqa)\
1542     SBUTTERFLY(c,d,b,wd,dqa)\
1543     SBUTTERFLY(e,f,d,wd,dqa)\
1544     SBUTTERFLY(g,h,f,wd,dqa)\
1545     SBUTTERFLY(a,c,h,dq,dqa)\
1546     SBUTTERFLY(%%xmm8,b,c,dq,dqa)\
1547     SBUTTERFLY(e,g,b,dq,dqa)\
1548     SBUTTERFLY(d,f,g,dq,dqa)\
1549     SBUTTERFLY(a,e,f,qdq,dqa)\
1550     SBUTTERFLY(%%xmm8,d,e,qdq,dqa)\
1551     SBUTTERFLY(h,b,d,qdq,dqa)\
1552     SBUTTERFLY(c,g,b,qdq,dqa)\
1553     "movdqa %%xmm8, "#g"              \n\t"
1554 #else
1555 #define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
1556     "movdqa "#h", "#t"                \n\t"\
1557     SBUTTERFLY(a,b,h,wd,dqa)\
1558     "movdqa "#h", 16"#t"              \n\t"\
1559     "movdqa "#t", "#h"                \n\t"\
1560     SBUTTERFLY(c,d,b,wd,dqa)\
1561     SBUTTERFLY(e,f,d,wd,dqa)\
1562     SBUTTERFLY(g,h,f,wd,dqa)\
1563     SBUTTERFLY(a,c,h,dq,dqa)\
1564     "movdqa "#h", "#t"                \n\t"\
1565     "movdqa 16"#t", "#h"              \n\t"\
1566     SBUTTERFLY(h,b,c,dq,dqa)\
1567     SBUTTERFLY(e,g,b,dq,dqa)\
1568     SBUTTERFLY(d,f,g,dq,dqa)\
1569     SBUTTERFLY(a,e,f,qdq,dqa)\
1570     SBUTTERFLY(h,d,e,qdq,dqa)\
1571     "movdqa "#h", 16"#t"              \n\t"\
1572     "movdqa "#t", "#h"                \n\t"\
1573     SBUTTERFLY(h,b,d,qdq,dqa)\
1574     SBUTTERFLY(c,g,b,qdq,dqa)\
1575     "movdqa 16"#t", "#g"              \n\t"
1576 #endif
1577
1578 #define LBUTTERFLY2(a1,b1,a2,b2)\
1579     "paddw " #b1 ", " #a1 "           \n\t"\
1580     "paddw " #b2 ", " #a2 "           \n\t"\
1581     "paddw " #b1 ", " #b1 "           \n\t"\
1582     "paddw " #b2 ", " #b2 "           \n\t"\
1583     "psubw " #a1 ", " #b1 "           \n\t"\
1584     "psubw " #a2 ", " #b2 "           \n\t"
1585
1586 #define HADAMARD8(m0, m1, m2, m3, m4, m5, m6, m7)\
1587         LBUTTERFLY2(m0, m1, m2, m3)\
1588         LBUTTERFLY2(m4, m5, m6, m7)\
1589         LBUTTERFLY2(m0, m2, m1, m3)\
1590         LBUTTERFLY2(m4, m6, m5, m7)\
1591         LBUTTERFLY2(m0, m4, m1, m5)\
1592         LBUTTERFLY2(m2, m6, m3, m7)\
1593
1594 #define HADAMARD48 HADAMARD8(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm6, %%mm7)
1595
1596 #define MMABS_MMX(a,z)\
1597     "pxor " #z ", " #z "              \n\t"\
1598     "pcmpgtw " #a ", " #z "           \n\t"\
1599     "pxor " #z ", " #a "              \n\t"\
1600     "psubw " #z ", " #a "             \n\t"
1601
1602 #define MMABS_MMX2(a,z)\
1603     "pxor " #z ", " #z "              \n\t"\
1604     "psubw " #a ", " #z "             \n\t"\
1605     "pmaxsw " #z ", " #a "            \n\t"
1606
1607 #define MMABS_SSSE3(a,z)\
1608     "pabsw " #a ", " #a "             \n\t"
1609
1610 #define MMABS_SUM(a,z, sum)\
1611     MMABS(a,z)\
1612     "paddusw " #a ", " #sum "         \n\t"
1613
1614 #define MMABS_SUM_8x8_NOSPILL\
1615     MMABS(%%xmm0, %%xmm8)\
1616     MMABS(%%xmm1, %%xmm9)\
1617     MMABS_SUM(%%xmm2, %%xmm8, %%xmm0)\
1618     MMABS_SUM(%%xmm3, %%xmm9, %%xmm1)\
1619     MMABS_SUM(%%xmm4, %%xmm8, %%xmm0)\
1620     MMABS_SUM(%%xmm5, %%xmm9, %%xmm1)\
1621     MMABS_SUM(%%xmm6, %%xmm8, %%xmm0)\
1622     MMABS_SUM(%%xmm7, %%xmm9, %%xmm1)\
1623     "paddusw %%xmm1, %%xmm0           \n\t"
1624
1625 #ifdef ARCH_X86_64
1626 #define MMABS_SUM_8x8_SSE2 MMABS_SUM_8x8_NOSPILL
1627 #else
1628 #define MMABS_SUM_8x8_SSE2\
1629     "movdqa %%xmm7, (%1)              \n\t"\
1630     MMABS(%%xmm0, %%xmm7)\
1631     MMABS(%%xmm1, %%xmm7)\
1632     MMABS_SUM(%%xmm2, %%xmm7, %%xmm0)\
1633     MMABS_SUM(%%xmm3, %%xmm7, %%xmm1)\
1634     MMABS_SUM(%%xmm4, %%xmm7, %%xmm0)\
1635     MMABS_SUM(%%xmm5, %%xmm7, %%xmm1)\
1636     MMABS_SUM(%%xmm6, %%xmm7, %%xmm0)\
1637     "movdqa (%1), %%xmm2              \n\t"\
1638     MMABS_SUM(%%xmm2, %%xmm7, %%xmm1)\
1639     "paddusw %%xmm1, %%xmm0           \n\t"
1640 #endif
1641
1642 #define LOAD4(o, a, b, c, d)\
1643     "movq "#o"(%1),    "#a"           \n\t"\
1644     "movq "#o"+8(%1),  "#b"           \n\t"\
1645     "movq "#o"+16(%1), "#c"           \n\t"\
1646     "movq "#o"+24(%1), "#d"           \n\t"\
1647
1648 #define STORE4(o, a, b, c, d)\
1649     "movq "#a", "#o"(%1)              \n\t"\
1650     "movq "#b", "#o"+8(%1)            \n\t"\
1651     "movq "#c", "#o"+16(%1)           \n\t"\
1652     "movq "#d", "#o"+24(%1)           \n\t"\
1653
1654 /* FIXME: HSUM_* saturates at 64k, while an 8x8 hadamard or dct block can get up to
1655  * about 100k on extreme inputs. But that's very unlikely to occur in natural video,
1656  * and it's even more unlikely to not have any alternative mvs/modes with lower cost. */
1657 #define HSUM_MMX(a, t, dst)\
1658     "movq "#a", "#t"                  \n\t"\
1659     "psrlq $32, "#a"                  \n\t"\
1660     "paddusw "#t", "#a"               \n\t"\
1661     "movq "#a", "#t"                  \n\t"\
1662     "psrlq $16, "#a"                  \n\t"\
1663     "paddusw "#t", "#a"               \n\t"\
1664     "movd "#a", "#dst"                \n\t"\
1665
1666 #define HSUM_MMX2(a, t, dst)\
1667     "pshufw $0x0E, "#a", "#t"         \n\t"\
1668     "paddusw "#t", "#a"               \n\t"\
1669     "pshufw $0x01, "#a", "#t"         \n\t"\
1670     "paddusw "#t", "#a"               \n\t"\
1671     "movd "#a", "#dst"                \n\t"\
1672
1673 #define HSUM_SSE2(a, t, dst)\
1674     "movhlps "#a", "#t"               \n\t"\
1675     "paddusw "#t", "#a"               \n\t"\
1676     "pshuflw $0x0E, "#a", "#t"        \n\t"\
1677     "paddusw "#t", "#a"               \n\t"\
1678     "pshuflw $0x01, "#a", "#t"        \n\t"\
1679     "paddusw "#t", "#a"               \n\t"\
1680     "movd "#a", "#dst"                \n\t"\
1681
1682 #define HADAMARD8_DIFF_MMX(cpu) \
1683 static int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){\
1684     DECLARE_ALIGNED_8(uint64_t, temp[13]);\
1685     int sum;\
1686 \
1687     assert(h==8);\
1688 \
1689     DIFF_PIXELS_4x8(src1, src2, stride, temp[0]);\
1690 \
1691     asm volatile(\
1692         HADAMARD48\
1693 \
1694         "movq %%mm7, 96(%1)             \n\t"\
1695 \
1696         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)\
1697         STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)\
1698 \
1699         "movq 96(%1), %%mm7             \n\t"\
1700         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)\
1701         STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)\
1702 \
1703         : "=r" (sum)\
1704         : "r"(temp)\
1705     );\
1706 \
1707     DIFF_PIXELS_4x8(src1+4, src2+4, stride, temp[4]);\
1708 \
1709     asm volatile(\
1710         HADAMARD48\
1711 \
1712         "movq %%mm7, 96(%1)             \n\t"\
1713 \
1714         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)\
1715         STORE4(32, %%mm0, %%mm3, %%mm7, %%mm2)\
1716 \
1717         "movq 96(%1), %%mm7             \n\t"\
1718         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)\
1719         "movq %%mm7, %%mm5              \n\t"/*FIXME remove*/\
1720         "movq %%mm6, %%mm7              \n\t"\
1721         "movq %%mm0, %%mm6              \n\t"\
1722 \
1723         LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)\
1724 \
1725         HADAMARD48\
1726         "movq %%mm7, 64(%1)             \n\t"\
1727         MMABS(%%mm0, %%mm7)\
1728         MMABS(%%mm1, %%mm7)\
1729         MMABS_SUM(%%mm2, %%mm7, %%mm0)\
1730         MMABS_SUM(%%mm3, %%mm7, %%mm1)\
1731         MMABS_SUM(%%mm4, %%mm7, %%mm0)\
1732         MMABS_SUM(%%mm5, %%mm7, %%mm1)\
1733         MMABS_SUM(%%mm6, %%mm7, %%mm0)\
1734         "movq 64(%1), %%mm2             \n\t"\
1735         MMABS_SUM(%%mm2, %%mm7, %%mm1)\
1736         "paddusw %%mm1, %%mm0           \n\t"\
1737         "movq %%mm0, 64(%1)             \n\t"\
1738 \
1739         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)\
1740         LOAD4(32, %%mm4, %%mm5, %%mm6, %%mm7)\
1741 \
1742         HADAMARD48\
1743         "movq %%mm7, (%1)               \n\t"\
1744         MMABS(%%mm0, %%mm7)\
1745         MMABS(%%mm1, %%mm7)\
1746         MMABS_SUM(%%mm2, %%mm7, %%mm0)\
1747         MMABS_SUM(%%mm3, %%mm7, %%mm1)\
1748         MMABS_SUM(%%mm4, %%mm7, %%mm0)\
1749         MMABS_SUM(%%mm5, %%mm7, %%mm1)\
1750         MMABS_SUM(%%mm6, %%mm7, %%mm0)\
1751         "movq (%1), %%mm2               \n\t"\
1752         MMABS_SUM(%%mm2, %%mm7, %%mm1)\
1753         "paddusw 64(%1), %%mm0          \n\t"\
1754         "paddusw %%mm1, %%mm0           \n\t"\
1755 \
1756         HSUM(%%mm0, %%mm1, %0)\
1757 \
1758         : "=r" (sum)\
1759         : "r"(temp)\
1760     );\
1761     return sum&0xFFFF;\
1762 }\
1763 WARPER8_16_SQ(hadamard8_diff_##cpu, hadamard8_diff16_##cpu)
1764
1765 #define HADAMARD8_DIFF_SSE2(cpu) \
1766 static int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){\
1767     DECLARE_ALIGNED_16(uint64_t, temp[4]);\
1768     int sum;\
1769 \
1770     assert(h==8);\
1771 \
1772     DIFF_PIXELS_8x8(src1, src2, stride, temp[0]);\
1773 \
1774     asm volatile(\
1775         HADAMARD8(%%xmm0, %%xmm1, %%xmm2, %%xmm3, %%xmm4, %%xmm5, %%xmm6, %%xmm7)\
1776         TRANSPOSE8(%%xmm0, %%xmm1, %%xmm2, %%xmm3, %%xmm4, %%xmm5, %%xmm6, %%xmm7, (%1))\
1777         HADAMARD8(%%xmm0, %%xmm5, %%xmm7, %%xmm3, %%xmm6, %%xmm4, %%xmm2, %%xmm1)\
1778         MMABS_SUM_8x8\
1779         HSUM_SSE2(%%xmm0, %%xmm1, %0)\
1780         : "=r" (sum)\
1781         : "r"(temp)\
1782     );\
1783     return sum&0xFFFF;\
1784 }\
1785 WARPER8_16_SQ(hadamard8_diff_##cpu, hadamard8_diff16_##cpu)
1786
1787 #define MMABS(a,z)         MMABS_MMX(a,z)
1788 #define HSUM(a,t,dst)      HSUM_MMX(a,t,dst)
1789 HADAMARD8_DIFF_MMX(mmx)
1790 #undef MMABS
1791 #undef HSUM
1792
1793 #define MMABS(a,z)         MMABS_MMX2(a,z)
1794 #define MMABS_SUM_8x8      MMABS_SUM_8x8_SSE2
1795 #define HSUM(a,t,dst)      HSUM_MMX2(a,t,dst)
1796 HADAMARD8_DIFF_MMX(mmx2)
1797 HADAMARD8_DIFF_SSE2(sse2)
1798 #undef MMABS
1799 #undef MMABS_SUM_8x8
1800 #undef HSUM
1801
1802 #ifdef HAVE_SSSE3
1803 #define MMABS(a,z)         MMABS_SSSE3(a,z)
1804 #define MMABS_SUM_8x8      MMABS_SUM_8x8_NOSPILL
1805 HADAMARD8_DIFF_SSE2(ssse3)
1806 #undef MMABS
1807 #undef MMABS_SUM_8x8
1808 #endif
1809
1810 #define DCT_SAD4(m,mm,o)\
1811     "mov"#m" "#o"+ 0(%1), "#mm"2      \n\t"\
1812     "mov"#m" "#o"+16(%1), "#mm"3      \n\t"\
1813     "mov"#m" "#o"+32(%1), "#mm"4      \n\t"\
1814     "mov"#m" "#o"+48(%1), "#mm"5      \n\t"\
1815     MMABS_SUM(mm##2, mm##6, mm##0)\
1816     MMABS_SUM(mm##3, mm##7, mm##1)\
1817     MMABS_SUM(mm##4, mm##6, mm##0)\
1818     MMABS_SUM(mm##5, mm##7, mm##1)\
1819
1820 #define DCT_SAD_MMX\
1821     "pxor %%mm0, %%mm0                \n\t"\
1822     "pxor %%mm1, %%mm1                \n\t"\
1823     DCT_SAD4(q, %%mm, 0)\
1824     DCT_SAD4(q, %%mm, 8)\
1825     DCT_SAD4(q, %%mm, 64)\
1826     DCT_SAD4(q, %%mm, 72)\
1827     "paddusw %%mm1, %%mm0             \n\t"\
1828     HSUM(%%mm0, %%mm1, %0)
1829
1830 #define DCT_SAD_SSE2\
1831     "pxor %%xmm0, %%xmm0              \n\t"\
1832     "pxor %%xmm1, %%xmm1              \n\t"\
1833     DCT_SAD4(dqa, %%xmm, 0)\
1834     DCT_SAD4(dqa, %%xmm, 64)\
1835     "paddusw %%xmm1, %%xmm0           \n\t"\
1836     HSUM(%%xmm0, %%xmm1, %0)
1837
1838 #define DCT_SAD_FUNC(cpu) \
1839 static int sum_abs_dctelem_##cpu(DCTELEM *block){\
1840     int sum;\
1841     asm volatile(\
1842         DCT_SAD\
1843         :"=r"(sum)\
1844         :"r"(block)\
1845     );\
1846     return sum&0xFFFF;\
1847 }
1848
1849 #define DCT_SAD       DCT_SAD_MMX
1850 #define HSUM(a,t,dst) HSUM_MMX(a,t,dst)
1851 #define MMABS(a,z)    MMABS_MMX(a,z)
1852 DCT_SAD_FUNC(mmx)
1853 #undef MMABS
1854 #undef HSUM
1855
1856 #define HSUM(a,t,dst) HSUM_MMX2(a,t,dst)
1857 #define MMABS(a,z)    MMABS_MMX2(a,z)
1858 DCT_SAD_FUNC(mmx2)
1859 #undef HSUM
1860 #undef DCT_SAD
1861
1862 #define DCT_SAD       DCT_SAD_SSE2
1863 #define HSUM(a,t,dst) HSUM_SSE2(a,t,dst)
1864 DCT_SAD_FUNC(sse2)
1865 #undef MMABS
1866
1867 #ifdef HAVE_SSSE3
1868 #define MMABS(a,z)    MMABS_SSSE3(a,z)
1869 DCT_SAD_FUNC(ssse3)
1870 #undef MMABS
1871 #endif
1872 #undef HSUM
1873 #undef DCT_SAD
1874
1875 static int ssd_int8_vs_int16_mmx(int8_t *pix1, int16_t *pix2, int size){
1876     int sum;
1877     long i=size;
1878     asm volatile(
1879         "pxor %%mm4, %%mm4 \n"
1880         "1: \n"
1881         "sub $8, %0 \n"
1882         "movq (%2,%0), %%mm2 \n"
1883         "movq (%3,%0,2), %%mm0 \n"
1884         "movq 8(%3,%0,2), %%mm1 \n"
1885         "punpckhbw %%mm2, %%mm3 \n"
1886         "punpcklbw %%mm2, %%mm2 \n"
1887         "psraw $8, %%mm3 \n"
1888         "psraw $8, %%mm2 \n"
1889         "psubw %%mm3, %%mm1 \n"
1890         "psubw %%mm2, %%mm0 \n"
1891         "pmaddwd %%mm1, %%mm1 \n"
1892         "pmaddwd %%mm0, %%mm0 \n"
1893         "paddd %%mm1, %%mm4 \n"
1894         "paddd %%mm0, %%mm4 \n"
1895         "jg 1b \n"
1896         "movq %%mm4, %%mm3 \n"
1897         "psrlq $32, %%mm3 \n"
1898         "paddd %%mm3, %%mm4 \n"
1899         "movd %%mm4, %1 \n"
1900         :"+r"(i), "=r"(sum)
1901         :"r"(pix1), "r"(pix2)
1902     );
1903     return sum;
1904 }
1905
1906 #endif //CONFIG_ENCODERS
1907
1908 #define put_no_rnd_pixels8_mmx(a,b,c,d) put_pixels8_mmx(a,b,c,d)
1909 #define put_no_rnd_pixels16_mmx(a,b,c,d) put_pixels16_mmx(a,b,c,d)
1910
1911 #define QPEL_V_LOW(m3,m4,m5,m6, pw_20, pw_3, rnd, in0, in1, in2, in7, out, OP)\
1912         "paddw " #m4 ", " #m3 "           \n\t" /* x1 */\
1913         "movq "MANGLE(ff_pw_20)", %%mm4   \n\t" /* 20 */\
1914         "pmullw " #m3 ", %%mm4            \n\t" /* 20x1 */\
1915         "movq "#in7", " #m3 "             \n\t" /* d */\
1916         "movq "#in0", %%mm5               \n\t" /* D */\
1917         "paddw " #m3 ", %%mm5             \n\t" /* x4 */\
1918         "psubw %%mm5, %%mm4               \n\t" /* 20x1 - x4 */\
1919         "movq "#in1", %%mm5               \n\t" /* C */\
1920         "movq "#in2", %%mm6               \n\t" /* B */\
1921         "paddw " #m6 ", %%mm5             \n\t" /* x3 */\
1922         "paddw " #m5 ", %%mm6             \n\t" /* x2 */\
1923         "paddw %%mm6, %%mm6               \n\t" /* 2x2 */\
1924         "psubw %%mm6, %%mm5               \n\t" /* -2x2 + x3 */\
1925         "pmullw "MANGLE(ff_pw_3)", %%mm5  \n\t" /* -6x2 + 3x3 */\
1926         "paddw " #rnd ", %%mm4            \n\t" /* x2 */\
1927         "paddw %%mm4, %%mm5               \n\t" /* 20x1 - 6x2 + 3x3 - x4 */\
1928         "psraw $5, %%mm5                  \n\t"\
1929         "packuswb %%mm5, %%mm5            \n\t"\
1930         OP(%%mm5, out, %%mm7, d)
1931
1932 #define QPEL_BASE(OPNAME, ROUNDER, RND, OP_MMX2, OP_3DNOW)\
1933 static void OPNAME ## mpeg4_qpel16_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
1934     uint64_t temp;\
1935 \
1936     asm volatile(\
1937         "pxor %%mm7, %%mm7                \n\t"\
1938         "1:                               \n\t"\
1939         "movq  (%0), %%mm0                \n\t" /* ABCDEFGH */\
1940         "movq %%mm0, %%mm1                \n\t" /* ABCDEFGH */\
1941         "movq %%mm0, %%mm2                \n\t" /* ABCDEFGH */\
1942         "punpcklbw %%mm7, %%mm0           \n\t" /* 0A0B0C0D */\
1943         "punpckhbw %%mm7, %%mm1           \n\t" /* 0E0F0G0H */\
1944         "pshufw $0x90, %%mm0, %%mm5       \n\t" /* 0A0A0B0C */\
1945         "pshufw $0x41, %%mm0, %%mm6       \n\t" /* 0B0A0A0B */\
1946         "movq %%mm2, %%mm3                \n\t" /* ABCDEFGH */\
1947         "movq %%mm2, %%mm4                \n\t" /* ABCDEFGH */\
1948         "psllq $8, %%mm2                  \n\t" /* 0ABCDEFG */\
1949         "psllq $16, %%mm3                 \n\t" /* 00ABCDEF */\
1950         "psllq $24, %%mm4                 \n\t" /* 000ABCDE */\
1951         "punpckhbw %%mm7, %%mm2           \n\t" /* 0D0E0F0G */\
1952         "punpckhbw %%mm7, %%mm3           \n\t" /* 0C0D0E0F */\
1953         "punpckhbw %%mm7, %%mm4           \n\t" /* 0B0C0D0E */\
1954         "paddw %%mm3, %%mm5               \n\t" /* b */\
1955         "paddw %%mm2, %%mm6               \n\t" /* c */\
1956         "paddw %%mm5, %%mm5               \n\t" /* 2b */\
1957         "psubw %%mm5, %%mm6               \n\t" /* c - 2b */\
1958         "pshufw $0x06, %%mm0, %%mm5       \n\t" /* 0C0B0A0A */\
1959         "pmullw "MANGLE(ff_pw_3)", %%mm6  \n\t" /* 3c - 6b */\
1960         "paddw %%mm4, %%mm0               \n\t" /* a */\
1961         "paddw %%mm1, %%mm5               \n\t" /* d */\
1962         "pmullw "MANGLE(ff_pw_20)", %%mm0 \n\t" /* 20a */\
1963         "psubw %%mm5, %%mm0               \n\t" /* 20a - d */\
1964         "paddw %6, %%mm6                  \n\t"\
1965         "paddw %%mm6, %%mm0               \n\t" /* 20a - 6b + 3c - d */\
1966         "psraw $5, %%mm0                  \n\t"\
1967         "movq %%mm0, %5                   \n\t"\
1968         /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\
1969         \
1970         "movq 5(%0), %%mm0                \n\t" /* FGHIJKLM */\
1971         "movq %%mm0, %%mm5                \n\t" /* FGHIJKLM */\
1972         "movq %%mm0, %%mm6                \n\t" /* FGHIJKLM */\
1973         "psrlq $8, %%mm0                  \n\t" /* GHIJKLM0 */\
1974         "psrlq $16, %%mm5                 \n\t" /* HIJKLM00 */\
1975         "punpcklbw %%mm7, %%mm0           \n\t" /* 0G0H0I0J */\
1976         "punpcklbw %%mm7, %%mm5           \n\t" /* 0H0I0J0K */\
1977         "paddw %%mm0, %%mm2               \n\t" /* b */\
1978         "paddw %%mm5, %%mm3               \n\t" /* c */\
1979         "paddw %%mm2, %%mm2               \n\t" /* 2b */\
1980         "psubw %%mm2, %%mm3               \n\t" /* c - 2b */\
1981         "movq %%mm6, %%mm2                \n\t" /* FGHIJKLM */\
1982         "psrlq $24, %%mm6                 \n\t" /* IJKLM000 */\
1983         "punpcklbw %%mm7, %%mm2           \n\t" /* 0F0G0H0I */\
1984         "punpcklbw %%mm7, %%mm6           \n\t" /* 0I0J0K0L */\
1985         "pmullw "MANGLE(ff_pw_3)", %%mm3  \n\t" /* 3c - 6b */\
1986         "paddw %%mm2, %%mm1               \n\t" /* a */\
1987         "paddw %%mm6, %%mm4               \n\t" /* d */\
1988         "pmullw "MANGLE(ff_pw_20)", %%mm1 \n\t" /* 20a */\
1989         "psubw %%mm4, %%mm3               \n\t" /* - 6b +3c - d */\
1990         "paddw %6, %%mm1                  \n\t"\
1991         "paddw %%mm1, %%mm3               \n\t" /* 20a - 6b +3c - d */\
1992         "psraw $5, %%mm3                  \n\t"\
1993         "movq %5, %%mm1                   \n\t"\
1994         "packuswb %%mm3, %%mm1            \n\t"\
1995         OP_MMX2(%%mm1, (%1),%%mm4, q)\
1996         /* mm0= GHIJ, mm2=FGHI, mm5=HIJK, mm6=IJKL, mm7=0 */\
1997         \
1998         "movq 9(%0), %%mm1                \n\t" /* JKLMNOPQ */\
1999         "movq %%mm1, %%mm4                \n\t" /* JKLMNOPQ */\
2000         "movq %%mm1, %%mm3                \n\t" /* JKLMNOPQ */\
2001         "psrlq $8, %%mm1                  \n\t" /* KLMNOPQ0 */\
2002         "psrlq $16, %%mm4                 \n\t" /* LMNOPQ00 */\
2003         "punpcklbw %%mm7, %%mm1           \n\t" /* 0K0L0M0N */\
2004         "punpcklbw %%mm7, %%mm4           \n\t" /* 0L0M0N0O */\
2005         "paddw %%mm1, %%mm5               \n\t" /* b */\
2006         "paddw %%mm4, %%mm0               \n\t" /* c */\
2007         "paddw %%mm5, %%mm5               \n\t" /* 2b */\
2008         "psubw %%mm5, %%mm0               \n\t" /* c - 2b */\
2009         "movq %%mm3, %%mm5                \n\t" /* JKLMNOPQ */\
2010         "psrlq $24, %%mm3                 \n\t" /* MNOPQ000 */\
2011         "pmullw "MANGLE(ff_pw_3)", %%mm0  \n\t" /* 3c - 6b */\
2012         "punpcklbw %%mm7, %%mm3           \n\t" /* 0M0N0O0P */\
2013         "paddw %%mm3, %%mm2               \n\t" /* d */\
2014         "psubw %%mm2, %%mm0               \n\t" /* -6b + 3c - d */\
2015         "movq %%mm5, %%mm2                \n\t" /* JKLMNOPQ */\
2016         "punpcklbw %%mm7, %%mm2           \n\t" /* 0J0K0L0M */\
2017         "punpckhbw %%mm7, %%mm5           \n\t" /* 0N0O0P0Q */\
2018         "paddw %%mm2, %%mm6               \n\t" /* a */\
2019         "pmullw "MANGLE(ff_pw_20)", %%mm6 \n\t" /* 20a */\
2020         "paddw %6, %%mm0                  \n\t"\
2021         "paddw %%mm6, %%mm0               \n\t" /* 20a - 6b + 3c - d */\
2022         "psraw $5, %%mm0                  \n\t"\
2023         /* mm1=KLMN, mm2=JKLM, mm3=MNOP, mm4=LMNO, mm5=NOPQ mm7=0 */\
2024         \
2025         "paddw %%mm5, %%mm3               \n\t" /* a */\
2026         "pshufw $0xF9, %%mm5, %%mm6       \n\t" /* 0O0P0Q0Q */\
2027         "paddw %%mm4, %%mm6               \n\t" /* b */\
2028         "pshufw $0xBE, %%mm5, %%mm4       \n\t" /* 0P0Q0Q0P */\
2029         "pshufw $0x6F, %%mm5, %%mm5       \n\t" /* 0Q0Q0P0O */\
2030         "paddw %%mm1, %%mm4               \n\t" /* c */\
2031         "paddw %%mm2, %%mm5               \n\t" /* d */\
2032         "paddw %%mm6, %%mm6               \n\t" /* 2b */\
2033         "psubw %%mm6, %%mm4               \n\t" /* c - 2b */\
2034         "pmullw "MANGLE(ff_pw_20)", %%mm3 \n\t" /* 20a */\
2035         "pmullw "MANGLE(ff_pw_3)", %%mm4  \n\t" /* 3c - 6b */\
2036         "psubw %%mm5, %%mm3               \n\t" /* -6b + 3c - d */\
2037         "paddw %6, %%mm4                  \n\t"\
2038         "paddw %%mm3, %%mm4               \n\t" /* 20a - 6b + 3c - d */\
2039         "psraw $5, %%mm4                  \n\t"\
2040         "packuswb %%mm4, %%mm0            \n\t"\
2041         OP_MMX2(%%mm0, 8(%1), %%mm4, q)\
2042         \
2043         "add %3, %0                       \n\t"\
2044         "add %4, %1                       \n\t"\
2045         "decl %2                          \n\t"\
2046         " jnz 1b                          \n\t"\
2047         : "+a"(src), "+c"(dst), "+m"(h)\
2048         : "d"((long)srcStride), "S"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\
2049         : "memory"\
2050     );\
2051 }\
2052 \
2053 static void OPNAME ## mpeg4_qpel16_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
2054     int i;\
2055     int16_t temp[16];\
2056     /* quick HACK, XXX FIXME MUST be optimized */\
2057     for(i=0; i<h; i++)\
2058     {\
2059         temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\
2060         temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\
2061         temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\
2062         temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\
2063         temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\
2064         temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 9]);\
2065         temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 9])*3 - (src[ 3]+src[10]);\
2066         temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 9])*6 + (src[ 5]+src[10])*3 - (src[ 4]+src[11]);\
2067         temp[ 8]= (src[ 8]+src[ 9])*20 - (src[ 7]+src[10])*6 + (src[ 6]+src[11])*3 - (src[ 5]+src[12]);\
2068         temp[ 9]= (src[ 9]+src[10])*20 - (src[ 8]+src[11])*6 + (src[ 7]+src[12])*3 - (src[ 6]+src[13]);\
2069         temp[10]= (src[10]+src[11])*20 - (src[ 9]+src[12])*6 + (src[ 8]+src[13])*3 - (src[ 7]+src[14]);\
2070         temp[11]= (src[11]+src[12])*20 - (src[10]+src[13])*6 + (src[ 9]+src[14])*3 - (src[ 8]+src[15]);\
2071         temp[12]= (src[12]+src[13])*20 - (src[11]+src[14])*6 + (src[10]+src[15])*3 - (src[ 9]+src[16]);\
2072         temp[13]= (src[13]+src[14])*20 - (src[12]+src[15])*6 + (src[11]+src[16])*3 - (src[10]+src[16]);\
2073         temp[14]= (src[14]+src[15])*20 - (src[13]+src[16])*6 + (src[12]+src[16])*3 - (src[11]+src[15]);\
2074         temp[15]= (src[15]+src[16])*20 - (src[14]+src[16])*6 + (src[13]+src[15])*3 - (src[12]+src[14]);\
2075         asm volatile(\
2076             "movq (%0), %%mm0               \n\t"\
2077             "movq 8(%0), %%mm1              \n\t"\
2078             "paddw %2, %%mm0                \n\t"\
2079             "paddw %2, %%mm1                \n\t"\
2080             "psraw $5, %%mm0                \n\t"\
2081             "psraw $5, %%mm1                \n\t"\
2082             "packuswb %%mm1, %%mm0          \n\t"\
2083             OP_3DNOW(%%mm0, (%1), %%mm1, q)\
2084             "movq 16(%0), %%mm0             \n\t"\
2085             "movq 24(%0), %%mm1             \n\t"\
2086             "paddw %2, %%mm0                \n\t"\
2087             "paddw %2, %%mm1                \n\t"\
2088             "psraw $5, %%mm0                \n\t"\
2089             "psraw $5, %%mm1                \n\t"\
2090             "packuswb %%mm1, %%mm0          \n\t"\
2091             OP_3DNOW(%%mm0, 8(%1), %%mm1, q)\
2092             :: "r"(temp), "r"(dst), "m"(ROUNDER)\
2093             : "memory"\
2094         );\
2095         dst+=dstStride;\
2096         src+=srcStride;\
2097     }\
2098 }\
2099 \
2100 static void OPNAME ## mpeg4_qpel8_h_lowpass_mmx2(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
2101     uint64_t temp;\
2102 \
2103     asm volatile(\
2104         "pxor %%mm7, %%mm7                \n\t"\
2105         "1:                               \n\t"\
2106         "movq  (%0), %%mm0                \n\t" /* ABCDEFGH */\
2107         "movq %%mm0, %%mm1                \n\t" /* ABCDEFGH */\
2108         "movq %%mm0, %%mm2                \n\t" /* ABCDEFGH */\
2109         "punpcklbw %%mm7, %%mm0           \n\t" /* 0A0B0C0D */\
2110         "punpckhbw %%mm7, %%mm1           \n\t" /* 0E0F0G0H */\
2111         "pshufw $0x90, %%mm0, %%mm5       \n\t" /* 0A0A0B0C */\
2112         "pshufw $0x41, %%mm0, %%mm6       \n\t" /* 0B0A0A0B */\
2113         "movq %%mm2, %%mm3                \n\t" /* ABCDEFGH */\
2114         "movq %%mm2, %%mm4                \n\t" /* ABCDEFGH */\
2115         "psllq $8, %%mm2                  \n\t" /* 0ABCDEFG */\
2116         "psllq $16, %%mm3                 \n\t" /* 00ABCDEF */\
2117         "psllq $24, %%mm4                 \n\t" /* 000ABCDE */\
2118         "punpckhbw %%mm7, %%mm2           \n\t" /* 0D0E0F0G */\
2119         "punpckhbw %%mm7, %%mm3           \n\t" /* 0C0D0E0F */\
2120         "punpckhbw %%mm7, %%mm4           \n\t" /* 0B0C0D0E */\
2121         "paddw %%mm3, %%mm5               \n\t" /* b */\
2122         "paddw %%mm2, %%mm6               \n\t" /* c */\
2123         "paddw %%mm5, %%mm5               \n\t" /* 2b */\
2124         "psubw %%mm5, %%mm6               \n\t" /* c - 2b */\
2125         "pshufw $0x06, %%mm0, %%mm5       \n\t" /* 0C0B0A0A */\
2126         "pmullw "MANGLE(ff_pw_3)", %%mm6  \n\t" /* 3c - 6b */\
2127         "paddw %%mm4, %%mm0               \n\t" /* a */\
2128         "paddw %%mm1, %%mm5               \n\t" /* d */\
2129         "pmullw "MANGLE(ff_pw_20)", %%mm0 \n\t" /* 20a */\
2130         "psubw %%mm5, %%mm0               \n\t" /* 20a - d */\
2131         "paddw %6, %%mm6                  \n\t"\
2132         "paddw %%mm6, %%mm0               \n\t" /* 20a - 6b + 3c - d */\
2133         "psraw $5, %%mm0                  \n\t"\
2134         /* mm1=EFGH, mm2=DEFG, mm3=CDEF, mm4=BCDE, mm7=0 */\
2135         \
2136         "movd 5(%0), %%mm5                \n\t" /* FGHI */\
2137         "punpcklbw %%mm7, %%mm5           \n\t" /* 0F0G0H0I */\
2138         "pshufw $0xF9, %%mm5, %%mm6       \n\t" /* 0G0H0I0I */\
2139         "paddw %%mm5, %%mm1               \n\t" /* a */\
2140         "paddw %%mm6, %%mm2               \n\t" /* b */\
2141         "pshufw $0xBE, %%mm5, %%mm6       \n\t" /* 0H0I0I0H */\
2142         "pshufw $0x6F, %%mm5, %%mm5       \n\t" /* 0I0I0H0G */\
2143         "paddw %%mm6, %%mm3               \n\t" /* c */\
2144         "paddw %%mm5, %%mm4               \n\t" /* d */\
2145         "paddw %%mm2, %%mm2               \n\t" /* 2b */\
2146         "psubw %%mm2, %%mm3               \n\t" /* c - 2b */\
2147         "pmullw "MANGLE(ff_pw_20)", %%mm1 \n\t" /* 20a */\
2148         "pmullw "MANGLE(ff_pw_3)", %%mm3  \n\t" /* 3c - 6b */\
2149         "psubw %%mm4, %%mm3               \n\t" /* -6b + 3c - d */\
2150         "paddw %6, %%mm1                  \n\t"\
2151         "paddw %%mm1, %%mm3               \n\t" /* 20a - 6b + 3c - d */\
2152         "psraw $5, %%mm3                  \n\t"\
2153         "packuswb %%mm3, %%mm0            \n\t"\
2154         OP_MMX2(%%mm0, (%1), %%mm4, q)\
2155         \
2156         "add %3, %0                       \n\t"\
2157         "add %4, %1                       \n\t"\
2158         "decl %2                          \n\t"\
2159         " jnz 1b                          \n\t"\
2160         : "+a"(src), "+c"(dst), "+m"(h)\
2161         : "S"((long)srcStride), "D"((long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(temp), "m"(ROUNDER)\
2162         : "memory"\
2163     );\
2164 }\
2165 \
2166 static void OPNAME ## mpeg4_qpel8_h_lowpass_3dnow(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int h){\
2167     int i;\
2168     int16_t temp[8];\
2169     /* quick HACK, XXX FIXME MUST be optimized */\
2170     for(i=0; i<h; i++)\
2171     {\
2172         temp[ 0]= (src[ 0]+src[ 1])*20 - (src[ 0]+src[ 2])*6 + (src[ 1]+src[ 3])*3 - (src[ 2]+src[ 4]);\
2173         temp[ 1]= (src[ 1]+src[ 2])*20 - (src[ 0]+src[ 3])*6 + (src[ 0]+src[ 4])*3 - (src[ 1]+src[ 5]);\
2174         temp[ 2]= (src[ 2]+src[ 3])*20 - (src[ 1]+src[ 4])*6 + (src[ 0]+src[ 5])*3 - (src[ 0]+src[ 6]);\
2175         temp[ 3]= (src[ 3]+src[ 4])*20 - (src[ 2]+src[ 5])*6 + (src[ 1]+src[ 6])*3 - (src[ 0]+src[ 7]);\
2176         temp[ 4]= (src[ 4]+src[ 5])*20 - (src[ 3]+src[ 6])*6 + (src[ 2]+src[ 7])*3 - (src[ 1]+src[ 8]);\
2177         temp[ 5]= (src[ 5]+src[ 6])*20 - (src[ 4]+src[ 7])*6 + (src[ 3]+src[ 8])*3 - (src[ 2]+src[ 8]);\
2178         temp[ 6]= (src[ 6]+src[ 7])*20 - (src[ 5]+src[ 8])*6 + (src[ 4]+src[ 8])*3 - (src[ 3]+src[ 7]);\
2179         temp[ 7]= (src[ 7]+src[ 8])*20 - (src[ 6]+src[ 8])*6 + (src[ 5]+src[ 7])*3 - (src[ 4]+src[ 6]);\
2180         asm volatile(\
2181             "movq (%0), %%mm0           \n\t"\
2182             "movq 8(%0), %%mm1          \n\t"\
2183             "paddw %2, %%mm0            \n\t"\
2184             "paddw %2, %%mm1            \n\t"\
2185             "psraw $5, %%mm0            \n\t"\
2186             "psraw $5, %%mm1            \n\t"\
2187             "packuswb %%mm1, %%mm0      \n\t"\
2188             OP_3DNOW(%%mm0, (%1), %%mm1, q)\
2189             :: "r"(temp), "r"(dst), "m"(ROUNDER)\
2190             :"memory"\
2191         );\
2192         dst+=dstStride;\
2193         src+=srcStride;\
2194     }\
2195 }
2196
2197 #define QPEL_OP(OPNAME, ROUNDER, RND, OP, MMX)\
2198 \
2199 static void OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
2200     uint64_t temp[17*4];\
2201     uint64_t *temp_ptr= temp;\
2202     int count= 17;\
2203 \
2204     /*FIXME unroll */\
2205     asm volatile(\
2206         "pxor %%mm7, %%mm7              \n\t"\
2207         "1:                             \n\t"\
2208         "movq (%0), %%mm0               \n\t"\
2209         "movq (%0), %%mm1               \n\t"\
2210         "movq 8(%0), %%mm2              \n\t"\
2211         "movq 8(%0), %%mm3              \n\t"\
2212         "punpcklbw %%mm7, %%mm0         \n\t"\
2213         "punpckhbw %%mm7, %%mm1         \n\t"\
2214         "punpcklbw %%mm7, %%mm2         \n\t"\
2215         "punpckhbw %%mm7, %%mm3         \n\t"\
2216         "movq %%mm0, (%1)               \n\t"\
2217         "movq %%mm1, 17*8(%1)           \n\t"\
2218         "movq %%mm2, 2*17*8(%1)         \n\t"\
2219         "movq %%mm3, 3*17*8(%1)         \n\t"\
2220         "add $8, %1                     \n\t"\
2221         "add %3, %0                     \n\t"\
2222         "decl %2                        \n\t"\
2223         " jnz 1b                        \n\t"\
2224         : "+r" (src), "+r" (temp_ptr), "+r"(count)\
2225         : "r" ((long)srcStride)\
2226         : "memory"\
2227     );\
2228     \
2229     temp_ptr= temp;\
2230     count=4;\
2231     \
2232 /*FIXME reorder for speed */\
2233     asm volatile(\
2234         /*"pxor %%mm7, %%mm7              \n\t"*/\
2235         "1:                             \n\t"\
2236         "movq (%0), %%mm0               \n\t"\
2237         "movq 8(%0), %%mm1              \n\t"\
2238         "movq 16(%0), %%mm2             \n\t"\
2239         "movq 24(%0), %%mm3             \n\t"\
2240         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)\
2241         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)\
2242         "add %4, %1                     \n\t"\
2243         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)\
2244         \
2245         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)\
2246         "add %4, %1                     \n\t"\
2247         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\
2248         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 72(%0), (%1, %3), OP)\
2249         "add %4, %1                     \n\t"\
2250         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 80(%0), (%1), OP)\
2251         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 88(%0), (%1, %3), OP)\
2252         "add %4, %1                     \n\t"\
2253         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 40(%0), 48(%0), 56(%0), 96(%0), (%1), OP)\
2254         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 48(%0), 56(%0), 64(%0),104(%0), (%1, %3), OP)\
2255         "add %4, %1                     \n\t"\
2256         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 56(%0), 64(%0), 72(%0),112(%0), (%1), OP)\
2257         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 64(%0), 72(%0), 80(%0),120(%0), (%1, %3), OP)\
2258         "add %4, %1                     \n\t"\
2259         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 72(%0), 80(%0), 88(%0),128(%0), (%1), OP)\
2260         \
2261         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 80(%0), 88(%0), 96(%0),128(%0), (%1, %3), OP)\
2262         "add %4, %1                     \n\t"  \
2263         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 88(%0), 96(%0),104(%0),120(%0), (%1), OP)\
2264         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 96(%0),104(%0),112(%0),112(%0), (%1, %3), OP)\
2265         \
2266         "add $136, %0                   \n\t"\
2267         "add %6, %1                     \n\t"\
2268         "decl %2                        \n\t"\
2269         " jnz 1b                        \n\t"\
2270         \
2271         : "+r"(temp_ptr), "+r"(dst), "+g"(count)\
2272         : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-14*(long)dstStride)\
2273         :"memory"\
2274     );\
2275 }\
2276 \
2277 static void OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(uint8_t *dst, uint8_t *src, int dstStride, int srcStride){\
2278     uint64_t temp[9*2];\
2279     uint64_t *temp_ptr= temp;\
2280     int count= 9;\
2281 \
2282     /*FIXME unroll */\
2283     asm volatile(\
2284         "pxor %%mm7, %%mm7              \n\t"\
2285         "1:                             \n\t"\
2286         "movq (%0), %%mm0               \n\t"\
2287         "movq (%0), %%mm1               \n\t"\
2288         "punpcklbw %%mm7, %%mm0         \n\t"\
2289         "punpckhbw %%mm7, %%mm1         \n\t"\
2290         "movq %%mm0, (%1)               \n\t"\
2291         "movq %%mm1, 9*8(%1)            \n\t"\
2292         "add $8, %1                     \n\t"\
2293         "add %3, %0                     \n\t"\
2294         "decl %2                        \n\t"\
2295         " jnz 1b                        \n\t"\
2296         : "+r" (src), "+r" (temp_ptr), "+r"(count)\
2297         : "r" ((long)srcStride)\
2298         : "memory"\
2299     );\
2300     \
2301     temp_ptr= temp;\
2302     count=2;\
2303     \
2304 /*FIXME reorder for speed */\
2305     asm volatile(\
2306         /*"pxor %%mm7, %%mm7              \n\t"*/\
2307         "1:                             \n\t"\
2308         "movq (%0), %%mm0               \n\t"\
2309         "movq 8(%0), %%mm1              \n\t"\
2310         "movq 16(%0), %%mm2             \n\t"\
2311         "movq 24(%0), %%mm3             \n\t"\
2312         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5, 16(%0),  8(%0),   (%0), 32(%0), (%1), OP)\
2313         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5,  8(%0),   (%0),   (%0), 40(%0), (%1, %3), OP)\
2314         "add %4, %1                     \n\t"\
2315         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5,   (%0),   (%0),  8(%0), 48(%0), (%1), OP)\
2316         \
2317         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5,   (%0),  8(%0), 16(%0), 56(%0), (%1, %3), OP)\
2318         "add %4, %1                     \n\t"\
2319         QPEL_V_LOW(%%mm0, %%mm1, %%mm2, %%mm3, %5, %6, %5,  8(%0), 16(%0), 24(%0), 64(%0), (%1), OP)\
2320         \
2321         QPEL_V_LOW(%%mm1, %%mm2, %%mm3, %%mm0, %5, %6, %5, 16(%0), 24(%0), 32(%0), 64(%0), (%1, %3), OP)\
2322         "add %4, %1                     \n\t"\
2323         QPEL_V_LOW(%%mm2, %%mm3, %%mm0, %%mm1, %5, %6, %5, 24(%0), 32(%0), 40(%0), 56(%0), (%1), OP)\
2324         QPEL_V_LOW(%%mm3, %%mm0, %%mm1, %%mm2, %5, %6, %5, 32(%0), 40(%0), 48(%0), 48(%0), (%1, %3), OP)\
2325                 \
2326         "add $72, %0                    \n\t"\
2327         "add %6, %1                     \n\t"\
2328         "decl %2                        \n\t"\
2329         " jnz 1b                        \n\t"\
2330          \
2331         : "+r"(temp_ptr), "+r"(dst), "+g"(count)\
2332         : "r"((long)dstStride), "r"(2*(long)dstStride), /*"m"(ff_pw_20), "m"(ff_pw_3),*/ "m"(ROUNDER), "g"(4-6*(long)dstStride)\
2333         : "memory"\
2334    );\
2335 }\
2336 \
2337 static void OPNAME ## qpel8_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
2338     OPNAME ## pixels8_mmx(dst, src, stride, 8);\
2339 }\
2340 \
2341 static void OPNAME ## qpel8_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2342     uint64_t temp[8];\
2343     uint8_t * const half= (uint8_t*)temp;\
2344     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
2345     OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\
2346 }\
2347 \
2348 static void OPNAME ## qpel8_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2349     OPNAME ## mpeg4_qpel8_h_lowpass_ ## MMX(dst, src, stride, stride, 8);\
2350 }\
2351 \
2352 static void OPNAME ## qpel8_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2353     uint64_t temp[8];\
2354     uint8_t * const half= (uint8_t*)temp;\
2355     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(half, src, 8, stride, 8);\
2356     OPNAME ## pixels8_l2_ ## MMX(dst, src+1, half, stride, stride, 8);\
2357 }\
2358 \
2359 static void OPNAME ## qpel8_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2360     uint64_t temp[8];\
2361     uint8_t * const half= (uint8_t*)temp;\
2362     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
2363     OPNAME ## pixels8_l2_ ## MMX(dst, src, half, stride, stride, 8);\
2364 }\
2365 \
2366 static void OPNAME ## qpel8_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2367     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, src, stride, stride);\
2368 }\
2369 \
2370 static void OPNAME ## qpel8_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2371     uint64_t temp[8];\
2372     uint8_t * const half= (uint8_t*)temp;\
2373     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(half, src, 8, stride);\
2374     OPNAME ## pixels8_l2_ ## MMX(dst, src+stride, half, stride, stride, 8);\
2375 }\
2376 static void OPNAME ## qpel8_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2377     uint64_t half[8 + 9];\
2378     uint8_t * const halfH= ((uint8_t*)half) + 64;\
2379     uint8_t * const halfHV= ((uint8_t*)half);\
2380     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2381     put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
2382     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
2383     OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
2384 }\
2385 static void OPNAME ## qpel8_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2386     uint64_t half[8 + 9];\
2387     uint8_t * const halfH= ((uint8_t*)half) + 64;\
2388     uint8_t * const halfHV= ((uint8_t*)half);\
2389     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2390     put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
2391     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
2392     OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
2393 }\
2394 static void OPNAME ## qpel8_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2395     uint64_t half[8 + 9];\
2396     uint8_t * const halfH= ((uint8_t*)half) + 64;\
2397     uint8_t * const halfHV= ((uint8_t*)half);\
2398     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2399     put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
2400     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
2401     OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
2402 }\
2403 static void OPNAME ## qpel8_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2404     uint64_t half[8 + 9];\
2405     uint8_t * const halfH= ((uint8_t*)half) + 64;\
2406     uint8_t * const halfHV= ((uint8_t*)half);\
2407     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2408     put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
2409     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
2410     OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
2411 }\
2412 static void OPNAME ## qpel8_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2413     uint64_t half[8 + 9];\
2414     uint8_t * const halfH= ((uint8_t*)half) + 64;\
2415     uint8_t * const halfHV= ((uint8_t*)half);\
2416     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2417     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
2418     OPNAME ## pixels8_l2_ ## MMX(dst, halfH, halfHV, stride, 8, 8);\
2419 }\
2420 static void OPNAME ## qpel8_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2421     uint64_t half[8 + 9];\
2422     uint8_t * const halfH= ((uint8_t*)half) + 64;\
2423     uint8_t * const halfHV= ((uint8_t*)half);\
2424     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2425     put ## RND ## mpeg4_qpel8_v_lowpass_ ## MMX(halfHV, halfH, 8, 8);\
2426     OPNAME ## pixels8_l2_ ## MMX(dst, halfH+8, halfHV, stride, 8, 8);\
2427 }\
2428 static void OPNAME ## qpel8_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2429     uint64_t half[8 + 9];\
2430     uint8_t * const halfH= ((uint8_t*)half);\
2431     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2432     put ## RND ## pixels8_l2_ ## MMX(halfH, src, halfH, 8, stride, 9);\
2433     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
2434 }\
2435 static void OPNAME ## qpel8_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2436     uint64_t half[8 + 9];\
2437     uint8_t * const halfH= ((uint8_t*)half);\
2438     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2439     put ## RND ## pixels8_l2_ ## MMX(halfH, src+1, halfH, 8, stride, 9);\
2440     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
2441 }\
2442 static void OPNAME ## qpel8_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2443     uint64_t half[9];\
2444     uint8_t * const halfH= ((uint8_t*)half);\
2445     put ## RND ## mpeg4_qpel8_h_lowpass_ ## MMX(halfH, src, 8, stride, 9);\
2446     OPNAME ## mpeg4_qpel8_v_lowpass_ ## MMX(dst, halfH, stride, 8);\
2447 }\
2448 static void OPNAME ## qpel16_mc00_ ## MMX (uint8_t *dst, uint8_t *src, int stride){\
2449     OPNAME ## pixels16_mmx(dst, src, stride, 16);\
2450 }\
2451 \
2452 static void OPNAME ## qpel16_mc10_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2453     uint64_t temp[32];\
2454     uint8_t * const half= (uint8_t*)temp;\
2455     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
2456     OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\
2457 }\
2458 \
2459 static void OPNAME ## qpel16_mc20_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2460     OPNAME ## mpeg4_qpel16_h_lowpass_ ## MMX(dst, src, stride, stride, 16);\
2461 }\
2462 \
2463 static void OPNAME ## qpel16_mc30_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2464     uint64_t temp[32];\
2465     uint8_t * const half= (uint8_t*)temp;\
2466     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(half, src, 16, stride, 16);\
2467     OPNAME ## pixels16_l2_ ## MMX(dst, src+1, half, stride, stride, 16);\
2468 }\
2469 \
2470 static void OPNAME ## qpel16_mc01_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2471     uint64_t temp[32];\
2472     uint8_t * const half= (uint8_t*)temp;\
2473     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
2474     OPNAME ## pixels16_l2_ ## MMX(dst, src, half, stride, stride, 16);\
2475 }\
2476 \
2477 static void OPNAME ## qpel16_mc02_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2478     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, src, stride, stride);\
2479 }\
2480 \
2481 static void OPNAME ## qpel16_mc03_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2482     uint64_t temp[32];\
2483     uint8_t * const half= (uint8_t*)temp;\
2484     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(half, src, 16, stride);\
2485     OPNAME ## pixels16_l2_ ## MMX(dst, src+stride, half, stride, stride, 16);\
2486 }\
2487 static void OPNAME ## qpel16_mc11_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2488     uint64_t half[16*2 + 17*2];\
2489     uint8_t * const halfH= ((uint8_t*)half) + 256;\
2490     uint8_t * const halfHV= ((uint8_t*)half);\
2491     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2492     put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
2493     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
2494     OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
2495 }\
2496 static void OPNAME ## qpel16_mc31_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2497     uint64_t half[16*2 + 17*2];\
2498     uint8_t * const halfH= ((uint8_t*)half) + 256;\
2499     uint8_t * const halfHV= ((uint8_t*)half);\
2500     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2501     put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
2502     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
2503     OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
2504 }\
2505 static void OPNAME ## qpel16_mc13_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2506     uint64_t half[16*2 + 17*2];\
2507     uint8_t * const halfH= ((uint8_t*)half) + 256;\
2508     uint8_t * const halfHV= ((uint8_t*)half);\
2509     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2510     put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
2511     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
2512     OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
2513 }\
2514 static void OPNAME ## qpel16_mc33_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2515     uint64_t half[16*2 + 17*2];\
2516     uint8_t * const halfH= ((uint8_t*)half) + 256;\
2517     uint8_t * const halfHV= ((uint8_t*)half);\
2518     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2519     put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
2520     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
2521     OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
2522 }\
2523 static void OPNAME ## qpel16_mc21_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2524     uint64_t half[16*2 + 17*2];\
2525     uint8_t * const halfH= ((uint8_t*)half) + 256;\
2526     uint8_t * const halfHV= ((uint8_t*)half);\
2527     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2528     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
2529     OPNAME ## pixels16_l2_ ## MMX(dst, halfH, halfHV, stride, 16, 16);\
2530 }\
2531 static void OPNAME ## qpel16_mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2532     uint64_t half[16*2 + 17*2];\
2533     uint8_t * const halfH= ((uint8_t*)half) + 256;\
2534     uint8_t * const halfHV= ((uint8_t*)half);\
2535     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2536     put ## RND ## mpeg4_qpel16_v_lowpass_ ## MMX(halfHV, halfH, 16, 16);\
2537     OPNAME ## pixels16_l2_ ## MMX(dst, halfH+16, halfHV, stride, 16, 16);\
2538 }\
2539 static void OPNAME ## qpel16_mc12_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2540     uint64_t half[17*2];\
2541     uint8_t * const halfH= ((uint8_t*)half);\
2542     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2543     put ## RND ## pixels16_l2_ ## MMX(halfH, src, halfH, 16, stride, 17);\
2544     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
2545 }\
2546 static void OPNAME ## qpel16_mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2547     uint64_t half[17*2];\
2548     uint8_t * const halfH= ((uint8_t*)half);\
2549     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2550     put ## RND ## pixels16_l2_ ## MMX(halfH, src+1, halfH, 16, stride, 17);\
2551     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
2552 }\
2553 static void OPNAME ## qpel16_mc22_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2554     uint64_t half[17*2];\
2555     uint8_t * const halfH= ((uint8_t*)half);\
2556     put ## RND ## mpeg4_qpel16_h_lowpass_ ## MMX(halfH, src, 16, stride, 17);\
2557     OPNAME ## mpeg4_qpel16_v_lowpass_ ## MMX(dst, halfH, stride, 16);\
2558 }
2559
2560 #define PUT_OP(a,b,temp, size) "mov" #size " " #a ", " #b "        \n\t"
2561 #define AVG_3DNOW_OP(a,b,temp, size) \
2562 "mov" #size " " #b ", " #temp "   \n\t"\
2563 "pavgusb " #temp ", " #a "        \n\t"\
2564 "mov" #size " " #a ", " #b "      \n\t"
2565 #define AVG_MMX2_OP(a,b,temp, size) \
2566 "mov" #size " " #b ", " #temp "   \n\t"\
2567 "pavgb " #temp ", " #a "          \n\t"\
2568 "mov" #size " " #a ", " #b "      \n\t"
2569
2570 QPEL_BASE(put_       , ff_pw_16, _       , PUT_OP, PUT_OP)
2571 QPEL_BASE(avg_       , ff_pw_16, _       , AVG_MMX2_OP, AVG_3DNOW_OP)
2572 QPEL_BASE(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, PUT_OP)
2573 QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, 3dnow)
2574 QPEL_OP(avg_       , ff_pw_16, _       , AVG_3DNOW_OP, 3dnow)
2575 QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, 3dnow)
2576 QPEL_OP(put_       , ff_pw_16, _       , PUT_OP, mmx2)
2577 QPEL_OP(avg_       , ff_pw_16, _       , AVG_MMX2_OP, mmx2)
2578 QPEL_OP(put_no_rnd_, ff_pw_15, _no_rnd_, PUT_OP, mmx2)
2579
2580 /***********************************/
2581 /* bilinear qpel: not compliant to any spec, only for -lavdopts fast */
2582
2583 #define QPEL_2TAP_XY(OPNAME, SIZE, MMX, XY, HPEL)\
2584 static void OPNAME ## 2tap_qpel ## SIZE ## _mc ## XY ## _ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2585     OPNAME ## pixels ## SIZE ## HPEL(dst, src, stride, SIZE);\
2586 }
2587 #define QPEL_2TAP_L3(OPNAME, SIZE, MMX, XY, S0, S1, S2)\
2588 static void OPNAME ## 2tap_qpel ## SIZE ## _mc ## XY ## _ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2589     OPNAME ## 2tap_qpel ## SIZE ## _l3_ ## MMX(dst, src+S0, stride, SIZE, S1, S2);\
2590 }
2591
2592 #define QPEL_2TAP(OPNAME, SIZE, MMX)\
2593 QPEL_2TAP_XY(OPNAME, SIZE, MMX, 20, _x2_ ## MMX)\
2594 QPEL_2TAP_XY(OPNAME, SIZE, MMX, 02, _y2_ ## MMX)\
2595 QPEL_2TAP_XY(OPNAME, SIZE, MMX, 22, _xy2_mmx)\
2596 static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc00_ ## MMX =\
2597                           OPNAME ## qpel ## SIZE ## _mc00_ ## MMX;\
2598 static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc21_ ## MMX =\
2599                           OPNAME ## 2tap_qpel ## SIZE ## _mc20_ ## MMX;\
2600 static const qpel_mc_func OPNAME ## 2tap_qpel ## SIZE ## _mc12_ ## MMX =\
2601                           OPNAME ## 2tap_qpel ## SIZE ## _mc02_ ## MMX;\
2602 static void OPNAME ## 2tap_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2603     OPNAME ## pixels ## SIZE ## _y2_ ## MMX(dst, src+1, stride, SIZE);\
2604 }\
2605 static void OPNAME ## 2tap_qpel ## SIZE ## _mc23_ ## MMX(uint8_t *dst, uint8_t *src, int stride){\
2606     OPNAME ## pixels ## SIZE ## _x2_ ## MMX(dst, src+stride, stride, SIZE);\
2607 }\
2608 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 10, 0,         1,       0)\
2609 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 30, 1,        -1,       0)\
2610 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 01, 0,         stride,  0)\
2611 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 03, stride,   -stride,  0)\
2612 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 11, 0,         stride,  1)\
2613 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 31, 1,         stride, -1)\
2614 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 13, stride,   -stride,  1)\
2615 QPEL_2TAP_L3(OPNAME, SIZE, MMX, 33, stride+1, -stride, -1)\
2616
2617 QPEL_2TAP(put_, 16, mmx2)
2618 QPEL_2TAP(avg_, 16, mmx2)
2619 QPEL_2TAP(put_,  8, mmx2)
2620 QPEL_2TAP(avg_,  8, mmx2)
2621 QPEL_2TAP(put_, 16, 3dnow)
2622 QPEL_2TAP(avg_, 16, 3dnow)
2623 QPEL_2TAP(put_,  8, 3dnow)
2624 QPEL_2TAP(avg_,  8, 3dnow)
2625
2626
2627 #if 0
2628 static void just_return() { return; }
2629 #endif
2630
2631 #define SET_QPEL_FUNC(postfix1, postfix2) \
2632     c->put_ ## postfix1 = put_ ## postfix2;\
2633     c->put_no_rnd_ ## postfix1 = put_no_rnd_ ## postfix2;\
2634     c->avg_ ## postfix1 = avg_ ## postfix2;
2635
2636 static void gmc_mmx(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int oy,
2637                     int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height){
2638     const int w = 8;
2639     const int ix = ox>>(16+shift);
2640     const int iy = oy>>(16+shift);
2641     const int oxs = ox>>4;
2642     const int oys = oy>>4;
2643     const int dxxs = dxx>>4;
2644     const int dxys = dxy>>4;
2645     const int dyxs = dyx>>4;
2646     const int dyys = dyy>>4;
2647     const uint16_t r4[4] = {r,r,r,r};
2648     const uint16_t dxy4[4] = {dxys,dxys,dxys,dxys};
2649     const uint16_t dyy4[4] = {dyys,dyys,dyys,dyys};
2650     const uint64_t shift2 = 2*shift;
2651     uint8_t edge_buf[(h+1)*stride];
2652     int x, y;
2653
2654     const int dxw = (dxx-(1<<(16+shift)))*(w-1);
2655     const int dyh = (dyy-(1<<(16+shift)))*(h-1);
2656     const int dxh = dxy*(h-1);
2657     const int dyw = dyx*(w-1);
2658     if( // non-constant fullpel offset (3% of blocks)
2659         (ox^(ox+dxw) | ox^(ox+dxh) | ox^(ox+dxw+dxh) |
2660          oy^(oy+dyw) | oy^(oy+dyh) | oy^(oy+dyw+dyh)) >> (16+shift)
2661         // uses more than 16 bits of subpel mv (only at huge resolution)
2662         || (dxx|dxy|dyx|dyy)&15 )
2663     {
2664         //FIXME could still use mmx for some of the rows
2665         ff_gmc_c(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r, width, height);
2666         return;
2667     }
2668
2669     src += ix + iy*stride;
2670     if( (unsigned)ix >= width-w ||
2671         (unsigned)iy >= height-h )
2672     {
2673         ff_emulated_edge_mc(edge_buf, src, stride, w+1, h+1, ix, iy, width, height);
2674         src = edge_buf;
2675     }
2676
2677     asm volatile(
2678         "movd         %0, %%mm6 \n\t"
2679         "pxor      %%mm7, %%mm7 \n\t"
2680         "punpcklwd %%mm6, %%mm6 \n\t"
2681         "punpcklwd %%mm6, %%mm6 \n\t"
2682         :: "r"(1<<shift)
2683     );
2684
2685     for(x=0; x<w; x+=4){
2686         uint16_t dx4[4] = { oxs - dxys + dxxs*(x+0),
2687                             oxs - dxys + dxxs*(x+1),
2688                             oxs - dxys + dxxs*(x+2),
2689                             oxs - dxys + dxxs*(x+3) };
2690         uint16_t dy4[4] = { oys - dyys + dyxs*(x+0),
2691                             oys - dyys + dyxs*(x+1),
2692                             oys - dyys + dyxs*(x+2),
2693                             oys - dyys + dyxs*(x+3) };
2694
2695         for(y=0; y<h; y++){
2696             asm volatile(
2697                 "movq   %0,  %%mm4 \n\t"
2698                 "movq   %1,  %%mm5 \n\t"
2699                 "paddw  %2,  %%mm4 \n\t"
2700                 "paddw  %3,  %%mm5 \n\t"
2701                 "movq   %%mm4, %0  \n\t"
2702                 "movq   %%mm5, %1  \n\t"
2703                 "psrlw  $12, %%mm4 \n\t"
2704                 "psrlw  $12, %%mm5 \n\t"
2705                 : "+m"(*dx4), "+m"(*dy4)
2706                 : "m"(*dxy4), "m"(*dyy4)
2707             );
2708
2709             asm volatile(
2710                 "movq   %%mm6, %%mm2 \n\t"
2711                 "movq   %%mm6, %%mm1 \n\t"
2712                 "psubw  %%mm4, %%mm2 \n\t"
2713                 "psubw  %%mm5, %%mm1 \n\t"
2714                 "movq   %%mm2, %%mm0 \n\t"
2715                 "movq   %%mm4, %%mm3 \n\t"
2716                 "pmullw %%mm1, %%mm0 \n\t" // (s-dx)*(s-dy)
2717                 "pmullw %%mm5, %%mm3 \n\t" // dx*dy
2718                 "pmullw %%mm5, %%mm2 \n\t" // (s-dx)*dy
2719                 "pmullw %%mm4, %%mm1 \n\t" // dx*(s-dy)
2720
2721                 "movd   %4,    %%mm5 \n\t"
2722                 "movd   %3,    %%mm4 \n\t"
2723                 "punpcklbw %%mm7, %%mm5 \n\t"
2724                 "punpcklbw %%mm7, %%mm4 \n\t"
2725                 "pmullw %%mm5, %%mm3 \n\t" // src[1,1] * dx*dy
2726                 "pmullw %%mm4, %%mm2 \n\t" // src[0,1] * (s-dx)*dy
2727
2728                 "movd   %2,    %%mm5 \n\t"
2729                 "movd   %1,    %%mm4 \n\t"
2730                 "punpcklbw %%mm7, %%mm5 \n\t"
2731                 "punpcklbw %%mm7, %%mm4 \n\t"
2732                 "pmullw %%mm5, %%mm1 \n\t" // src[1,0] * dx*(s-dy)
2733                 "pmullw %%mm4, %%mm0 \n\t" // src[0,0] * (s-dx)*(s-dy)
2734                 "paddw  %5,    %%mm1 \n\t"
2735                 "paddw  %%mm3, %%mm2 \n\t"
2736                 "paddw  %%mm1, %%mm0 \n\t"
2737                 "paddw  %%mm2, %%mm0 \n\t"
2738
2739                 "psrlw    %6,    %%mm0 \n\t"
2740                 "packuswb %%mm0, %%mm0 \n\t"
2741                 "movd     %%mm0, %0    \n\t"
2742
2743                 : "=m"(dst[x+y*stride])
2744                 : "m"(src[0]), "m"(src[1]),
2745                   "m"(src[stride]), "m"(src[stride+1]),
2746                   "m"(*r4), "m"(shift2)
2747             );
2748             src += stride;
2749         }
2750         src += 4-h*stride;
2751     }
2752 }
2753
2754 #ifdef CONFIG_ENCODERS
2755 static int try_8x8basis_mmx(int16_t rem[64], int16_t weight[64], int16_t basis[64], int scale){
2756     long i=0;
2757
2758     assert(FFABS(scale) < 256);
2759     scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
2760
2761     asm volatile(
2762         "pcmpeqw %%mm6, %%mm6           \n\t" // -1w
2763         "psrlw $15, %%mm6               \n\t" //  1w
2764         "pxor %%mm7, %%mm7              \n\t"
2765         "movd  %4, %%mm5                \n\t"
2766         "punpcklwd %%mm5, %%mm5         \n\t"
2767         "punpcklwd %%mm5, %%mm5         \n\t"
2768         "1:                             \n\t"
2769         "movq  (%1, %0), %%mm0          \n\t"
2770         "movq  8(%1, %0), %%mm1         \n\t"
2771         "pmulhw %%mm5, %%mm0            \n\t"
2772         "pmulhw %%mm5, %%mm1            \n\t"
2773         "paddw %%mm6, %%mm0             \n\t"
2774         "paddw %%mm6, %%mm1             \n\t"
2775         "psraw $1, %%mm0                \n\t"
2776         "psraw $1, %%mm1                \n\t"
2777         "paddw (%2, %0), %%mm0          \n\t"
2778         "paddw 8(%2, %0), %%mm1         \n\t"
2779         "psraw $6, %%mm0                \n\t"
2780         "psraw $6, %%mm1                \n\t"
2781         "pmullw (%3, %0), %%mm0         \n\t"
2782         "pmullw 8(%3, %0), %%mm1        \n\t"
2783         "pmaddwd %%mm0, %%mm0           \n\t"
2784         "pmaddwd %%mm1, %%mm1           \n\t"
2785         "paddd %%mm1, %%mm0             \n\t"
2786         "psrld $4, %%mm0                \n\t"
2787         "paddd %%mm0, %%mm7             \n\t"
2788         "add $16, %0                    \n\t"
2789         "cmp $128, %0                   \n\t" //FIXME optimize & bench
2790         " jb 1b                         \n\t"
2791         "movq %%mm7, %%mm6              \n\t"
2792         "psrlq $32, %%mm7               \n\t"
2793         "paddd %%mm6, %%mm7             \n\t"
2794         "psrld $2, %%mm7                \n\t"
2795         "movd %%mm7, %0                 \n\t"
2796
2797         : "+r" (i)
2798         : "r"(basis), "r"(rem), "r"(weight), "g"(scale)
2799     );
2800     return i;
2801 }
2802
2803 static void add_8x8basis_mmx(int16_t rem[64], int16_t basis[64], int scale){
2804     long i=0;
2805
2806     if(FFABS(scale) < 256){
2807         scale<<= 16 + 1 - BASIS_SHIFT + RECON_SHIFT;
2808         asm volatile(
2809                 "pcmpeqw %%mm6, %%mm6   \n\t" // -1w
2810                 "psrlw $15, %%mm6       \n\t" //  1w
2811                 "movd  %3, %%mm5        \n\t"
2812                 "punpcklwd %%mm5, %%mm5 \n\t"
2813                 "punpcklwd %%mm5, %%mm5 \n\t"
2814                 "1:                     \n\t"
2815                 "movq  (%1, %0), %%mm0  \n\t"
2816                 "movq  8(%1, %0), %%mm1 \n\t"
2817                 "pmulhw %%mm5, %%mm0    \n\t"
2818                 "pmulhw %%mm5, %%mm1    \n\t"
2819                 "paddw %%mm6, %%mm0     \n\t"
2820                 "paddw %%mm6, %%mm1     \n\t"
2821                 "psraw $1, %%mm0        \n\t"
2822                 "psraw $1, %%mm1        \n\t"
2823                 "paddw (%2, %0), %%mm0  \n\t"
2824                 "paddw 8(%2, %0), %%mm1 \n\t"
2825                 "movq %%mm0, (%2, %0)   \n\t"
2826                 "movq %%mm1, 8(%2, %0)  \n\t"
2827                 "add $16, %0            \n\t"
2828                 "cmp $128, %0           \n\t" //FIXME optimize & bench
2829                 " jb 1b                 \n\t"
2830
2831                 : "+r" (i)
2832                 : "r"(basis), "r"(rem), "g"(scale)
2833         );
2834     }else{
2835         for(i=0; i<8*8; i++){
2836             rem[i] += (basis[i]*scale + (1<<(BASIS_SHIFT - RECON_SHIFT-1)))>>(BASIS_SHIFT - RECON_SHIFT);
2837         }
2838     }
2839 }
2840 #endif /* CONFIG_ENCODERS */
2841
2842 #define PREFETCH(name, op) \
2843 static void name(void *mem, int stride, int h){\
2844     const uint8_t *p= mem;\
2845     do{\
2846         asm volatile(#op" %0" :: "m"(*p));\
2847         p+= stride;\
2848     }while(--h);\
2849 }
2850 PREFETCH(prefetch_mmx2,  prefetcht0)
2851 PREFETCH(prefetch_3dnow, prefetch)
2852 #undef PREFETCH
2853
2854 #include "h264dsp_mmx.c"
2855
2856 /* AVS specific */
2857 void ff_cavsdsp_init_mmx2(DSPContext* c, AVCodecContext *avctx);
2858
2859 void ff_put_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2860     put_pixels8_mmx(dst, src, stride, 8);
2861 }
2862 void ff_avg_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2863     avg_pixels8_mmx(dst, src, stride, 8);
2864 }
2865 void ff_put_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2866     put_pixels16_mmx(dst, src, stride, 16);
2867 }
2868 void ff_avg_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2869     avg_pixels16_mmx(dst, src, stride, 16);
2870 }
2871
2872 /* external functions, from idct_mmx.c */
2873 void ff_mmx_idct(DCTELEM *block);
2874 void ff_mmxext_idct(DCTELEM *block);
2875
2876 /* XXX: those functions should be suppressed ASAP when all IDCTs are
2877    converted */
2878 #ifdef CONFIG_GPL
2879 static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
2880 {
2881     ff_mmx_idct (block);
2882     put_pixels_clamped_mmx(block, dest, line_size);
2883 }
2884 static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
2885 {
2886     ff_mmx_idct (block);
2887     add_pixels_clamped_mmx(block, dest, line_size);
2888 }
2889 static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
2890 {
2891     ff_mmxext_idct (block);
2892     put_pixels_clamped_mmx(block, dest, line_size);
2893 }
2894 static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
2895 {
2896     ff_mmxext_idct (block);
2897     add_pixels_clamped_mmx(block, dest, line_size);
2898 }
2899 #endif
2900 static void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, DCTELEM *block)
2901 {
2902     ff_idct_xvid_mmx (block);
2903     put_pixels_clamped_mmx(block, dest, line_size);
2904 }
2905 static void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, DCTELEM *block)
2906 {
2907     ff_idct_xvid_mmx (block);
2908     add_pixels_clamped_mmx(block, dest, line_size);
2909 }
2910 static void ff_idct_xvid_mmx2_put(uint8_t *dest, int line_size, DCTELEM *block)
2911 {
2912     ff_idct_xvid_mmx2 (block);
2913     put_pixels_clamped_mmx(block, dest, line_size);
2914 }
2915 static void ff_idct_xvid_mmx2_add(uint8_t *dest, int line_size, DCTELEM *block)
2916 {
2917     ff_idct_xvid_mmx2 (block);
2918     add_pixels_clamped_mmx(block, dest, line_size);
2919 }
2920
2921 static void vorbis_inverse_coupling_3dnow(float *mag, float *ang, int blocksize)
2922 {
2923     int i;
2924     asm volatile("pxor %%mm7, %%mm7":);
2925     for(i=0; i<blocksize; i+=2) {
2926         asm volatile(
2927             "movq    %0,    %%mm0 \n\t"
2928             "movq    %1,    %%mm1 \n\t"
2929             "movq    %%mm0, %%mm2 \n\t"
2930             "movq    %%mm1, %%mm3 \n\t"
2931             "pfcmpge %%mm7, %%mm2 \n\t" // m <= 0.0
2932             "pfcmpge %%mm7, %%mm3 \n\t" // a <= 0.0
2933             "pslld   $31,   %%mm2 \n\t" // keep only the sign bit
2934             "pxor    %%mm2, %%mm1 \n\t"
2935             "movq    %%mm3, %%mm4 \n\t"
2936             "pand    %%mm1, %%mm3 \n\t"
2937             "pandn   %%mm1, %%mm4 \n\t"
2938             "pfadd   %%mm0, %%mm3 \n\t" // a = m + ((a<0) & (a ^ sign(m)))
2939             "pfsub   %%mm4, %%mm0 \n\t" // m = m + ((a>0) & (a ^ sign(m)))
2940             "movq    %%mm3, %1    \n\t"
2941             "movq    %%mm0, %0    \n\t"
2942             :"+m"(mag[i]), "+m"(ang[i])
2943             ::"memory"
2944         );
2945     }
2946     asm volatile("femms");
2947 }
2948 static void vorbis_inverse_coupling_sse(float *mag, float *ang, int blocksize)
2949 {
2950     int i;
2951
2952     asm volatile(
2953             "movaps  %0,     %%xmm5 \n\t"
2954         ::"m"(ff_pdw_80000000[0])
2955     );
2956     for(i=0; i<blocksize; i+=4) {
2957         asm volatile(
2958             "movaps  %0,     %%xmm0 \n\t"
2959             "movaps  %1,     %%xmm1 \n\t"
2960             "xorps   %%xmm2, %%xmm2 \n\t"
2961             "xorps   %%xmm3, %%xmm3 \n\t"
2962             "cmpleps %%xmm0, %%xmm2 \n\t" // m <= 0.0
2963             "cmpleps %%xmm1, %%xmm3 \n\t" // a <= 0.0
2964             "andps   %%xmm5, %%xmm2 \n\t" // keep only the sign bit
2965             "xorps   %%xmm2, %%xmm1 \n\t"
2966             "movaps  %%xmm3, %%xmm4 \n\t"
2967             "andps   %%xmm1, %%xmm3 \n\t"
2968             "andnps  %%xmm1, %%xmm4 \n\t"
2969             "addps   %%xmm0, %%xmm3 \n\t" // a = m + ((a<0) & (a ^ sign(m)))
2970             "subps   %%xmm4, %%xmm0 \n\t" // m = m + ((a>0) & (a ^ sign(m)))
2971             "movaps  %%xmm3, %1     \n\t"
2972             "movaps  %%xmm0, %0     \n\t"
2973             :"+m"(mag[i]), "+m"(ang[i])
2974             ::"memory"
2975         );
2976     }
2977 }
2978
2979 static void vector_fmul_3dnow(float *dst, const float *src, int len){
2980     long i = (len-4)*4;
2981     asm volatile(
2982         "1: \n\t"
2983         "movq    (%1,%0), %%mm0 \n\t"
2984         "movq   8(%1,%0), %%mm1 \n\t"
2985         "pfmul   (%2,%0), %%mm0 \n\t"
2986         "pfmul  8(%2,%0), %%mm1 \n\t"
2987         "movq   %%mm0,  (%1,%0) \n\t"
2988         "movq   %%mm1, 8(%1,%0) \n\t"
2989         "sub  $16, %0 \n\t"
2990         "jge 1b \n\t"
2991         "femms  \n\t"
2992         :"+r"(i)
2993         :"r"(dst), "r"(src)
2994         :"memory"
2995     );
2996 }
2997 static void vector_fmul_sse(float *dst, const float *src, int len){
2998     long i = (len-8)*4;
2999     asm volatile(
3000         "1: \n\t"
3001         "movaps    (%1,%0), %%xmm0 \n\t"
3002         "movaps  16(%1,%0), %%xmm1 \n\t"
3003         "mulps     (%2,%0), %%xmm0 \n\t"
3004         "mulps   16(%2,%0), %%xmm1 \n\t"
3005         "movaps  %%xmm0,   (%1,%0) \n\t"
3006         "movaps  %%xmm1, 16(%1,%0) \n\t"
3007         "sub  $32, %0 \n\t"
3008         "jge 1b \n\t"
3009         :"+r"(i)
3010         :"r"(dst), "r"(src)
3011         :"memory"
3012     );
3013 }
3014
3015 static void vector_fmul_reverse_3dnow2(float *dst, const float *src0, const float *src1, int len){
3016     long i = len*4-16;
3017     asm volatile(
3018         "1: \n\t"
3019         "pswapd   8(%1), %%mm0 \n\t"
3020         "pswapd    (%1), %%mm1 \n\t"
3021         "pfmul  (%3,%0), %%mm0 \n\t"
3022         "pfmul 8(%3,%0), %%mm1 \n\t"
3023         "movq  %%mm0,  (%2,%0) \n\t"
3024         "movq  %%mm1, 8(%2,%0) \n\t"
3025         "add   $16, %1 \n\t"
3026         "sub   $16, %0 \n\t"
3027         "jge   1b \n\t"
3028         :"+r"(i), "+r"(src1)
3029         :"r"(dst), "r"(src0)
3030     );
3031     asm volatile("femms");
3032 }
3033 static void vector_fmul_reverse_sse(float *dst, const float *src0, const float *src1, int len){
3034     long i = len*4-32;
3035     asm volatile(
3036         "1: \n\t"
3037         "movaps        16(%1), %%xmm0 \n\t"
3038         "movaps          (%1), %%xmm1 \n\t"
3039         "shufps $0x1b, %%xmm0, %%xmm0 \n\t"
3040         "shufps $0x1b, %%xmm1, %%xmm1 \n\t"
3041         "mulps        (%3,%0), %%xmm0 \n\t"
3042         "mulps      16(%3,%0), %%xmm1 \n\t"
3043         "movaps     %%xmm0,   (%2,%0) \n\t"
3044         "movaps     %%xmm1, 16(%2,%0) \n\t"
3045         "add    $32, %1 \n\t"
3046         "sub    $32, %0 \n\t"
3047         "jge    1b \n\t"
3048         :"+r"(i), "+r"(src1)
3049         :"r"(dst), "r"(src0)
3050     );
3051 }
3052
3053 static void vector_fmul_add_add_3dnow(float *dst, const float *src0, const float *src1,
3054                                       const float *src2, int src3, int len, int step){
3055     long i = (len-4)*4;
3056     if(step == 2 && src3 == 0){
3057         dst += (len-4)*2;
3058         asm volatile(
3059             "1: \n\t"
3060             "movq   (%2,%0),  %%mm0 \n\t"
3061             "movq  8(%2,%0),  %%mm1 \n\t"
3062             "pfmul  (%3,%0),  %%mm0 \n\t"
3063             "pfmul 8(%3,%0),  %%mm1 \n\t"
3064             "pfadd  (%4,%0),  %%mm0 \n\t"
3065             "pfadd 8(%4,%0),  %%mm1 \n\t"
3066             "movd     %%mm0,   (%1) \n\t"
3067             "movd     %%mm1, 16(%1) \n\t"
3068             "psrlq      $32,  %%mm0 \n\t"
3069             "psrlq      $32,  %%mm1 \n\t"
3070             "movd     %%mm0,  8(%1) \n\t"
3071             "movd     %%mm1, 24(%1) \n\t"
3072             "sub  $32, %1 \n\t"
3073             "sub  $16, %0 \n\t"
3074             "jge  1b \n\t"
3075             :"+r"(i), "+r"(dst)
3076             :"r"(src0), "r"(src1), "r"(src2)
3077             :"memory"
3078         );
3079     }
3080     else if(step == 1 && src3 == 0){
3081         asm volatile(
3082             "1: \n\t"
3083             "movq    (%2,%0), %%mm0 \n\t"
3084             "movq   8(%2,%0), %%mm1 \n\t"
3085             "pfmul   (%3,%0), %%mm0 \n\t"
3086             "pfmul  8(%3,%0), %%mm1 \n\t"
3087             "pfadd   (%4,%0), %%mm0 \n\t"
3088             "pfadd  8(%4,%0), %%mm1 \n\t"
3089             "movq  %%mm0,   (%1,%0) \n\t"
3090             "movq  %%mm1,  8(%1,%0) \n\t"
3091             "sub  $16, %0 \n\t"
3092             "jge  1b \n\t"
3093             :"+r"(i)
3094             :"r"(dst), "r"(src0), "r"(src1), "r"(src2)
3095             :"memory"
3096         );
3097     }
3098     else
3099         ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
3100     asm volatile("femms");
3101 }
3102 static void vector_fmul_add_add_sse(float *dst, const float *src0, const float *src1,
3103                                     const float *src2, int src3, int len, int step){
3104     long i = (len-8)*4;
3105     if(step == 2 && src3 == 0){
3106         dst += (len-8)*2;
3107         asm volatile(
3108             "1: \n\t"
3109             "movaps   (%2,%0), %%xmm0 \n\t"
3110             "movaps 16(%2,%0), %%xmm1 \n\t"
3111             "mulps    (%3,%0), %%xmm0 \n\t"
3112             "mulps  16(%3,%0), %%xmm1 \n\t"
3113             "addps    (%4,%0), %%xmm0 \n\t"
3114             "addps  16(%4,%0), %%xmm1 \n\t"
3115             "movss     %%xmm0,   (%1) \n\t"
3116             "movss     %%xmm1, 32(%1) \n\t"
3117             "movhlps   %%xmm0, %%xmm2 \n\t"
3118             "movhlps   %%xmm1, %%xmm3 \n\t"
3119             "movss     %%xmm2, 16(%1) \n\t"
3120             "movss     %%xmm3, 48(%1) \n\t"
3121             "shufps $0xb1, %%xmm0, %%xmm0 \n\t"
3122             "shufps $0xb1, %%xmm1, %%xmm1 \n\t"
3123             "movss     %%xmm0,  8(%1) \n\t"
3124             "movss     %%xmm1, 40(%1) \n\t"
3125             "movhlps   %%xmm0, %%xmm2 \n\t"
3126             "movhlps   %%xmm1, %%xmm3 \n\t"
3127             "movss     %%xmm2, 24(%1) \n\t"
3128             "movss     %%xmm3, 56(%1) \n\t"
3129             "sub  $64, %1 \n\t"
3130             "sub  $32, %0 \n\t"
3131             "jge  1b \n\t"
3132             :"+r"(i), "+r"(dst)
3133             :"r"(src0), "r"(src1), "r"(src2)
3134             :"memory"
3135         );
3136     }
3137     else if(step == 1 && src3 == 0){
3138         asm volatile(
3139             "1: \n\t"
3140             "movaps   (%2,%0), %%xmm0 \n\t"
3141             "movaps 16(%2,%0), %%xmm1 \n\t"
3142             "mulps    (%3,%0), %%xmm0 \n\t"
3143             "mulps  16(%3,%0), %%xmm1 \n\t"
3144             "addps    (%4,%0), %%xmm0 \n\t"
3145             "addps  16(%4,%0), %%xmm1 \n\t"
3146             "movaps %%xmm0,   (%1,%0) \n\t"
3147             "movaps %%xmm1, 16(%1,%0) \n\t"
3148             "sub  $32, %0 \n\t"
3149             "jge  1b \n\t"
3150             :"+r"(i)
3151             :"r"(dst), "r"(src0), "r"(src1), "r"(src2)
3152             :"memory"
3153         );
3154     }
3155     else
3156         ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
3157 }
3158
3159 static void float_to_int16_3dnow(int16_t *dst, const float *src, int len){
3160     // not bit-exact: pf2id uses different rounding than C and SSE
3161     int i;
3162     for(i=0; i<len; i+=4) {
3163         asm volatile(
3164             "pf2id       %1, %%mm0 \n\t"
3165             "pf2id       %2, %%mm1 \n\t"
3166             "packssdw %%mm1, %%mm0 \n\t"
3167             "movq     %%mm0, %0    \n\t"
3168             :"=m"(dst[i])
3169             :"m"(src[i]), "m"(src[i+2])
3170         );
3171     }
3172     asm volatile("femms");
3173 }
3174 static void float_to_int16_sse(int16_t *dst, const float *src, int len){
3175     int i;
3176     for(i=0; i<len; i+=4) {
3177         asm volatile(
3178             "cvtps2pi    %1, %%mm0 \n\t"
3179             "cvtps2pi    %2, %%mm1 \n\t"
3180             "packssdw %%mm1, %%mm0 \n\t"
3181             "movq     %%mm0, %0    \n\t"
3182             :"=m"(dst[i])
3183             :"m"(src[i]), "m"(src[i+2])
3184         );
3185     }
3186     asm volatile("emms");
3187 }
3188
3189 #ifdef CONFIG_SNOW_DECODER
3190 extern void ff_snow_horizontal_compose97i_sse2(DWTELEM *b, int width);
3191 extern void ff_snow_horizontal_compose97i_mmx(DWTELEM *b, int width);
3192 extern void ff_snow_vertical_compose97i_sse2(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
3193 extern void ff_snow_vertical_compose97i_mmx(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
3194 extern void ff_snow_inner_add_yblock_sse2(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h,
3195                            int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8);
3196 extern void ff_snow_inner_add_yblock_mmx(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h,
3197                           int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8);
3198 #endif
3199
3200 void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
3201 {
3202     mm_flags = mm_support();
3203
3204     if (avctx->dsp_mask) {
3205         if (avctx->dsp_mask & FF_MM_FORCE)
3206             mm_flags |= (avctx->dsp_mask & 0xffff);
3207         else
3208             mm_flags &= ~(avctx->dsp_mask & 0xffff);
3209     }
3210
3211 #if 0
3212     av_log(avctx, AV_LOG_INFO, "libavcodec: CPU flags:");
3213     if (mm_flags & MM_MMX)
3214         av_log(avctx, AV_LOG_INFO, " mmx");
3215     if (mm_flags & MM_MMXEXT)
3216         av_log(avctx, AV_LOG_INFO, " mmxext");
3217     if (mm_flags & MM_3DNOW)
3218         av_log(avctx, AV_LOG_INFO, " 3dnow");
3219     if (mm_flags & MM_SSE)
3220         av_log(avctx, AV_LOG_INFO, " sse");
3221     if (mm_flags & MM_SSE2)
3222         av_log(avctx, AV_LOG_INFO, " sse2");
3223     av_log(avctx, AV_LOG_INFO, "\n");
3224 #endif
3225
3226     if (mm_flags & MM_MMX) {
3227         const int idct_algo= avctx->idct_algo;
3228
3229 #ifdef CONFIG_ENCODERS
3230         const int dct_algo = avctx->dct_algo;
3231         if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
3232             if(mm_flags & MM_SSE2){
3233                 c->fdct = ff_fdct_sse2;
3234             }else if(mm_flags & MM_MMXEXT){
3235                 c->fdct = ff_fdct_mmx2;
3236             }else{
3237                 c->fdct = ff_fdct_mmx;
3238             }
3239         }
3240 #endif //CONFIG_ENCODERS
3241         if(avctx->lowres==0){
3242             if(idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SIMPLEMMX){
3243                 c->idct_put= ff_simple_idct_put_mmx;
3244                 c->idct_add= ff_simple_idct_add_mmx;
3245                 c->idct    = ff_simple_idct_mmx;
3246                 c->idct_permutation_type= FF_SIMPLE_IDCT_PERM;
3247 #ifdef CONFIG_GPL
3248             }else if(idct_algo==FF_IDCT_LIBMPEG2MMX){
3249                 if(mm_flags & MM_MMXEXT){
3250                     c->idct_put= ff_libmpeg2mmx2_idct_put;
3251                     c->idct_add= ff_libmpeg2mmx2_idct_add;
3252                     c->idct    = ff_mmxext_idct;
3253                 }else{
3254                     c->idct_put= ff_libmpeg2mmx_idct_put;
3255                     c->idct_add= ff_libmpeg2mmx_idct_add;
3256                     c->idct    = ff_mmx_idct;
3257                 }
3258                 c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
3259 #endif
3260             }else if((ENABLE_VP3_DECODER || ENABLE_VP5_DECODER || ENABLE_VP6_DECODER) &&
3261                      idct_algo==FF_IDCT_VP3 &&
3262                      avctx->codec->id!=CODEC_ID_THEORA &&
3263                      !(avctx->flags & CODEC_FLAG_BITEXACT)){
3264                 if(mm_flags & MM_SSE2){
3265                     c->idct_put= ff_vp3_idct_put_sse2;
3266                     c->idct_add= ff_vp3_idct_add_sse2;
3267                     c->idct    = ff_vp3_idct_sse2;
3268                     c->idct_permutation_type= FF_TRANSPOSE_IDCT_PERM;
3269                 }else{
3270                     ff_vp3_dsp_init_mmx();
3271                     c->idct_put= ff_vp3_idct_put_mmx;
3272                     c->idct_add= ff_vp3_idct_add_mmx;
3273                     c->idct    = ff_vp3_idct_mmx;
3274                     c->idct_permutation_type= FF_PARTTRANS_IDCT_PERM;
3275                 }
3276      &n