470c31193087ea21a910915da2ad3f12a2994238
[ffmpeg.git] / libavcodec / i386 / dsputilenc_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 "libavutil/x86_cpu.h"
26 #include "libavcodec/dsputil.h"
27 #include "libavcodec/mpegvideo.h"
28 #include "dsputil_mmx.h"
29
30
31 static void get_pixels_mmx(DCTELEM *block, const uint8_t *pixels, int line_size)
32 {
33     asm volatile(
34         "mov $-128, %%"REG_a"           \n\t"
35         "pxor %%mm7, %%mm7              \n\t"
36         ASMALIGN(4)
37         "1:                             \n\t"
38         "movq (%0), %%mm0               \n\t"
39         "movq (%0, %2), %%mm2           \n\t"
40         "movq %%mm0, %%mm1              \n\t"
41         "movq %%mm2, %%mm3              \n\t"
42         "punpcklbw %%mm7, %%mm0         \n\t"
43         "punpckhbw %%mm7, %%mm1         \n\t"
44         "punpcklbw %%mm7, %%mm2         \n\t"
45         "punpckhbw %%mm7, %%mm3         \n\t"
46         "movq %%mm0, (%1, %%"REG_a")    \n\t"
47         "movq %%mm1, 8(%1, %%"REG_a")   \n\t"
48         "movq %%mm2, 16(%1, %%"REG_a")  \n\t"
49         "movq %%mm3, 24(%1, %%"REG_a")  \n\t"
50         "add %3, %0                     \n\t"
51         "add $32, %%"REG_a"             \n\t"
52         "js 1b                          \n\t"
53         : "+r" (pixels)
54         : "r" (block+64), "r" ((x86_reg)line_size), "r" ((x86_reg)line_size*2)
55         : "%"REG_a
56     );
57 }
58
59 static inline void diff_pixels_mmx(DCTELEM *block, const uint8_t *s1, const uint8_t *s2, int stride)
60 {
61     asm volatile(
62         "pxor %%mm7, %%mm7              \n\t"
63         "mov $-128, %%"REG_a"           \n\t"
64         ASMALIGN(4)
65         "1:                             \n\t"
66         "movq (%0), %%mm0               \n\t"
67         "movq (%1), %%mm2               \n\t"
68         "movq %%mm0, %%mm1              \n\t"
69         "movq %%mm2, %%mm3              \n\t"
70         "punpcklbw %%mm7, %%mm0         \n\t"
71         "punpckhbw %%mm7, %%mm1         \n\t"
72         "punpcklbw %%mm7, %%mm2         \n\t"
73         "punpckhbw %%mm7, %%mm3         \n\t"
74         "psubw %%mm2, %%mm0             \n\t"
75         "psubw %%mm3, %%mm1             \n\t"
76         "movq %%mm0, (%2, %%"REG_a")    \n\t"
77         "movq %%mm1, 8(%2, %%"REG_a")   \n\t"
78         "add %3, %0                     \n\t"
79         "add %3, %1                     \n\t"
80         "add $16, %%"REG_a"             \n\t"
81         "jnz 1b                         \n\t"
82         : "+r" (s1), "+r" (s2)
83         : "r" (block+64), "r" ((x86_reg)stride)
84         : "%"REG_a
85     );
86 }
87
88 static int pix_sum16_mmx(uint8_t * pix, int line_size){
89     const int h=16;
90     int sum;
91     x86_reg index= -line_size*h;
92
93     asm volatile(
94                 "pxor %%mm7, %%mm7              \n\t"
95                 "pxor %%mm6, %%mm6              \n\t"
96                 "1:                             \n\t"
97                 "movq (%2, %1), %%mm0           \n\t"
98                 "movq (%2, %1), %%mm1           \n\t"
99                 "movq 8(%2, %1), %%mm2          \n\t"
100                 "movq 8(%2, %1), %%mm3          \n\t"
101                 "punpcklbw %%mm7, %%mm0         \n\t"
102                 "punpckhbw %%mm7, %%mm1         \n\t"
103                 "punpcklbw %%mm7, %%mm2         \n\t"
104                 "punpckhbw %%mm7, %%mm3         \n\t"
105                 "paddw %%mm0, %%mm1             \n\t"
106                 "paddw %%mm2, %%mm3             \n\t"
107                 "paddw %%mm1, %%mm3             \n\t"
108                 "paddw %%mm3, %%mm6             \n\t"
109                 "add %3, %1                     \n\t"
110                 " js 1b                         \n\t"
111                 "movq %%mm6, %%mm5              \n\t"
112                 "psrlq $32, %%mm6               \n\t"
113                 "paddw %%mm5, %%mm6             \n\t"
114                 "movq %%mm6, %%mm5              \n\t"
115                 "psrlq $16, %%mm6               \n\t"
116                 "paddw %%mm5, %%mm6             \n\t"
117                 "movd %%mm6, %0                 \n\t"
118                 "andl $0xFFFF, %0               \n\t"
119                 : "=&r" (sum), "+r" (index)
120                 : "r" (pix - index), "r" ((x86_reg)line_size)
121         );
122
123         return sum;
124 }
125
126 static int pix_norm1_mmx(uint8_t *pix, int line_size) {
127     int tmp;
128   asm volatile (
129       "movl $16,%%ecx\n"
130       "pxor %%mm0,%%mm0\n"
131       "pxor %%mm7,%%mm7\n"
132       "1:\n"
133       "movq (%0),%%mm2\n"       /* mm2 = pix[0-7] */
134       "movq 8(%0),%%mm3\n"      /* mm3 = pix[8-15] */
135
136       "movq %%mm2,%%mm1\n"      /* mm1 = mm2 = pix[0-7] */
137
138       "punpckhbw %%mm0,%%mm1\n" /* mm1 = [pix4-7] */
139       "punpcklbw %%mm0,%%mm2\n" /* mm2 = [pix0-3] */
140
141       "movq %%mm3,%%mm4\n"      /* mm4 = mm3 = pix[8-15] */
142       "punpckhbw %%mm0,%%mm3\n" /* mm3 = [pix12-15] */
143       "punpcklbw %%mm0,%%mm4\n" /* mm4 = [pix8-11] */
144
145       "pmaddwd %%mm1,%%mm1\n"   /* mm1 = (pix0^2+pix1^2,pix2^2+pix3^2) */
146       "pmaddwd %%mm2,%%mm2\n"   /* mm2 = (pix4^2+pix5^2,pix6^2+pix7^2) */
147
148       "pmaddwd %%mm3,%%mm3\n"
149       "pmaddwd %%mm4,%%mm4\n"
150
151       "paddd %%mm1,%%mm2\n"     /* mm2 = (pix0^2+pix1^2+pix4^2+pix5^2,
152                                           pix2^2+pix3^2+pix6^2+pix7^2) */
153       "paddd %%mm3,%%mm4\n"
154       "paddd %%mm2,%%mm7\n"
155
156       "add %2, %0\n"
157       "paddd %%mm4,%%mm7\n"
158       "dec %%ecx\n"
159       "jnz 1b\n"
160
161       "movq %%mm7,%%mm1\n"
162       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
163       "paddd %%mm7,%%mm1\n"
164       "movd %%mm1,%1\n"
165       : "+r" (pix), "=r"(tmp) : "r" ((x86_reg)line_size) : "%ecx" );
166     return tmp;
167 }
168
169 static int sse8_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
170     int tmp;
171   asm volatile (
172       "movl %4,%%ecx\n"
173       "shr $1,%%ecx\n"
174       "pxor %%mm0,%%mm0\n"      /* mm0 = 0 */
175       "pxor %%mm7,%%mm7\n"      /* mm7 holds the sum */
176       "1:\n"
177       "movq (%0),%%mm1\n"       /* mm1 = pix1[0][0-7] */
178       "movq (%1),%%mm2\n"       /* mm2 = pix2[0][0-7] */
179       "movq (%0,%3),%%mm3\n"    /* mm3 = pix1[1][0-7] */
180       "movq (%1,%3),%%mm4\n"    /* mm4 = pix2[1][0-7] */
181
182       /* todo: mm1-mm2, mm3-mm4 */
183       /* algo: subtract mm1 from mm2 with saturation and vice versa */
184       /*       OR the results to get absolute difference */
185       "movq %%mm1,%%mm5\n"
186       "movq %%mm3,%%mm6\n"
187       "psubusb %%mm2,%%mm1\n"
188       "psubusb %%mm4,%%mm3\n"
189       "psubusb %%mm5,%%mm2\n"
190       "psubusb %%mm6,%%mm4\n"
191
192       "por %%mm1,%%mm2\n"
193       "por %%mm3,%%mm4\n"
194
195       /* now convert to 16-bit vectors so we can square them */
196       "movq %%mm2,%%mm1\n"
197       "movq %%mm4,%%mm3\n"
198
199       "punpckhbw %%mm0,%%mm2\n"
200       "punpckhbw %%mm0,%%mm4\n"
201       "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */
202       "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */
203
204       "pmaddwd %%mm2,%%mm2\n"
205       "pmaddwd %%mm4,%%mm4\n"
206       "pmaddwd %%mm1,%%mm1\n"
207       "pmaddwd %%mm3,%%mm3\n"
208
209       "lea (%0,%3,2), %0\n"     /* pix1 += 2*line_size */
210       "lea (%1,%3,2), %1\n"     /* pix2 += 2*line_size */
211
212       "paddd %%mm2,%%mm1\n"
213       "paddd %%mm4,%%mm3\n"
214       "paddd %%mm1,%%mm7\n"
215       "paddd %%mm3,%%mm7\n"
216
217       "decl %%ecx\n"
218       "jnz 1b\n"
219
220       "movq %%mm7,%%mm1\n"
221       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
222       "paddd %%mm7,%%mm1\n"
223       "movd %%mm1,%2\n"
224       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
225       : "r" ((x86_reg)line_size) , "m" (h)
226       : "%ecx");
227     return tmp;
228 }
229
230 static int sse16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
231     int tmp;
232   asm volatile (
233       "movl %4,%%ecx\n"
234       "pxor %%mm0,%%mm0\n"      /* mm0 = 0 */
235       "pxor %%mm7,%%mm7\n"      /* mm7 holds the sum */
236       "1:\n"
237       "movq (%0),%%mm1\n"       /* mm1 = pix1[0-7] */
238       "movq (%1),%%mm2\n"       /* mm2 = pix2[0-7] */
239       "movq 8(%0),%%mm3\n"      /* mm3 = pix1[8-15] */
240       "movq 8(%1),%%mm4\n"      /* mm4 = pix2[8-15] */
241
242       /* todo: mm1-mm2, mm3-mm4 */
243       /* algo: subtract mm1 from mm2 with saturation and vice versa */
244       /*       OR the results to get absolute difference */
245       "movq %%mm1,%%mm5\n"
246       "movq %%mm3,%%mm6\n"
247       "psubusb %%mm2,%%mm1\n"
248       "psubusb %%mm4,%%mm3\n"
249       "psubusb %%mm5,%%mm2\n"
250       "psubusb %%mm6,%%mm4\n"
251
252       "por %%mm1,%%mm2\n"
253       "por %%mm3,%%mm4\n"
254
255       /* now convert to 16-bit vectors so we can square them */
256       "movq %%mm2,%%mm1\n"
257       "movq %%mm4,%%mm3\n"
258
259       "punpckhbw %%mm0,%%mm2\n"
260       "punpckhbw %%mm0,%%mm4\n"
261       "punpcklbw %%mm0,%%mm1\n" /* mm1 now spread over (mm1,mm2) */
262       "punpcklbw %%mm0,%%mm3\n" /* mm4 now spread over (mm3,mm4) */
263
264       "pmaddwd %%mm2,%%mm2\n"
265       "pmaddwd %%mm4,%%mm4\n"
266       "pmaddwd %%mm1,%%mm1\n"
267       "pmaddwd %%mm3,%%mm3\n"
268
269       "add %3,%0\n"
270       "add %3,%1\n"
271
272       "paddd %%mm2,%%mm1\n"
273       "paddd %%mm4,%%mm3\n"
274       "paddd %%mm1,%%mm7\n"
275       "paddd %%mm3,%%mm7\n"
276
277       "decl %%ecx\n"
278       "jnz 1b\n"
279
280       "movq %%mm7,%%mm1\n"
281       "psrlq $32, %%mm7\n"      /* shift hi dword to lo */
282       "paddd %%mm7,%%mm1\n"
283       "movd %%mm1,%2\n"
284       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
285       : "r" ((x86_reg)line_size) , "m" (h)
286       : "%ecx");
287     return tmp;
288 }
289
290 static int sse16_sse2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
291     int tmp;
292   asm volatile (
293       "shr $1,%2\n"
294       "pxor %%xmm0,%%xmm0\n"    /* mm0 = 0 */
295       "pxor %%xmm7,%%xmm7\n"    /* mm7 holds the sum */
296       "1:\n"
297       "movdqu (%0),%%xmm1\n"    /* mm1 = pix1[0][0-15] */
298       "movdqu (%1),%%xmm2\n"    /* mm2 = pix2[0][0-15] */
299       "movdqu (%0,%4),%%xmm3\n" /* mm3 = pix1[1][0-15] */
300       "movdqu (%1,%4),%%xmm4\n" /* mm4 = pix2[1][0-15] */
301
302       /* todo: mm1-mm2, mm3-mm4 */
303       /* algo: subtract mm1 from mm2 with saturation and vice versa */
304       /*       OR the results to get absolute difference */
305       "movdqa %%xmm1,%%xmm5\n"
306       "movdqa %%xmm3,%%xmm6\n"
307       "psubusb %%xmm2,%%xmm1\n"
308       "psubusb %%xmm4,%%xmm3\n"
309       "psubusb %%xmm5,%%xmm2\n"
310       "psubusb %%xmm6,%%xmm4\n"
311
312       "por %%xmm1,%%xmm2\n"
313       "por %%xmm3,%%xmm4\n"
314
315       /* now convert to 16-bit vectors so we can square them */
316       "movdqa %%xmm2,%%xmm1\n"
317       "movdqa %%xmm4,%%xmm3\n"
318
319       "punpckhbw %%xmm0,%%xmm2\n"
320       "punpckhbw %%xmm0,%%xmm4\n"
321       "punpcklbw %%xmm0,%%xmm1\n"  /* mm1 now spread over (mm1,mm2) */
322       "punpcklbw %%xmm0,%%xmm3\n"  /* mm4 now spread over (mm3,mm4) */
323
324       "pmaddwd %%xmm2,%%xmm2\n"
325       "pmaddwd %%xmm4,%%xmm4\n"
326       "pmaddwd %%xmm1,%%xmm1\n"
327       "pmaddwd %%xmm3,%%xmm3\n"
328
329       "lea (%0,%4,2), %0\n"        /* pix1 += 2*line_size */
330       "lea (%1,%4,2), %1\n"        /* pix2 += 2*line_size */
331
332       "paddd %%xmm2,%%xmm1\n"
333       "paddd %%xmm4,%%xmm3\n"
334       "paddd %%xmm1,%%xmm7\n"
335       "paddd %%xmm3,%%xmm7\n"
336
337       "decl %2\n"
338       "jnz 1b\n"
339
340       "movdqa %%xmm7,%%xmm1\n"
341       "psrldq $8, %%xmm7\n"        /* shift hi qword to lo */
342       "paddd %%xmm1,%%xmm7\n"
343       "movdqa %%xmm7,%%xmm1\n"
344       "psrldq $4, %%xmm7\n"        /* shift hi dword to lo */
345       "paddd %%xmm1,%%xmm7\n"
346       "movd %%xmm7,%3\n"
347       : "+r" (pix1), "+r" (pix2), "+r"(h), "=r"(tmp)
348       : "r" ((x86_reg)line_size));
349     return tmp;
350 }
351
352 static int hf_noise8_mmx(uint8_t * pix1, int line_size, int h) {
353     int tmp;
354   asm volatile (
355       "movl %3,%%ecx\n"
356       "pxor %%mm7,%%mm7\n"
357       "pxor %%mm6,%%mm6\n"
358
359       "movq (%0),%%mm0\n"
360       "movq %%mm0, %%mm1\n"
361       "psllq $8, %%mm0\n"
362       "psrlq $8, %%mm1\n"
363       "psrlq $8, %%mm0\n"
364       "movq %%mm0, %%mm2\n"
365       "movq %%mm1, %%mm3\n"
366       "punpcklbw %%mm7,%%mm0\n"
367       "punpcklbw %%mm7,%%mm1\n"
368       "punpckhbw %%mm7,%%mm2\n"
369       "punpckhbw %%mm7,%%mm3\n"
370       "psubw %%mm1, %%mm0\n"
371       "psubw %%mm3, %%mm2\n"
372
373       "add %2,%0\n"
374
375       "movq (%0),%%mm4\n"
376       "movq %%mm4, %%mm1\n"
377       "psllq $8, %%mm4\n"
378       "psrlq $8, %%mm1\n"
379       "psrlq $8, %%mm4\n"
380       "movq %%mm4, %%mm5\n"
381       "movq %%mm1, %%mm3\n"
382       "punpcklbw %%mm7,%%mm4\n"
383       "punpcklbw %%mm7,%%mm1\n"
384       "punpckhbw %%mm7,%%mm5\n"
385       "punpckhbw %%mm7,%%mm3\n"
386       "psubw %%mm1, %%mm4\n"
387       "psubw %%mm3, %%mm5\n"
388       "psubw %%mm4, %%mm0\n"
389       "psubw %%mm5, %%mm2\n"
390       "pxor %%mm3, %%mm3\n"
391       "pxor %%mm1, %%mm1\n"
392       "pcmpgtw %%mm0, %%mm3\n\t"
393       "pcmpgtw %%mm2, %%mm1\n\t"
394       "pxor %%mm3, %%mm0\n"
395       "pxor %%mm1, %%mm2\n"
396       "psubw %%mm3, %%mm0\n"
397       "psubw %%mm1, %%mm2\n"
398       "paddw %%mm0, %%mm2\n"
399       "paddw %%mm2, %%mm6\n"
400
401       "add %2,%0\n"
402       "1:\n"
403
404       "movq (%0),%%mm0\n"
405       "movq %%mm0, %%mm1\n"
406       "psllq $8, %%mm0\n"
407       "psrlq $8, %%mm1\n"
408       "psrlq $8, %%mm0\n"
409       "movq %%mm0, %%mm2\n"
410       "movq %%mm1, %%mm3\n"
411       "punpcklbw %%mm7,%%mm0\n"
412       "punpcklbw %%mm7,%%mm1\n"
413       "punpckhbw %%mm7,%%mm2\n"
414       "punpckhbw %%mm7,%%mm3\n"
415       "psubw %%mm1, %%mm0\n"
416       "psubw %%mm3, %%mm2\n"
417       "psubw %%mm0, %%mm4\n"
418       "psubw %%mm2, %%mm5\n"
419       "pxor %%mm3, %%mm3\n"
420       "pxor %%mm1, %%mm1\n"
421       "pcmpgtw %%mm4, %%mm3\n\t"
422       "pcmpgtw %%mm5, %%mm1\n\t"
423       "pxor %%mm3, %%mm4\n"
424       "pxor %%mm1, %%mm5\n"
425       "psubw %%mm3, %%mm4\n"
426       "psubw %%mm1, %%mm5\n"
427       "paddw %%mm4, %%mm5\n"
428       "paddw %%mm5, %%mm6\n"
429
430       "add %2,%0\n"
431
432       "movq (%0),%%mm4\n"
433       "movq %%mm4, %%mm1\n"
434       "psllq $8, %%mm4\n"
435       "psrlq $8, %%mm1\n"
436       "psrlq $8, %%mm4\n"
437       "movq %%mm4, %%mm5\n"
438       "movq %%mm1, %%mm3\n"
439       "punpcklbw %%mm7,%%mm4\n"
440       "punpcklbw %%mm7,%%mm1\n"
441       "punpckhbw %%mm7,%%mm5\n"
442       "punpckhbw %%mm7,%%mm3\n"
443       "psubw %%mm1, %%mm4\n"
444       "psubw %%mm3, %%mm5\n"
445       "psubw %%mm4, %%mm0\n"
446       "psubw %%mm5, %%mm2\n"
447       "pxor %%mm3, %%mm3\n"
448       "pxor %%mm1, %%mm1\n"
449       "pcmpgtw %%mm0, %%mm3\n\t"
450       "pcmpgtw %%mm2, %%mm1\n\t"
451       "pxor %%mm3, %%mm0\n"
452       "pxor %%mm1, %%mm2\n"
453       "psubw %%mm3, %%mm0\n"
454       "psubw %%mm1, %%mm2\n"
455       "paddw %%mm0, %%mm2\n"
456       "paddw %%mm2, %%mm6\n"
457
458       "add %2,%0\n"
459       "subl $2, %%ecx\n"
460       " jnz 1b\n"
461
462       "movq %%mm6, %%mm0\n"
463       "punpcklwd %%mm7,%%mm0\n"
464       "punpckhwd %%mm7,%%mm6\n"
465       "paddd %%mm0, %%mm6\n"
466
467       "movq %%mm6,%%mm0\n"
468       "psrlq $32, %%mm6\n"
469       "paddd %%mm6,%%mm0\n"
470       "movd %%mm0,%1\n"
471       : "+r" (pix1), "=r"(tmp)
472       : "r" ((x86_reg)line_size) , "g" (h-2)
473       : "%ecx");
474       return tmp;
475 }
476
477 static int hf_noise16_mmx(uint8_t * pix1, int line_size, int h) {
478     int tmp;
479     uint8_t * pix= pix1;
480   asm volatile (
481       "movl %3,%%ecx\n"
482       "pxor %%mm7,%%mm7\n"
483       "pxor %%mm6,%%mm6\n"
484
485       "movq (%0),%%mm0\n"
486       "movq 1(%0),%%mm1\n"
487       "movq %%mm0, %%mm2\n"
488       "movq %%mm1, %%mm3\n"
489       "punpcklbw %%mm7,%%mm0\n"
490       "punpcklbw %%mm7,%%mm1\n"
491       "punpckhbw %%mm7,%%mm2\n"
492       "punpckhbw %%mm7,%%mm3\n"
493       "psubw %%mm1, %%mm0\n"
494       "psubw %%mm3, %%mm2\n"
495
496       "add %2,%0\n"
497
498       "movq (%0),%%mm4\n"
499       "movq 1(%0),%%mm1\n"
500       "movq %%mm4, %%mm5\n"
501       "movq %%mm1, %%mm3\n"
502       "punpcklbw %%mm7,%%mm4\n"
503       "punpcklbw %%mm7,%%mm1\n"
504       "punpckhbw %%mm7,%%mm5\n"
505       "punpckhbw %%mm7,%%mm3\n"
506       "psubw %%mm1, %%mm4\n"
507       "psubw %%mm3, %%mm5\n"
508       "psubw %%mm4, %%mm0\n"
509       "psubw %%mm5, %%mm2\n"
510       "pxor %%mm3, %%mm3\n"
511       "pxor %%mm1, %%mm1\n"
512       "pcmpgtw %%mm0, %%mm3\n\t"
513       "pcmpgtw %%mm2, %%mm1\n\t"
514       "pxor %%mm3, %%mm0\n"
515       "pxor %%mm1, %%mm2\n"
516       "psubw %%mm3, %%mm0\n"
517       "psubw %%mm1, %%mm2\n"
518       "paddw %%mm0, %%mm2\n"
519       "paddw %%mm2, %%mm6\n"
520
521       "add %2,%0\n"
522       "1:\n"
523
524       "movq (%0),%%mm0\n"
525       "movq 1(%0),%%mm1\n"
526       "movq %%mm0, %%mm2\n"
527       "movq %%mm1, %%mm3\n"
528       "punpcklbw %%mm7,%%mm0\n"
529       "punpcklbw %%mm7,%%mm1\n"
530       "punpckhbw %%mm7,%%mm2\n"
531       "punpckhbw %%mm7,%%mm3\n"
532       "psubw %%mm1, %%mm0\n"
533       "psubw %%mm3, %%mm2\n"
534       "psubw %%mm0, %%mm4\n"
535       "psubw %%mm2, %%mm5\n"
536       "pxor %%mm3, %%mm3\n"
537       "pxor %%mm1, %%mm1\n"
538       "pcmpgtw %%mm4, %%mm3\n\t"
539       "pcmpgtw %%mm5, %%mm1\n\t"
540       "pxor %%mm3, %%mm4\n"
541       "pxor %%mm1, %%mm5\n"
542       "psubw %%mm3, %%mm4\n"
543       "psubw %%mm1, %%mm5\n"
544       "paddw %%mm4, %%mm5\n"
545       "paddw %%mm5, %%mm6\n"
546
547       "add %2,%0\n"
548
549       "movq (%0),%%mm4\n"
550       "movq 1(%0),%%mm1\n"
551       "movq %%mm4, %%mm5\n"
552       "movq %%mm1, %%mm3\n"
553       "punpcklbw %%mm7,%%mm4\n"
554       "punpcklbw %%mm7,%%mm1\n"
555       "punpckhbw %%mm7,%%mm5\n"
556       "punpckhbw %%mm7,%%mm3\n"
557       "psubw %%mm1, %%mm4\n"
558       "psubw %%mm3, %%mm5\n"
559       "psubw %%mm4, %%mm0\n"
560       "psubw %%mm5, %%mm2\n"
561       "pxor %%mm3, %%mm3\n"
562       "pxor %%mm1, %%mm1\n"
563       "pcmpgtw %%mm0, %%mm3\n\t"
564       "pcmpgtw %%mm2, %%mm1\n\t"
565       "pxor %%mm3, %%mm0\n"
566       "pxor %%mm1, %%mm2\n"
567       "psubw %%mm3, %%mm0\n"
568       "psubw %%mm1, %%mm2\n"
569       "paddw %%mm0, %%mm2\n"
570       "paddw %%mm2, %%mm6\n"
571
572       "add %2,%0\n"
573       "subl $2, %%ecx\n"
574       " jnz 1b\n"
575
576       "movq %%mm6, %%mm0\n"
577       "punpcklwd %%mm7,%%mm0\n"
578       "punpckhwd %%mm7,%%mm6\n"
579       "paddd %%mm0, %%mm6\n"
580
581       "movq %%mm6,%%mm0\n"
582       "psrlq $32, %%mm6\n"
583       "paddd %%mm6,%%mm0\n"
584       "movd %%mm0,%1\n"
585       : "+r" (pix1), "=r"(tmp)
586       : "r" ((x86_reg)line_size) , "g" (h-2)
587       : "%ecx");
588       return tmp + hf_noise8_mmx(pix+8, line_size, h);
589 }
590
591 static int nsse16_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
592     MpegEncContext *c = p;
593     int score1, score2;
594
595     if(c) score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h);
596     else  score1 = sse16_mmx(c, pix1, pix2, line_size, h);
597     score2= hf_noise16_mmx(pix1, line_size, h) - hf_noise16_mmx(pix2, line_size, h);
598
599     if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight;
600     else  return score1 + FFABS(score2)*8;
601 }
602
603 static int nsse8_mmx(void *p, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
604     MpegEncContext *c = p;
605     int score1= sse8_mmx(c, pix1, pix2, line_size, h);
606     int score2= hf_noise8_mmx(pix1, line_size, h) - hf_noise8_mmx(pix2, line_size, h);
607
608     if(c) return score1 + FFABS(score2)*c->avctx->nsse_weight;
609     else  return score1 + FFABS(score2)*8;
610 }
611
612 static int vsad_intra16_mmx(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
613     int tmp;
614
615     assert( (((int)pix) & 7) == 0);
616     assert((line_size &7) ==0);
617
618 #define SUM(in0, in1, out0, out1) \
619       "movq (%0), %%mm2\n"\
620       "movq 8(%0), %%mm3\n"\
621       "add %2,%0\n"\
622       "movq %%mm2, " #out0 "\n"\
623       "movq %%mm3, " #out1 "\n"\
624       "psubusb " #in0 ", %%mm2\n"\
625       "psubusb " #in1 ", %%mm3\n"\
626       "psubusb " #out0 ", " #in0 "\n"\
627       "psubusb " #out1 ", " #in1 "\n"\
628       "por %%mm2, " #in0 "\n"\
629       "por %%mm3, " #in1 "\n"\
630       "movq " #in0 ", %%mm2\n"\
631       "movq " #in1 ", %%mm3\n"\
632       "punpcklbw %%mm7, " #in0 "\n"\
633       "punpcklbw %%mm7, " #in1 "\n"\
634       "punpckhbw %%mm7, %%mm2\n"\
635       "punpckhbw %%mm7, %%mm3\n"\
636       "paddw " #in1 ", " #in0 "\n"\
637       "paddw %%mm3, %%mm2\n"\
638       "paddw %%mm2, " #in0 "\n"\
639       "paddw " #in0 ", %%mm6\n"
640
641
642   asm volatile (
643       "movl %3,%%ecx\n"
644       "pxor %%mm6,%%mm6\n"
645       "pxor %%mm7,%%mm7\n"
646       "movq (%0),%%mm0\n"
647       "movq 8(%0),%%mm1\n"
648       "add %2,%0\n"
649       "jmp 2f\n"
650       "1:\n"
651
652       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
653       "2:\n"
654       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
655
656       "subl $2, %%ecx\n"
657       "jnz 1b\n"
658
659       "movq %%mm6,%%mm0\n"
660       "psrlq $32, %%mm6\n"
661       "paddw %%mm6,%%mm0\n"
662       "movq %%mm0,%%mm6\n"
663       "psrlq $16, %%mm0\n"
664       "paddw %%mm6,%%mm0\n"
665       "movd %%mm0,%1\n"
666       : "+r" (pix), "=r"(tmp)
667       : "r" ((x86_reg)line_size) , "m" (h)
668       : "%ecx");
669     return tmp & 0xFFFF;
670 }
671 #undef SUM
672
673 static int vsad_intra16_mmx2(void *v, uint8_t * pix, uint8_t * dummy, int line_size, int h) {
674     int tmp;
675
676     assert( (((int)pix) & 7) == 0);
677     assert((line_size &7) ==0);
678
679 #define SUM(in0, in1, out0, out1) \
680       "movq (%0), " #out0 "\n"\
681       "movq 8(%0), " #out1 "\n"\
682       "add %2,%0\n"\
683       "psadbw " #out0 ", " #in0 "\n"\
684       "psadbw " #out1 ", " #in1 "\n"\
685       "paddw " #in1 ", " #in0 "\n"\
686       "paddw " #in0 ", %%mm6\n"
687
688   asm volatile (
689       "movl %3,%%ecx\n"
690       "pxor %%mm6,%%mm6\n"
691       "pxor %%mm7,%%mm7\n"
692       "movq (%0),%%mm0\n"
693       "movq 8(%0),%%mm1\n"
694       "add %2,%0\n"
695       "jmp 2f\n"
696       "1:\n"
697
698       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
699       "2:\n"
700       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
701
702       "subl $2, %%ecx\n"
703       "jnz 1b\n"
704
705       "movd %%mm6,%1\n"
706       : "+r" (pix), "=r"(tmp)
707       : "r" ((x86_reg)line_size) , "m" (h)
708       : "%ecx");
709     return tmp;
710 }
711 #undef SUM
712
713 static int vsad16_mmx(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
714     int tmp;
715
716     assert( (((int)pix1) & 7) == 0);
717     assert( (((int)pix2) & 7) == 0);
718     assert((line_size &7) ==0);
719
720 #define SUM(in0, in1, out0, out1) \
721       "movq (%0),%%mm2\n"\
722       "movq (%1)," #out0 "\n"\
723       "movq 8(%0),%%mm3\n"\
724       "movq 8(%1)," #out1 "\n"\
725       "add %3,%0\n"\
726       "add %3,%1\n"\
727       "psubb " #out0 ", %%mm2\n"\
728       "psubb " #out1 ", %%mm3\n"\
729       "pxor %%mm7, %%mm2\n"\
730       "pxor %%mm7, %%mm3\n"\
731       "movq %%mm2, " #out0 "\n"\
732       "movq %%mm3, " #out1 "\n"\
733       "psubusb " #in0 ", %%mm2\n"\
734       "psubusb " #in1 ", %%mm3\n"\
735       "psubusb " #out0 ", " #in0 "\n"\
736       "psubusb " #out1 ", " #in1 "\n"\
737       "por %%mm2, " #in0 "\n"\
738       "por %%mm3, " #in1 "\n"\
739       "movq " #in0 ", %%mm2\n"\
740       "movq " #in1 ", %%mm3\n"\
741       "punpcklbw %%mm7, " #in0 "\n"\
742       "punpcklbw %%mm7, " #in1 "\n"\
743       "punpckhbw %%mm7, %%mm2\n"\
744       "punpckhbw %%mm7, %%mm3\n"\
745       "paddw " #in1 ", " #in0 "\n"\
746       "paddw %%mm3, %%mm2\n"\
747       "paddw %%mm2, " #in0 "\n"\
748       "paddw " #in0 ", %%mm6\n"
749
750
751   asm volatile (
752       "movl %4,%%ecx\n"
753       "pxor %%mm6,%%mm6\n"
754       "pcmpeqw %%mm7,%%mm7\n"
755       "psllw $15, %%mm7\n"
756       "packsswb %%mm7, %%mm7\n"
757       "movq (%0),%%mm0\n"
758       "movq (%1),%%mm2\n"
759       "movq 8(%0),%%mm1\n"
760       "movq 8(%1),%%mm3\n"
761       "add %3,%0\n"
762       "add %3,%1\n"
763       "subl $2, %%ecx\n"
764       "psubb %%mm2, %%mm0\n"
765       "psubb %%mm3, %%mm1\n"
766       "pxor %%mm7, %%mm0\n"
767       "pxor %%mm7, %%mm1\n"
768       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
769       "1:\n"
770
771       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
772
773       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
774
775       "subl $2, %%ecx\n"
776       "jnz 1b\n"
777
778       "movq %%mm6,%%mm0\n"
779       "psrlq $32, %%mm6\n"
780       "paddw %%mm6,%%mm0\n"
781       "movq %%mm0,%%mm6\n"
782       "psrlq $16, %%mm0\n"
783       "paddw %%mm6,%%mm0\n"
784       "movd %%mm0,%2\n"
785       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
786       : "r" ((x86_reg)line_size) , "m" (h)
787       : "%ecx");
788     return tmp & 0x7FFF;
789 }
790 #undef SUM
791
792 static int vsad16_mmx2(void *v, uint8_t * pix1, uint8_t * pix2, int line_size, int h) {
793     int tmp;
794
795     assert( (((int)pix1) & 7) == 0);
796     assert( (((int)pix2) & 7) == 0);
797     assert((line_size &7) ==0);
798
799 #define SUM(in0, in1, out0, out1) \
800       "movq (%0)," #out0 "\n"\
801       "movq (%1),%%mm2\n"\
802       "movq 8(%0)," #out1 "\n"\
803       "movq 8(%1),%%mm3\n"\
804       "add %3,%0\n"\
805       "add %3,%1\n"\
806       "psubb %%mm2, " #out0 "\n"\
807       "psubb %%mm3, " #out1 "\n"\
808       "pxor %%mm7, " #out0 "\n"\
809       "pxor %%mm7, " #out1 "\n"\
810       "psadbw " #out0 ", " #in0 "\n"\
811       "psadbw " #out1 ", " #in1 "\n"\
812       "paddw " #in1 ", " #in0 "\n"\
813       "paddw " #in0 ", %%mm6\n"
814
815   asm volatile (
816       "movl %4,%%ecx\n"
817       "pxor %%mm6,%%mm6\n"
818       "pcmpeqw %%mm7,%%mm7\n"
819       "psllw $15, %%mm7\n"
820       "packsswb %%mm7, %%mm7\n"
821       "movq (%0),%%mm0\n"
822       "movq (%1),%%mm2\n"
823       "movq 8(%0),%%mm1\n"
824       "movq 8(%1),%%mm3\n"
825       "add %3,%0\n"
826       "add %3,%1\n"
827       "subl $2, %%ecx\n"
828       "psubb %%mm2, %%mm0\n"
829       "psubb %%mm3, %%mm1\n"
830       "pxor %%mm7, %%mm0\n"
831       "pxor %%mm7, %%mm1\n"
832       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
833       "1:\n"
834
835       SUM(%%mm4, %%mm5, %%mm0, %%mm1)
836
837       SUM(%%mm0, %%mm1, %%mm4, %%mm5)
838
839       "subl $2, %%ecx\n"
840       "jnz 1b\n"
841
842       "movd %%mm6,%2\n"
843       : "+r" (pix1), "+r" (pix2), "=r"(tmp)
844       : "r" ((x86_reg)line_size) , "m" (h)
845       : "%ecx");
846     return tmp;
847 }
848 #undef SUM
849
850 static void diff_bytes_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w){
851     x86_reg i=0;
852     asm volatile(
853         "1:                             \n\t"
854         "movq  (%2, %0), %%mm0          \n\t"
855         "movq  (%1, %0), %%mm1          \n\t"
856         "psubb %%mm0, %%mm1             \n\t"
857         "movq %%mm1, (%3, %0)           \n\t"
858         "movq 8(%2, %0), %%mm0          \n\t"
859         "movq 8(%1, %0), %%mm1          \n\t"
860         "psubb %%mm0, %%mm1             \n\t"
861         "movq %%mm1, 8(%3, %0)          \n\t"
862         "add $16, %0                    \n\t"
863         "cmp %4, %0                     \n\t"
864         " jb 1b                         \n\t"
865         : "+r" (i)
866         : "r"(src1), "r"(src2), "r"(dst), "r"((x86_reg)w-15)
867     );
868     for(; i<w; i++)
869         dst[i+0] = src1[i+0]-src2[i+0];
870 }
871
872 static void sub_hfyu_median_prediction_mmx2(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w, int *left, int *left_top){
873     x86_reg i=0;
874     uint8_t l, lt;
875
876     asm volatile(
877         "1:                             \n\t"
878         "movq  -1(%1, %0), %%mm0        \n\t" // LT
879         "movq  (%1, %0), %%mm1          \n\t" // T
880         "movq  -1(%2, %0), %%mm2        \n\t" // L
881         "movq  (%2, %0), %%mm3          \n\t" // X
882         "movq %%mm2, %%mm4              \n\t" // L
883         "psubb %%mm0, %%mm2             \n\t"
884         "paddb %%mm1, %%mm2             \n\t" // L + T - LT
885         "movq %%mm4, %%mm5              \n\t" // L
886         "pmaxub %%mm1, %%mm4            \n\t" // max(T, L)
887         "pminub %%mm5, %%mm1            \n\t" // min(T, L)
888         "pminub %%mm2, %%mm4            \n\t"
889         "pmaxub %%mm1, %%mm4            \n\t"
890         "psubb %%mm4, %%mm3             \n\t" // dst - pred
891         "movq %%mm3, (%3, %0)           \n\t"
892         "add $8, %0                     \n\t"
893         "cmp %4, %0                     \n\t"
894         " jb 1b                         \n\t"
895         : "+r" (i)
896         : "r"(src1), "r"(src2), "r"(dst), "r"((x86_reg)w)
897     );
898
899     l= *left;
900     lt= *left_top;
901
902     dst[0]= src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt)&0xFF);
903
904     *left_top= src1[w-1];
905     *left    = src2[w-1];
906 }
907
908 #define DIFF_PIXELS_1(m,a,t,p1,p2)\
909     "mov"#m" "#p1", "#a"              \n\t"\
910     "mov"#m" "#p2", "#t"              \n\t"\
911     "punpcklbw "#a", "#t"             \n\t"\
912     "punpcklbw "#a", "#a"             \n\t"\
913     "psubw     "#t", "#a"             \n\t"\
914
915 #define DIFF_PIXELS_8(m0,m1,mm,p1,p2,stride,temp) {\
916     uint8_t *p1b=p1, *p2b=p2;\
917     asm volatile(\
918         DIFF_PIXELS_1(m0, mm##0, mm##7, (%1), (%2))\
919         DIFF_PIXELS_1(m0, mm##1, mm##7, (%1,%3), (%2,%3))\
920         DIFF_PIXELS_1(m0, mm##2, mm##7, (%1,%3,2), (%2,%3,2))\
921         "add %4, %1                   \n\t"\
922         "add %4, %2                   \n\t"\
923         DIFF_PIXELS_1(m0, mm##3, mm##7, (%1), (%2))\
924         DIFF_PIXELS_1(m0, mm##4, mm##7, (%1,%3), (%2,%3))\
925         DIFF_PIXELS_1(m0, mm##5, mm##7, (%1,%3,2), (%2,%3,2))\
926         DIFF_PIXELS_1(m0, mm##6, mm##7, (%1,%4), (%2,%4))\
927         "mov"#m1" "#mm"0, %0          \n\t"\
928         DIFF_PIXELS_1(m0, mm##7, mm##0, (%1,%3,4), (%2,%3,4))\
929         "mov"#m1" %0, "#mm"0          \n\t"\
930         : "+m"(temp), "+r"(p1b), "+r"(p2b)\
931         : "r"((x86_reg)stride), "r"((x86_reg)stride*3)\
932     );\
933 }
934     //the "+m"(temp) is needed as gcc 2.95 sometimes fails to compile "=m"(temp)
935
936 #define DIFF_PIXELS_4x8(p1,p2,stride,temp) DIFF_PIXELS_8(d, q,   %%mm,  p1, p2, stride, temp)
937 #define DIFF_PIXELS_8x8(p1,p2,stride,temp) DIFF_PIXELS_8(q, dqa, %%xmm, p1, p2, stride, temp)
938
939 #define LBUTTERFLY2(a1,b1,a2,b2)\
940     "paddw " #b1 ", " #a1 "           \n\t"\
941     "paddw " #b2 ", " #a2 "           \n\t"\
942     "paddw " #b1 ", " #b1 "           \n\t"\
943     "paddw " #b2 ", " #b2 "           \n\t"\
944     "psubw " #a1 ", " #b1 "           \n\t"\
945     "psubw " #a2 ", " #b2 "           \n\t"
946
947 #define HADAMARD8(m0, m1, m2, m3, m4, m5, m6, m7)\
948         LBUTTERFLY2(m0, m1, m2, m3)\
949         LBUTTERFLY2(m4, m5, m6, m7)\
950         LBUTTERFLY2(m0, m2, m1, m3)\
951         LBUTTERFLY2(m4, m6, m5, m7)\
952         LBUTTERFLY2(m0, m4, m1, m5)\
953         LBUTTERFLY2(m2, m6, m3, m7)\
954
955 #define HADAMARD48 HADAMARD8(%%mm0, %%mm1, %%mm2, %%mm3, %%mm4, %%mm5, %%mm6, %%mm7)
956
957 #define MMABS_MMX(a,z)\
958     "pxor " #z ", " #z "              \n\t"\
959     "pcmpgtw " #a ", " #z "           \n\t"\
960     "pxor " #z ", " #a "              \n\t"\
961     "psubw " #z ", " #a "             \n\t"
962
963 #define MMABS_MMX2(a,z)\
964     "pxor " #z ", " #z "              \n\t"\
965     "psubw " #a ", " #z "             \n\t"\
966     "pmaxsw " #z ", " #a "            \n\t"
967
968 #define MMABS_SSSE3(a,z)\
969     "pabsw " #a ", " #a "             \n\t"
970
971 #define MMABS_SUM(a,z, sum)\
972     MMABS(a,z)\
973     "paddusw " #a ", " #sum "         \n\t"
974
975 #define MMABS_SUM_8x8_NOSPILL\
976     MMABS(%%xmm0, %%xmm8)\
977     MMABS(%%xmm1, %%xmm9)\
978     MMABS_SUM(%%xmm2, %%xmm8, %%xmm0)\
979     MMABS_SUM(%%xmm3, %%xmm9, %%xmm1)\
980     MMABS_SUM(%%xmm4, %%xmm8, %%xmm0)\
981     MMABS_SUM(%%xmm5, %%xmm9, %%xmm1)\
982     MMABS_SUM(%%xmm6, %%xmm8, %%xmm0)\
983     MMABS_SUM(%%xmm7, %%xmm9, %%xmm1)\
984     "paddusw %%xmm1, %%xmm0           \n\t"
985
986 #ifdef ARCH_X86_64
987 #define MMABS_SUM_8x8_SSE2 MMABS_SUM_8x8_NOSPILL
988 #else
989 #define MMABS_SUM_8x8_SSE2\
990     "movdqa %%xmm7, (%1)              \n\t"\
991     MMABS(%%xmm0, %%xmm7)\
992     MMABS(%%xmm1, %%xmm7)\
993     MMABS_SUM(%%xmm2, %%xmm7, %%xmm0)\
994     MMABS_SUM(%%xmm3, %%xmm7, %%xmm1)\
995     MMABS_SUM(%%xmm4, %%xmm7, %%xmm0)\
996     MMABS_SUM(%%xmm5, %%xmm7, %%xmm1)\
997     MMABS_SUM(%%xmm6, %%xmm7, %%xmm0)\
998     "movdqa (%1), %%xmm2              \n\t"\
999     MMABS_SUM(%%xmm2, %%xmm7, %%xmm1)\
1000     "paddusw %%xmm1, %%xmm0           \n\t"
1001 #endif
1002
1003 #define LOAD4(o, a, b, c, d)\
1004     "movq "#o"(%1),    "#a"           \n\t"\
1005     "movq "#o"+8(%1),  "#b"           \n\t"\
1006     "movq "#o"+16(%1), "#c"           \n\t"\
1007     "movq "#o"+24(%1), "#d"           \n\t"\
1008
1009 #define STORE4(o, a, b, c, d)\
1010     "movq "#a", "#o"(%1)              \n\t"\
1011     "movq "#b", "#o"+8(%1)            \n\t"\
1012     "movq "#c", "#o"+16(%1)           \n\t"\
1013     "movq "#d", "#o"+24(%1)           \n\t"\
1014
1015 /* FIXME: HSUM_* saturates at 64k, while an 8x8 hadamard or dct block can get up to
1016  * about 100k on extreme inputs. But that's very unlikely to occur in natural video,
1017  * and it's even more unlikely to not have any alternative mvs/modes with lower cost. */
1018 #define HSUM_MMX(a, t, dst)\
1019     "movq "#a", "#t"                  \n\t"\
1020     "psrlq $32, "#a"                  \n\t"\
1021     "paddusw "#t", "#a"               \n\t"\
1022     "movq "#a", "#t"                  \n\t"\
1023     "psrlq $16, "#a"                  \n\t"\
1024     "paddusw "#t", "#a"               \n\t"\
1025     "movd "#a", "#dst"                \n\t"\
1026
1027 #define HSUM_MMX2(a, t, dst)\
1028     "pshufw $0x0E, "#a", "#t"         \n\t"\
1029     "paddusw "#t", "#a"               \n\t"\
1030     "pshufw $0x01, "#a", "#t"         \n\t"\
1031     "paddusw "#t", "#a"               \n\t"\
1032     "movd "#a", "#dst"                \n\t"\
1033
1034 #define HSUM_SSE2(a, t, dst)\
1035     "movhlps "#a", "#t"               \n\t"\
1036     "paddusw "#t", "#a"               \n\t"\
1037     "pshuflw $0x0E, "#a", "#t"        \n\t"\
1038     "paddusw "#t", "#a"               \n\t"\
1039     "pshuflw $0x01, "#a", "#t"        \n\t"\
1040     "paddusw "#t", "#a"               \n\t"\
1041     "movd "#a", "#dst"                \n\t"\
1042
1043 #define HADAMARD8_DIFF_MMX(cpu) \
1044 static int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){\
1045     DECLARE_ALIGNED_8(uint64_t, temp[13]);\
1046     int sum;\
1047 \
1048     assert(h==8);\
1049 \
1050     DIFF_PIXELS_4x8(src1, src2, stride, temp[0]);\
1051 \
1052     asm volatile(\
1053         HADAMARD48\
1054 \
1055         "movq %%mm7, 96(%1)             \n\t"\
1056 \
1057         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)\
1058         STORE4(0 , %%mm0, %%mm3, %%mm7, %%mm2)\
1059 \
1060         "movq 96(%1), %%mm7             \n\t"\
1061         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)\
1062         STORE4(64, %%mm4, %%mm7, %%mm0, %%mm6)\
1063 \
1064         : "=r" (sum)\
1065         : "r"(temp)\
1066     );\
1067 \
1068     DIFF_PIXELS_4x8(src1+4, src2+4, stride, temp[4]);\
1069 \
1070     asm volatile(\
1071         HADAMARD48\
1072 \
1073         "movq %%mm7, 96(%1)             \n\t"\
1074 \
1075         TRANSPOSE4(%%mm0, %%mm1, %%mm2, %%mm3, %%mm7)\
1076         STORE4(32, %%mm0, %%mm3, %%mm7, %%mm2)\
1077 \
1078         "movq 96(%1), %%mm7             \n\t"\
1079         TRANSPOSE4(%%mm4, %%mm5, %%mm6, %%mm7, %%mm0)\
1080         "movq %%mm7, %%mm5              \n\t"/*FIXME remove*/\
1081         "movq %%mm6, %%mm7              \n\t"\
1082         "movq %%mm0, %%mm6              \n\t"\
1083 \
1084         LOAD4(64, %%mm0, %%mm1, %%mm2, %%mm3)\
1085 \
1086         HADAMARD48\
1087         "movq %%mm7, 64(%1)             \n\t"\
1088         MMABS(%%mm0, %%mm7)\
1089         MMABS(%%mm1, %%mm7)\
1090         MMABS_SUM(%%mm2, %%mm7, %%mm0)\
1091         MMABS_SUM(%%mm3, %%mm7, %%mm1)\
1092         MMABS_SUM(%%mm4, %%mm7, %%mm0)\
1093         MMABS_SUM(%%mm5, %%mm7, %%mm1)\
1094         MMABS_SUM(%%mm6, %%mm7, %%mm0)\
1095         "movq 64(%1), %%mm2             \n\t"\
1096         MMABS_SUM(%%mm2, %%mm7, %%mm1)\
1097         "paddusw %%mm1, %%mm0           \n\t"\
1098         "movq %%mm0, 64(%1)             \n\t"\
1099 \
1100         LOAD4(0 , %%mm0, %%mm1, %%mm2, %%mm3)\
1101         LOAD4(32, %%mm4, %%mm5, %%mm6, %%mm7)\
1102 \
1103         HADAMARD48\
1104         "movq %%mm7, (%1)               \n\t"\
1105         MMABS(%%mm0, %%mm7)\
1106         MMABS(%%mm1, %%mm7)\
1107         MMABS_SUM(%%mm2, %%mm7, %%mm0)\
1108         MMABS_SUM(%%mm3, %%mm7, %%mm1)\
1109         MMABS_SUM(%%mm4, %%mm7, %%mm0)\
1110         MMABS_SUM(%%mm5, %%mm7, %%mm1)\
1111         MMABS_SUM(%%mm6, %%mm7, %%mm0)\
1112         "movq (%1), %%mm2               \n\t"\
1113         MMABS_SUM(%%mm2, %%mm7, %%mm1)\
1114         "paddusw 64(%1), %%mm0          \n\t"\
1115         "paddusw %%mm1, %%mm0           \n\t"\
1116 \
1117         HSUM(%%mm0, %%mm1, %0)\
1118 \
1119         : "=r" (sum)\
1120         : "r"(temp)\
1121     );\
1122     return sum&0xFFFF;\
1123 }\
1124 WRAPPER8_16_SQ(hadamard8_diff_##cpu, hadamard8_diff16_##cpu)
1125
1126 #define HADAMARD8_DIFF_SSE2(cpu) \
1127 static int hadamard8_diff_##cpu(void *s, uint8_t *src1, uint8_t *src2, int stride, int h){\
1128     DECLARE_ALIGNED_16(uint64_t, temp[4]);\
1129     int sum;\
1130 \
1131     assert(h==8);\
1132 \
1133     DIFF_PIXELS_8x8(src1, src2, stride, temp[0]);\
1134 \
1135     asm volatile(\
1136         HADAMARD8(%%xmm0, %%xmm1, %%xmm2, %%xmm3, %%xmm4, %%xmm5, %%xmm6, %%xmm7)\
1137         TRANSPOSE8(%%xmm0, %%xmm1, %%xmm2, %%xmm3, %%xmm4, %%xmm5, %%xmm6, %%xmm7, (%1))\
1138         HADAMARD8(%%xmm0, %%xmm5, %%xmm7, %%xmm3, %%xmm6, %%xmm4, %%xmm2, %%xmm1)\
1139         MMABS_SUM_8x8\
1140         HSUM_SSE2(%%xmm0, %%xmm1, %0)\
1141         : "=r" (sum)\
1142         : "r"(temp)\
1143     );\
1144     return sum&0xFFFF;\
1145 }\
1146 WRAPPER8_16_SQ(hadamard8_diff_##cpu, hadamard8_diff16_##cpu)
1147
1148 #define MMABS(a,z)         MMABS_MMX(a,z)
1149 #define HSUM(a,t,dst)      HSUM_MMX(a,t,dst)
1150 HADAMARD8_DIFF_MMX(mmx)
1151 #undef MMABS
1152 #undef HSUM
1153
1154 #define MMABS(a,z)         MMABS_MMX2(a,z)
1155 #define MMABS_SUM_8x8      MMABS_SUM_8x8_SSE2
1156 #define HSUM(a,t,dst)      HSUM_MMX2(a,t,dst)
1157 HADAMARD8_DIFF_MMX(mmx2)
1158 HADAMARD8_DIFF_SSE2(sse2)
1159 #undef MMABS
1160 #undef MMABS_SUM_8x8
1161 #undef HSUM
1162
1163 #ifdef HAVE_SSSE3
1164 #define MMABS(a,z)         MMABS_SSSE3(a,z)
1165 #define MMABS_SUM_8x8      MMABS_SUM_8x8_NOSPILL
1166 HADAMARD8_DIFF_SSE2(ssse3)
1167 #undef MMABS
1168 #undef MMABS_SUM_8x8
1169 #endif
1170
1171 #define DCT_SAD4(m,mm,o)\
1172     "mov"#m" "#o"+ 0(%1), "#mm"2      \n\t"\
1173     "mov"#m" "#o"+16(%1), "#mm"3      \n\t"\
1174     "mov"#m" "#o"+32(%1), "#mm"4      \n\t"\
1175     "mov"#m" "#o"+48(%1), "#mm"5      \n\t"\
1176     MMABS_SUM(mm##2, mm##6, mm##0)\
1177     MMABS_SUM(mm##3, mm##7, mm##1)\
1178     MMABS_SUM(mm##4, mm##6, mm##0)\
1179     MMABS_SUM(mm##5, mm##7, mm##1)\
1180
1181 #define DCT_SAD_MMX\
1182     "pxor %%mm0, %%mm0                \n\t"\
1183     "pxor %%mm1, %%mm1                \n\t"\
1184     DCT_SAD4(q, %%mm, 0)\
1185     DCT_SAD4(q, %%mm, 8)\
1186     DCT_SAD4(q, %%mm, 64)\
1187     DCT_SAD4(q, %%mm, 72)\
1188     "paddusw %%mm1, %%mm0             \n\t"\
1189     HSUM(%%mm0, %%mm1, %0)
1190
1191 #define DCT_SAD_SSE2\
1192     "pxor %%xmm0, %%xmm0              \n\t"\
1193     "pxor %%xmm1, %%xmm1              \n\t"\
1194     DCT_SAD4(dqa, %%xmm, 0)\
1195     DCT_SAD4(dqa, %%xmm, 64)\
1196     "paddusw %%xmm1, %%xmm0           \n\t"\
1197     HSUM(%%xmm0, %%xmm1, %0)
1198
1199 #define DCT_SAD_FUNC(cpu) \
1200 static int sum_abs_dctelem_##cpu(DCTELEM *block){\
1201     int sum;\
1202     asm volatile(\
1203         DCT_SAD\
1204         :"=r"(sum)\
1205         :"r"(block)\
1206     );\
1207     return sum&0xFFFF;\
1208 }
1209
1210 #define DCT_SAD       DCT_SAD_MMX
1211 #define HSUM(a,t,dst) HSUM_MMX(a,t,dst)
1212 #define MMABS(a,z)    MMABS_MMX(a,z)
1213 DCT_SAD_FUNC(mmx)
1214 #undef MMABS
1215 #undef HSUM
1216
1217 #define HSUM(a,t,dst) HSUM_MMX2(a,t,dst)
1218 #define MMABS(a,z)    MMABS_MMX2(a,z)
1219 DCT_SAD_FUNC(mmx2)
1220 #undef HSUM
1221 #undef DCT_SAD
1222
1223 #define DCT_SAD       DCT_SAD_SSE2
1224 #define HSUM(a,t,dst) HSUM_SSE2(a,t,dst)
1225 DCT_SAD_FUNC(sse2)
1226 #undef MMABS
1227
1228 #ifdef HAVE_SSSE3
1229 #define MMABS(a,z)    MMABS_SSSE3(a,z)
1230 DCT_SAD_FUNC(ssse3)
1231 #undef MMABS
1232 #endif
1233 #undef HSUM
1234 #undef DCT_SAD
1235
1236 static int ssd_int8_vs_int16_mmx(const int8_t *pix1, const int16_t *pix2, int size){
1237     int sum;
1238     x86_reg i=size;
1239     asm volatile(
1240         "pxor %%mm4, %%mm4 \n"
1241         "1: \n"
1242         "sub $8, %0 \n"
1243         "movq (%2,%0), %%mm2 \n"
1244         "movq (%3,%0,2), %%mm0 \n"
1245         "movq 8(%3,%0,2), %%mm1 \n"
1246         "punpckhbw %%mm2, %%mm3 \n"
1247         "punpcklbw %%mm2, %%mm2 \n"
1248         "psraw $8, %%mm3 \n"
1249         "psraw $8, %%mm2 \n"
1250         "psubw %%mm3, %%mm1 \n"
1251         "psubw %%mm2, %%mm0 \n"
1252         "pmaddwd %%mm1, %%mm1 \n"
1253         "pmaddwd %%mm0, %%mm0 \n"
1254         "paddd %%mm1, %%mm4 \n"
1255         "paddd %%mm0, %%mm4 \n"
1256         "jg 1b \n"
1257         "movq %%mm4, %%mm3 \n"
1258         "psrlq $32, %%mm3 \n"
1259         "paddd %%mm3, %%mm4 \n"
1260         "movd %%mm4, %1 \n"
1261         :"+r"(i), "=r"(sum)
1262         :"r"(pix1), "r"(pix2)
1263     );
1264     return sum;
1265 }
1266
1267 #define PHADDD(a, t)\
1268     "movq "#a", "#t"                  \n\t"\
1269     "psrlq $32, "#a"                  \n\t"\
1270     "paddd "#t", "#a"                 \n\t"
1271 /*
1272    pmulhw: dst[0-15]=(src[0-15]*dst[0-15])[16-31]
1273    pmulhrw: dst[0-15]=(src[0-15]*dst[0-15] + 0x8000)[16-31]
1274    pmulhrsw: dst[0-15]=(src[0-15]*dst[0-15] + 0x4000)[15-30]
1275  */
1276 #define PMULHRW(x, y, s, o)\
1277     "pmulhw " #s ", "#x "            \n\t"\
1278     "pmulhw " #s ", "#y "            \n\t"\
1279     "paddw " #o ", "#x "             \n\t"\
1280     "paddw " #o ", "#y "             \n\t"\
1281     "psraw $1, "#x "                 \n\t"\
1282     "psraw $1, "#y "                 \n\t"
1283 #define DEF(x) x ## _mmx
1284 #define SET_RND MOVQ_WONE
1285 #define SCALE_OFFSET 1
1286
1287 #include "dsputil_mmx_qns.h"
1288
1289 #undef DEF
1290 #undef SET_RND
1291 #undef SCALE_OFFSET
1292 #undef PMULHRW
1293
1294 #define DEF(x) x ## _3dnow
1295 #define SET_RND(x)
1296 #define SCALE_OFFSET 0
1297 #define PMULHRW(x, y, s, o)\
1298     "pmulhrw " #s ", "#x "           \n\t"\
1299     "pmulhrw " #s ", "#y "           \n\t"
1300
1301 #include "dsputil_mmx_qns.h"
1302
1303 #undef DEF
1304 #undef SET_RND
1305 #undef SCALE_OFFSET
1306 #undef PMULHRW
1307
1308 #ifdef HAVE_SSSE3
1309 #undef PHADDD
1310 #define DEF(x) x ## _ssse3
1311 #define SET_RND(x)
1312 #define SCALE_OFFSET -1
1313 #define PHADDD(a, t)\
1314     "pshufw $0x0E, "#a", "#t"         \n\t"\
1315     "paddd "#t", "#a"                 \n\t" /* faster than phaddd on core2 */
1316 #define PMULHRW(x, y, s, o)\
1317     "pmulhrsw " #s ", "#x "          \n\t"\
1318     "pmulhrsw " #s ", "#y "          \n\t"
1319
1320 #include "dsputil_mmx_qns.h"
1321
1322 #undef DEF
1323 #undef SET_RND
1324 #undef SCALE_OFFSET
1325 #undef PMULHRW
1326 #undef PHADDD
1327 #endif //HAVE_SSSE3
1328
1329
1330 /* FLAC specific */
1331 void ff_flac_compute_autocorr_sse2(const int32_t *data, int len, int lag,
1332                                    double *autoc);
1333
1334
1335 void dsputilenc_init_mmx(DSPContext* c, AVCodecContext *avctx)
1336 {
1337     if (mm_flags & MM_MMX) {
1338         const int dct_algo = avctx->dct_algo;
1339         if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
1340             if(mm_flags & MM_SSE2){
1341                 c->fdct = ff_fdct_sse2;
1342             }else if(mm_flags & MM_MMXEXT){
1343                 c->fdct = ff_fdct_mmx2;
1344             }else{
1345                 c->fdct = ff_fdct_mmx;
1346             }
1347         }
1348
1349         c->get_pixels = get_pixels_mmx;
1350         c->diff_pixels = diff_pixels_mmx;
1351         c->pix_sum = pix_sum16_mmx;
1352
1353         c->diff_bytes= diff_bytes_mmx;
1354         c->sum_abs_dctelem= sum_abs_dctelem_mmx;
1355
1356         c->hadamard8_diff[0]= hadamard8_diff16_mmx;
1357         c->hadamard8_diff[1]= hadamard8_diff_mmx;
1358
1359         c->pix_norm1 = pix_norm1_mmx;
1360         c->sse[0] = (mm_flags & MM_SSE2) ? sse16_sse2 : sse16_mmx;
1361           c->sse[1] = sse8_mmx;
1362         c->vsad[4]= vsad_intra16_mmx;
1363
1364         c->nsse[0] = nsse16_mmx;
1365         c->nsse[1] = nsse8_mmx;
1366         if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1367             c->vsad[0] = vsad16_mmx;
1368         }
1369
1370         if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1371             c->try_8x8basis= try_8x8basis_mmx;
1372         }
1373         c->add_8x8basis= add_8x8basis_mmx;
1374
1375         c->ssd_int8_vs_int16 = ssd_int8_vs_int16_mmx;
1376
1377
1378         if (mm_flags & MM_MMXEXT) {
1379             c->sum_abs_dctelem= sum_abs_dctelem_mmx2;
1380             c->hadamard8_diff[0]= hadamard8_diff16_mmx2;
1381             c->hadamard8_diff[1]= hadamard8_diff_mmx2;
1382             c->vsad[4]= vsad_intra16_mmx2;
1383
1384             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1385                 c->vsad[0] = vsad16_mmx2;
1386             }
1387
1388             c->sub_hfyu_median_prediction= sub_hfyu_median_prediction_mmx2;
1389         }
1390
1391         if(mm_flags & MM_SSE2){
1392             c->sum_abs_dctelem= sum_abs_dctelem_sse2;
1393             c->hadamard8_diff[0]= hadamard8_diff16_sse2;
1394             c->hadamard8_diff[1]= hadamard8_diff_sse2;
1395             if (ENABLE_FLAC_ENCODER)
1396                 c->flac_compute_autocorr = ff_flac_compute_autocorr_sse2;
1397         }
1398
1399 #ifdef HAVE_SSSE3
1400         if(mm_flags & MM_SSSE3){
1401             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1402                 c->try_8x8basis= try_8x8basis_ssse3;
1403             }
1404             c->add_8x8basis= add_8x8basis_ssse3;
1405             c->sum_abs_dctelem= sum_abs_dctelem_ssse3;
1406             c->hadamard8_diff[0]= hadamard8_diff16_ssse3;
1407             c->hadamard8_diff[1]= hadamard8_diff_ssse3;
1408         }
1409 #endif
1410
1411         if(mm_flags & MM_3DNOW){
1412             if(!(avctx->flags & CODEC_FLAG_BITEXACT)){
1413                 c->try_8x8basis= try_8x8basis_3dnow;
1414             }
1415             c->add_8x8basis= add_8x8basis_3dnow;
1416         }
1417     }
1418
1419     dsputil_init_pix_mmx(c, avctx);
1420 }