cosmetics: indentation
[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 #include "h263.h"
33
34 //#undef NDEBUG
35 //#include <assert.h>
36
37 extern void ff_idct_xvid_mmx(short *block);
38 extern void ff_idct_xvid_mmx2(short *block);
39
40 int mm_flags; /* multimedia extension flags */
41
42 /* pixel operations */
43 static const uint64_t mm_bone attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
44 static const uint64_t mm_wone attribute_used __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
45 static const uint64_t mm_wtwo attribute_used __attribute__ ((aligned(8))) = 0x0002000200020002ULL;
46
47 static const uint64_t ff_pdw_80000000[2] attribute_used __attribute__ ((aligned(16))) =
48 {0x8000000080000000ULL, 0x8000000080000000ULL};
49
50 static const uint64_t ff_pw_20 attribute_used __attribute__ ((aligned(8))) = 0x0014001400140014ULL;
51 static const uint64_t ff_pw_3  attribute_used __attribute__ ((aligned(8))) = 0x0003000300030003ULL;
52 static const uint64_t ff_pw_4  attribute_used __attribute__ ((aligned(8))) = 0x0004000400040004ULL;
53 static const uint64_t ff_pw_5  attribute_used __attribute__ ((aligned(8))) = 0x0005000500050005ULL;
54 static const uint64_t ff_pw_8  attribute_used __attribute__ ((aligned(8))) = 0x0008000800080008ULL;
55 static const uint64_t ff_pw_16 attribute_used __attribute__ ((aligned(8))) = 0x0010001000100010ULL;
56 static const uint64_t ff_pw_32 attribute_used __attribute__ ((aligned(8))) = 0x0020002000200020ULL;
57 static const uint64_t ff_pw_64 attribute_used __attribute__ ((aligned(8))) = 0x0040004000400040ULL;
58 static const uint64_t ff_pw_15 attribute_used __attribute__ ((aligned(8))) = 0x000F000F000F000FULL;
59
60 static const uint64_t ff_pb_1  attribute_used __attribute__ ((aligned(8))) = 0x0101010101010101ULL;
61 static const uint64_t ff_pb_3  attribute_used __attribute__ ((aligned(8))) = 0x0303030303030303ULL;
62 static const uint64_t ff_pb_7  attribute_used __attribute__ ((aligned(8))) = 0x0707070707070707ULL;
63 static const uint64_t ff_pb_3F attribute_used __attribute__ ((aligned(8))) = 0x3F3F3F3F3F3F3F3FULL;
64 static const uint64_t ff_pb_A1 attribute_used __attribute__ ((aligned(8))) = 0xA1A1A1A1A1A1A1A1ULL;
65 static const uint64_t ff_pb_5F attribute_used __attribute__ ((aligned(8))) = 0x5F5F5F5F5F5F5F5FULL;
66 static const uint64_t ff_pb_FC attribute_used __attribute__ ((aligned(8))) = 0xFCFCFCFCFCFCFCFCULL;
67
68 #define JUMPALIGN() __asm __volatile (ASMALIGN(3)::)
69 #define MOVQ_ZERO(regd)  __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
70
71 #define MOVQ_WONE(regd) \
72     __asm __volatile ( \
73     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
74     "psrlw $15, %%" #regd ::)
75
76 #define MOVQ_BFE(regd) \
77     __asm __volatile ( \
78     "pcmpeqd %%" #regd ", %%" #regd " \n\t"\
79     "paddb %%" #regd ", %%" #regd " \n\t" ::)
80
81 #ifndef PIC
82 #define MOVQ_BONE(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_bone))
83 #define MOVQ_WTWO(regd)  __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_wtwo))
84 #else
85 // for shared library it's better to use this way for accessing constants
86 // pcmpeqd -> -1
87 #define MOVQ_BONE(regd) \
88     __asm __volatile ( \
89     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
90     "psrlw $15, %%" #regd " \n\t" \
91     "packuswb %%" #regd ", %%" #regd " \n\t" ::)
92
93 #define MOVQ_WTWO(regd) \
94     __asm __volatile ( \
95     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
96     "psrlw $15, %%" #regd " \n\t" \
97     "psllw $1, %%" #regd " \n\t"::)
98
99 #endif
100
101 // using regr as temporary and for the output result
102 // first argument is unmodifed and second is trashed
103 // regfe is supposed to contain 0xfefefefefefefefe
104 #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe) \
105     "movq " #rega ", " #regr "  \n\t"\
106     "pand " #regb ", " #regr "  \n\t"\
107     "pxor " #rega ", " #regb "  \n\t"\
108     "pand " #regfe "," #regb "  \n\t"\
109     "psrlq $1, " #regb "        \n\t"\
110     "paddb " #regb ", " #regr " \n\t"
111
112 #define PAVGB_MMX(rega, regb, regr, regfe) \
113     "movq " #rega ", " #regr "  \n\t"\
114     "por  " #regb ", " #regr "  \n\t"\
115     "pxor " #rega ", " #regb "  \n\t"\
116     "pand " #regfe "," #regb "  \n\t"\
117     "psrlq $1, " #regb "        \n\t"\
118     "psubb " #regb ", " #regr " \n\t"
119
120 // mm6 is supposed to contain 0xfefefefefefefefe
121 #define PAVGBP_MMX_NO_RND(rega, regb, regr,  regc, regd, regp) \
122     "movq " #rega ", " #regr "  \n\t"\
123     "movq " #regc ", " #regp "  \n\t"\
124     "pand " #regb ", " #regr "  \n\t"\
125     "pand " #regd ", " #regp "  \n\t"\
126     "pxor " #rega ", " #regb "  \n\t"\
127     "pxor " #regc ", " #regd "  \n\t"\
128     "pand %%mm6, " #regb "      \n\t"\
129     "pand %%mm6, " #regd "      \n\t"\
130     "psrlq $1, " #regb "        \n\t"\
131     "psrlq $1, " #regd "        \n\t"\
132     "paddb " #regb ", " #regr " \n\t"\
133     "paddb " #regd ", " #regp " \n\t"
134
135 #define PAVGBP_MMX(rega, regb, regr, regc, regd, regp) \
136     "movq " #rega ", " #regr "  \n\t"\
137     "movq " #regc ", " #regp "  \n\t"\
138     "por  " #regb ", " #regr "  \n\t"\
139     "por  " #regd ", " #regp "  \n\t"\
140     "pxor " #rega ", " #regb "  \n\t"\
141     "pxor " #regc ", " #regd "  \n\t"\
142     "pand %%mm6, " #regb "      \n\t"\
143     "pand %%mm6, " #regd "      \n\t"\
144     "psrlq $1, " #regd "        \n\t"\
145     "psrlq $1, " #regb "        \n\t"\
146     "psubb " #regb ", " #regr " \n\t"\
147     "psubb " #regd ", " #regp " \n\t"
148
149 /***********************************/
150 /* MMX no rounding */
151 #define DEF(x, y) x ## _no_rnd_ ## y ##_mmx
152 #define SET_RND  MOVQ_WONE
153 #define PAVGBP(a, b, c, d, e, f)        PAVGBP_MMX_NO_RND(a, b, c, d, e, f)
154 #define PAVGB(a, b, c, e)               PAVGB_MMX_NO_RND(a, b, c, e)
155
156 #include "dsputil_mmx_rnd.h"
157
158 #undef DEF
159 #undef SET_RND
160 #undef PAVGBP
161 #undef PAVGB
162 /***********************************/
163 /* MMX rounding */
164
165 #define DEF(x, y) x ## _ ## y ##_mmx
166 #define SET_RND  MOVQ_WTWO
167 #define PAVGBP(a, b, c, d, e, f)        PAVGBP_MMX(a, b, c, d, e, f)
168 #define PAVGB(a, b, c, e)               PAVGB_MMX(a, b, c, e)
169
170 #include "dsputil_mmx_rnd.h"
171
172 #undef DEF
173 #undef SET_RND
174 #undef PAVGBP
175 #undef PAVGB
176
177 /***********************************/
178 /* 3Dnow specific */
179
180 #define DEF(x) x ## _3dnow
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(const int8_t *pix1, const 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
2756 #define PHADDD(a, t)\
2757     "movq "#a", "#t"                  \n\t"\
2758     "psrlq $32, "#a"                  \n\t"\
2759     "paddd "#t", "#a"                 \n\t"
2760 /*
2761    pmulhw: dst[0-15]=(src[0-15]*dst[0-15])[16-31]
2762    pmulhrw: dst[0-15]=(src[0-15]*dst[0-15] + 0x8000)[16-31]
2763    pmulhrsw: dst[0-15]=(src[0-15]*dst[0-15] + 0x4000)[15-30]
2764  */
2765 #define PMULHRW(x, y, s, o)\
2766     "pmulhw " #s ", "#x "            \n\t"\
2767     "pmulhw " #s ", "#y "            \n\t"\
2768     "paddw " #o ", "#x "             \n\t"\
2769     "paddw " #o ", "#y "             \n\t"\
2770     "psraw $1, "#x "                 \n\t"\
2771     "psraw $1, "#y "                 \n\t"
2772 #define DEF(x) x ## _mmx
2773 #define SET_RND MOVQ_WONE
2774 #define SCALE_OFFSET 1
2775
2776 #include "dsputil_mmx_qns.h"
2777
2778 #undef DEF
2779 #undef SET_RND
2780 #undef SCALE_OFFSET
2781 #undef PMULHRW
2782
2783 #define DEF(x) x ## _3dnow
2784 #define SET_RND(x)
2785 #define SCALE_OFFSET 0
2786 #define PMULHRW(x, y, s, o)\
2787     "pmulhrw " #s ", "#x "           \n\t"\
2788     "pmulhrw " #s ", "#y "           \n\t"
2789
2790 #include "dsputil_mmx_qns.h"
2791
2792 #undef DEF
2793 #undef SET_RND
2794 #undef SCALE_OFFSET
2795 #undef PMULHRW
2796
2797 #ifdef HAVE_SSSE3
2798 #undef PHADDD
2799 #define DEF(x) x ## _ssse3
2800 #define SET_RND(x)
2801 #define SCALE_OFFSET -1
2802 #define PHADDD(a, t)\
2803     "pshufw $0x0E, "#a", "#t"         \n\t"\
2804     "paddd "#t", "#a"                 \n\t" /* faster than phaddd on core2 */
2805 #define PMULHRW(x, y, s, o)\
2806     "pmulhrsw " #s ", "#x "          \n\t"\
2807     "pmulhrsw " #s ", "#y "          \n\t"
2808
2809 #include "dsputil_mmx_qns.h"
2810
2811 #undef DEF
2812 #undef SET_RND
2813 #undef SCALE_OFFSET
2814 #undef PMULHRW
2815 #undef PHADDD
2816 #endif //HAVE_SSSE3
2817
2818 #endif /* CONFIG_ENCODERS */
2819
2820 #define PREFETCH(name, op) \
2821 static void name(void *mem, int stride, int h){\
2822     const uint8_t *p= mem;\
2823     do{\
2824         asm volatile(#op" %0" :: "m"(*p));\
2825         p+= stride;\
2826     }while(--h);\
2827 }
2828 PREFETCH(prefetch_mmx2,  prefetcht0)
2829 PREFETCH(prefetch_3dnow, prefetch)
2830 #undef PREFETCH
2831
2832 #include "h264dsp_mmx.c"
2833
2834 /* AVS specific */
2835 void ff_cavsdsp_init_mmx2(DSPContext* c, AVCodecContext *avctx);
2836
2837 void ff_put_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2838     put_pixels8_mmx(dst, src, stride, 8);
2839 }
2840 void ff_avg_cavs_qpel8_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2841     avg_pixels8_mmx(dst, src, stride, 8);
2842 }
2843 void ff_put_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2844     put_pixels16_mmx(dst, src, stride, 16);
2845 }
2846 void ff_avg_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride) {
2847     avg_pixels16_mmx(dst, src, stride, 16);
2848 }
2849
2850 /* external functions, from idct_mmx.c */
2851 void ff_mmx_idct(DCTELEM *block);
2852 void ff_mmxext_idct(DCTELEM *block);
2853
2854 /* XXX: those functions should be suppressed ASAP when all IDCTs are
2855    converted */
2856 #ifdef CONFIG_GPL
2857 static void ff_libmpeg2mmx_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
2858 {
2859     ff_mmx_idct (block);
2860     put_pixels_clamped_mmx(block, dest, line_size);
2861 }
2862 static void ff_libmpeg2mmx_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
2863 {
2864     ff_mmx_idct (block);
2865     add_pixels_clamped_mmx(block, dest, line_size);
2866 }
2867 static void ff_libmpeg2mmx2_idct_put(uint8_t *dest, int line_size, DCTELEM *block)
2868 {
2869     ff_mmxext_idct (block);
2870     put_pixels_clamped_mmx(block, dest, line_size);
2871 }
2872 static void ff_libmpeg2mmx2_idct_add(uint8_t *dest, int line_size, DCTELEM *block)
2873 {
2874     ff_mmxext_idct (block);
2875     add_pixels_clamped_mmx(block, dest, line_size);
2876 }
2877 #endif
2878 static void ff_idct_xvid_mmx_put(uint8_t *dest, int line_size, DCTELEM *block)
2879 {
2880     ff_idct_xvid_mmx (block);
2881     put_pixels_clamped_mmx(block, dest, line_size);
2882 }
2883 static void ff_idct_xvid_mmx_add(uint8_t *dest, int line_size, DCTELEM *block)
2884 {
2885     ff_idct_xvid_mmx (block);
2886     add_pixels_clamped_mmx(block, dest, line_size);
2887 }
2888 static void ff_idct_xvid_mmx2_put(uint8_t *dest, int line_size, DCTELEM *block)
2889 {
2890     ff_idct_xvid_mmx2 (block);
2891     put_pixels_clamped_mmx(block, dest, line_size);
2892 }
2893 static void ff_idct_xvid_mmx2_add(uint8_t *dest, int line_size, DCTELEM *block)
2894 {
2895     ff_idct_xvid_mmx2 (block);
2896     add_pixels_clamped_mmx(block, dest, line_size);
2897 }
2898
2899 static void vorbis_inverse_coupling_3dnow(float *mag, float *ang, int blocksize)
2900 {
2901     int i;
2902     asm volatile("pxor %%mm7, %%mm7":);
2903     for(i=0; i<blocksize; i+=2) {
2904         asm volatile(
2905             "movq    %0,    %%mm0 \n\t"
2906             "movq    %1,    %%mm1 \n\t"
2907             "movq    %%mm0, %%mm2 \n\t"
2908             "movq    %%mm1, %%mm3 \n\t"
2909             "pfcmpge %%mm7, %%mm2 \n\t" // m <= 0.0
2910             "pfcmpge %%mm7, %%mm3 \n\t" // a <= 0.0
2911             "pslld   $31,   %%mm2 \n\t" // keep only the sign bit
2912             "pxor    %%mm2, %%mm1 \n\t"
2913             "movq    %%mm3, %%mm4 \n\t"
2914             "pand    %%mm1, %%mm3 \n\t"
2915             "pandn   %%mm1, %%mm4 \n\t"
2916             "pfadd   %%mm0, %%mm3 \n\t" // a = m + ((a<0) & (a ^ sign(m)))
2917             "pfsub   %%mm4, %%mm0 \n\t" // m = m + ((a>0) & (a ^ sign(m)))
2918             "movq    %%mm3, %1    \n\t"
2919             "movq    %%mm0, %0    \n\t"
2920             :"+m"(mag[i]), "+m"(ang[i])
2921             ::"memory"
2922         );
2923     }
2924     asm volatile("femms");
2925 }
2926 static void vorbis_inverse_coupling_sse(float *mag, float *ang, int blocksize)
2927 {
2928     int i;
2929
2930     asm volatile(
2931             "movaps  %0,     %%xmm5 \n\t"
2932         ::"m"(ff_pdw_80000000[0])
2933     );
2934     for(i=0; i<blocksize; i+=4) {
2935         asm volatile(
2936             "movaps  %0,     %%xmm0 \n\t"
2937             "movaps  %1,     %%xmm1 \n\t"
2938             "xorps   %%xmm2, %%xmm2 \n\t"
2939             "xorps   %%xmm3, %%xmm3 \n\t"
2940             "cmpleps %%xmm0, %%xmm2 \n\t" // m <= 0.0
2941             "cmpleps %%xmm1, %%xmm3 \n\t" // a <= 0.0
2942             "andps   %%xmm5, %%xmm2 \n\t" // keep only the sign bit
2943             "xorps   %%xmm2, %%xmm1 \n\t"
2944             "movaps  %%xmm3, %%xmm4 \n\t"
2945             "andps   %%xmm1, %%xmm3 \n\t"
2946             "andnps  %%xmm1, %%xmm4 \n\t"
2947             "addps   %%xmm0, %%xmm3 \n\t" // a = m + ((a<0) & (a ^ sign(m)))
2948             "subps   %%xmm4, %%xmm0 \n\t" // m = m + ((a>0) & (a ^ sign(m)))
2949             "movaps  %%xmm3, %1     \n\t"
2950             "movaps  %%xmm0, %0     \n\t"
2951             :"+m"(mag[i]), "+m"(ang[i])
2952             ::"memory"
2953         );
2954     }
2955 }
2956
2957 static void vector_fmul_3dnow(float *dst, const float *src, int len){
2958     long i = (len-4)*4;
2959     asm volatile(
2960         "1: \n\t"
2961         "movq    (%1,%0), %%mm0 \n\t"
2962         "movq   8(%1,%0), %%mm1 \n\t"
2963         "pfmul   (%2,%0), %%mm0 \n\t"
2964         "pfmul  8(%2,%0), %%mm1 \n\t"
2965         "movq   %%mm0,  (%1,%0) \n\t"
2966         "movq   %%mm1, 8(%1,%0) \n\t"
2967         "sub  $16, %0 \n\t"
2968         "jge 1b \n\t"
2969         "femms  \n\t"
2970         :"+r"(i)
2971         :"r"(dst), "r"(src)
2972         :"memory"
2973     );
2974 }
2975 static void vector_fmul_sse(float *dst, const float *src, int len){
2976     long i = (len-8)*4;
2977     asm volatile(
2978         "1: \n\t"
2979         "movaps    (%1,%0), %%xmm0 \n\t"
2980         "movaps  16(%1,%0), %%xmm1 \n\t"
2981         "mulps     (%2,%0), %%xmm0 \n\t"
2982         "mulps   16(%2,%0), %%xmm1 \n\t"
2983         "movaps  %%xmm0,   (%1,%0) \n\t"
2984         "movaps  %%xmm1, 16(%1,%0) \n\t"
2985         "sub  $32, %0 \n\t"
2986         "jge 1b \n\t"
2987         :"+r"(i)
2988         :"r"(dst), "r"(src)
2989         :"memory"
2990     );
2991 }
2992
2993 static void vector_fmul_reverse_3dnow2(float *dst, const float *src0, const float *src1, int len){
2994     long i = len*4-16;
2995     asm volatile(
2996         "1: \n\t"
2997         "pswapd   8(%1), %%mm0 \n\t"
2998         "pswapd    (%1), %%mm1 \n\t"
2999         "pfmul  (%3,%0), %%mm0 \n\t"
3000         "pfmul 8(%3,%0), %%mm1 \n\t"
3001         "movq  %%mm0,  (%2,%0) \n\t"
3002         "movq  %%mm1, 8(%2,%0) \n\t"
3003         "add   $16, %1 \n\t"
3004         "sub   $16, %0 \n\t"
3005         "jge   1b \n\t"
3006         :"+r"(i), "+r"(src1)
3007         :"r"(dst), "r"(src0)
3008     );
3009     asm volatile("femms");
3010 }
3011 static void vector_fmul_reverse_sse(float *dst, const float *src0, const float *src1, int len){
3012     long i = len*4-32;
3013     asm volatile(
3014         "1: \n\t"
3015         "movaps        16(%1), %%xmm0 \n\t"
3016         "movaps          (%1), %%xmm1 \n\t"
3017         "shufps $0x1b, %%xmm0, %%xmm0 \n\t"
3018         "shufps $0x1b, %%xmm1, %%xmm1 \n\t"
3019         "mulps        (%3,%0), %%xmm0 \n\t"
3020         "mulps      16(%3,%0), %%xmm1 \n\t"
3021         "movaps     %%xmm0,   (%2,%0) \n\t"
3022         "movaps     %%xmm1, 16(%2,%0) \n\t"
3023         "add    $32, %1 \n\t"
3024         "sub    $32, %0 \n\t"
3025         "jge    1b \n\t"
3026         :"+r"(i), "+r"(src1)
3027         :"r"(dst), "r"(src0)
3028     );
3029 }
3030
3031 static void vector_fmul_add_add_3dnow(float *dst, const float *src0, const float *src1,
3032                                       const float *src2, int src3, int len, int step){
3033     long i = (len-4)*4;
3034     if(step == 2 && src3 == 0){
3035         dst += (len-4)*2;
3036         asm volatile(
3037             "1: \n\t"
3038             "movq   (%2,%0),  %%mm0 \n\t"
3039             "movq  8(%2,%0),  %%mm1 \n\t"
3040             "pfmul  (%3,%0),  %%mm0 \n\t"
3041             "pfmul 8(%3,%0),  %%mm1 \n\t"
3042             "pfadd  (%4,%0),  %%mm0 \n\t"
3043             "pfadd 8(%4,%0),  %%mm1 \n\t"
3044             "movd     %%mm0,   (%1) \n\t"
3045             "movd     %%mm1, 16(%1) \n\t"
3046             "psrlq      $32,  %%mm0 \n\t"
3047             "psrlq      $32,  %%mm1 \n\t"
3048             "movd     %%mm0,  8(%1) \n\t"
3049             "movd     %%mm1, 24(%1) \n\t"
3050             "sub  $32, %1 \n\t"
3051             "sub  $16, %0 \n\t"
3052             "jge  1b \n\t"
3053             :"+r"(i), "+r"(dst)
3054             :"r"(src0), "r"(src1), "r"(src2)
3055             :"memory"
3056         );
3057     }
3058     else if(step == 1 && src3 == 0){
3059         asm volatile(
3060             "1: \n\t"
3061             "movq    (%2,%0), %%mm0 \n\t"
3062             "movq   8(%2,%0), %%mm1 \n\t"
3063             "pfmul   (%3,%0), %%mm0 \n\t"
3064             "pfmul  8(%3,%0), %%mm1 \n\t"
3065             "pfadd   (%4,%0), %%mm0 \n\t"
3066             "pfadd  8(%4,%0), %%mm1 \n\t"
3067             "movq  %%mm0,   (%1,%0) \n\t"
3068             "movq  %%mm1,  8(%1,%0) \n\t"
3069             "sub  $16, %0 \n\t"
3070             "jge  1b \n\t"
3071             :"+r"(i)
3072             :"r"(dst), "r"(src0), "r"(src1), "r"(src2)
3073             :"memory"
3074         );
3075     }
3076     else
3077         ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
3078     asm volatile("femms");
3079 }
3080 static void vector_fmul_add_add_sse(float *dst, const float *src0, const float *src1,
3081                                     const float *src2, int src3, int len, int step){
3082     long i = (len-8)*4;
3083     if(step == 2 && src3 == 0){
3084         dst += (len-8)*2;
3085         asm volatile(
3086             "1: \n\t"
3087             "movaps   (%2,%0), %%xmm0 \n\t"
3088             "movaps 16(%2,%0), %%xmm1 \n\t"
3089             "mulps    (%3,%0), %%xmm0 \n\t"
3090             "mulps  16(%3,%0), %%xmm1 \n\t"
3091             "addps    (%4,%0), %%xmm0 \n\t"
3092             "addps  16(%4,%0), %%xmm1 \n\t"
3093             "movss     %%xmm0,   (%1) \n\t"
3094             "movss     %%xmm1, 32(%1) \n\t"
3095             "movhlps   %%xmm0, %%xmm2 \n\t"
3096             "movhlps   %%xmm1, %%xmm3 \n\t"
3097             "movss     %%xmm2, 16(%1) \n\t"
3098             "movss     %%xmm3, 48(%1) \n\t"
3099             "shufps $0xb1, %%xmm0, %%xmm0 \n\t"
3100             "shufps $0xb1, %%xmm1, %%xmm1 \n\t"
3101             "movss     %%xmm0,  8(%1) \n\t"
3102             "movss     %%xmm1, 40(%1) \n\t"
3103             "movhlps   %%xmm0, %%xmm2 \n\t"
3104             "movhlps   %%xmm1, %%xmm3 \n\t"
3105             "movss     %%xmm2, 24(%1) \n\t"
3106             "movss     %%xmm3, 56(%1) \n\t"
3107             "sub  $64, %1 \n\t"
3108             "sub  $32, %0 \n\t"
3109             "jge  1b \n\t"
3110             :"+r"(i), "+r"(dst)
3111             :"r"(src0), "r"(src1), "r"(src2)
3112             :"memory"
3113         );
3114     }
3115     else if(step == 1 && src3 == 0){
3116         asm volatile(
3117             "1: \n\t"
3118             "movaps   (%2,%0), %%xmm0 \n\t"
3119             "movaps 16(%2,%0), %%xmm1 \n\t"
3120             "mulps    (%3,%0), %%xmm0 \n\t"
3121             "mulps  16(%3,%0), %%xmm1 \n\t"
3122             "addps    (%4,%0), %%xmm0 \n\t"
3123             "addps  16(%4,%0), %%xmm1 \n\t"
3124             "movaps %%xmm0,   (%1,%0) \n\t"
3125             "movaps %%xmm1, 16(%1,%0) \n\t"
3126             "sub  $32, %0 \n\t"
3127             "jge  1b \n\t"
3128             :"+r"(i)
3129             :"r"(dst), "r"(src0), "r"(src1), "r"(src2)
3130             :"memory"
3131         );
3132     }
3133     else
3134         ff_vector_fmul_add_add_c(dst, src0, src1, src2, src3, len, step);
3135 }
3136
3137 static void float_to_int16_3dnow(int16_t *dst, const float *src, int len){
3138     // not bit-exact: pf2id uses different rounding than C and SSE
3139     int i;
3140     for(i=0; i<len; i+=4) {
3141         asm volatile(
3142             "pf2id       %1, %%mm0 \n\t"
3143             "pf2id       %2, %%mm1 \n\t"
3144             "packssdw %%mm1, %%mm0 \n\t"
3145             "movq     %%mm0, %0    \n\t"
3146             :"=m"(dst[i])
3147             :"m"(src[i]), "m"(src[i+2])
3148         );
3149     }
3150     asm volatile("femms");
3151 }
3152 static void float_to_int16_sse(int16_t *dst, const float *src, int len){
3153     int i;
3154     for(i=0; i<len; i+=4) {
3155         asm volatile(
3156             "cvtps2pi    %1, %%mm0 \n\t"
3157             "cvtps2pi    %2, %%mm1 \n\t"
3158             "packssdw %%mm1, %%mm0 \n\t"
3159             "movq     %%mm0, %0    \n\t"
3160             :"=m"(dst[i])
3161             :"m"(src[i]), "m"(src[i+2])
3162         );
3163     }
3164     asm volatile("emms");
3165 }
3166
3167 #ifdef CONFIG_SNOW_DECODER
3168 extern void ff_snow_horizontal_compose97i_sse2(DWTELEM *b, int width);
3169 extern void ff_snow_horizontal_compose97i_mmx(DWTELEM *b, int width);
3170 extern void ff_snow_vertical_compose97i_sse2(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
3171 extern void ff_snow_vertical_compose97i_mmx(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2, DWTELEM *b3, DWTELEM *b4, DWTELEM *b5, int width);
3172 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,
3173                            int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8);
3174 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,
3175                           int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8);
3176 #endif
3177
3178 void dsputil_init_mmx(DSPContext* c, AVCodecContext *avctx)
3179 {
3180     mm_flags = mm_support();
3181
3182     if (avctx->dsp_mask) {
3183         if (avctx->dsp_mask & FF_MM_FORCE)
3184             mm_flags |= (avctx->dsp_mask & 0xffff);
3185         else
3186             mm_flags &= ~(avctx->dsp_mask & 0xffff);
3187     }
3188
3189 #if 0
3190     av_log(avctx, AV_LOG_INFO, "libavcodec: CPU flags:");
3191     if (mm_flags & MM_MMX)
3192         av_log(avctx, AV_LOG_INFO, " mmx");
3193     if (mm_flags & MM_MMXEXT)
3194         av_log(avctx, AV_LOG_INFO, " mmxext");
3195     if (mm_flags & MM_3DNOW)
3196         av_log(avctx, AV_LOG_INFO, " 3dnow");
3197     if (mm_flags & MM_SSE)
3198         av_log(avctx, AV_LOG_INFO, " sse");
3199     if (mm_flags & MM_SSE2)
3200         av_log(avctx, AV_LOG_INFO, " sse2");
3201     av_log(avctx, AV_LOG_INFO, "\n");
3202 #endif
3203
3204     if (mm_flags & MM_MMX) {
3205         const int idct_algo= avctx->idct_algo;
3206
3207 #ifdef CONFIG_ENCODERS
3208         const int dct_algo = avctx->dct_algo;
3209         if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
3210             if(mm_flags & MM_SSE2){
3211                 c->fdct = ff_fdct_sse2;
3212             }else if(mm_flags & MM_MMXEXT){
3213                 c->fdct = ff_fdct_mmx2;
3214             }else{
3215                 c->fdct = ff_fdct_mmx;
3216             }
3217         }
3218 #endif //CONFIG_ENCODERS
3219         if(avctx->lowres==0){
3220             if(idct_algo==FF_IDCT_AUTO || idct_algo==FF_IDCT_SIMPLEMMX){
3221                 c->idct_put= ff_simple_idct_put_mmx;
3222                 c->idct_add= ff_simple_idct_add_mmx;
3223                 c->idct    = ff_simple_idct_mmx;
3224                 c->idct_permutation_type= FF_SIMPLE_IDCT_PERM;
3225 #ifdef CONFIG_GPL
3226             }else if(idct_algo==FF_IDCT_LIBMPEG2MMX){
3227                 if(mm_flags & MM_MMXEXT){
3228                     c->idct_put= ff_libmpeg2mmx2_idct_put;
3229                     c->idct_add= ff_libmpeg2mmx2_idct_add;
3230                     c->idct    = ff_mmxext_idct;
3231                 }else{
3232                     c->idct_put= ff_libmpeg2mmx_idct_put;
3233                     c->idct_add= ff_libmpeg2mmx_idct_add;
3234                     c->idct    = ff_mmx_idct;
3235                 }
3236                 c->idct_permutation_type= FF_LIBMPEG2_IDCT_PERM;
3237 #endif
3238             }else if((ENABLE_VP3_DECODER || ENABLE_VP5_DECODER || ENABLE_VP6_DECODER) &&
3239                      idct_algo==FF_IDCT_VP3 &&
3240                      avctx->codec->id!=CODEC_ID_THEORA &&
3241                      !(avctx->flags & CODEC_FLAG_BITEXACT)){
3242                 if(mm_flags & MM_SSE2){
3243                     c->idct_put= ff_vp3_idct_put_sse2;
3244                     c->idct_add= ff_vp3_idct_add_sse2;
3245                     c->idct    = ff_vp3_idct_sse2;
3246                     c->idct_permutation_type= FF_TRANSPOSE_IDCT_PERM;
3247                 }else{
3248                     ff_vp3_dsp_init_mmx();
3249                     c->idct_put= ff_vp3_idct_put_mmx;
3250                     c->idct_add= ff_vp3_idct_add_mmx;
3251                     c->idct    = ff_vp3_idct_mmx;
3252                     c->idct_permutation_type= FF_PARTTRANS_IDCT_PERM;
3253                 }
3254             }else if(idct_algo==FF_IDCT_CAVS){
3255                     c->idct_permutation_type= FF_TRANSPOSE_IDCT_PERM;
3256             }else if(idct_algo==FF_IDCT_XVIDMMX){
3257                 if(mm_flags & MM_MMXEXT){
3258                     c->idct_put= ff_idct_xvid_mmx2_put;
3259                     c->idct_add= ff_idct_xvid_mmx2_add;
3260                     c->idct    = ff_idct_xvid_mmx2;
3261                 }else{
3262                     c->idct_put= ff_idct_xvid_mmx_put;
3263                     c->idct_add= ff_idct_xvid_mmx_add;
3264                     c->idct    = ff_idct_xvid_mmx;
3265                 }
3266             }
3267         }
3268
3269 #ifdef CONFIG_ENCODERS
3270         c->get_pixels = get_pixels_mmx;
3271         c->diff_pixels = diff_pixels_mmx;
3272 #endif //CONFIG_ENCODERS
3273         c->put_pixels_clamped = put_pixels_clamped_mmx;
3274         c->put_signed_pixels_clamped = put_signed_pixels_clamped_mmx;
3275         c->add_pixels_clamped = add_pixels_clamped_mmx;
3276         c->clear_blocks = clear_blocks_mmx;
3277 #ifdef CONFIG_ENCODERS
3278         c->pix_sum = pix_sum16_mmx;
3279 #endif //CONFIG_ENCODERS
3280
3281         c->put_pixels_tab[0][0] = put_pixels16_mmx;
3282         c->put_pixels_tab[0][1] = put_pixels16_x2_mmx;
3283         c->put_pixels_tab[0][2] = put_pixels16_y2_mmx;
3284         c->put_pixels_tab[0][3] = put_pixels16_xy2_mmx;
3285
3286         c->put_no_rnd_pixels_tab[0][0] = put_pixels16_mmx;
3287         c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_mmx;
3288         c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_mmx;
3289         c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_mmx;
3290
3291         c->avg_pixels_tab[0][0] = avg_pixels16_mmx;
3292         c->avg_pixels_tab[0][1] = avg_pixels16_x2_mmx;
3293         c->avg_pixels_tab[0][2] = avg_pixels16_y2_mmx;
3294        &n