dsputil: Drop unused bit_depth parameter from all init functions
[ffmpeg.git] / libavcodec / x86 / 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  * MMX optimization by Nick Kurshev <nickols_k@mail.ru>
7  *
8  * This file is part of Libav.
9  *
10  * Libav is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * Libav is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with Libav; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24
25 #include "libavutil/attributes.h"
26 #include "libavutil/cpu.h"
27 #include "libavutil/x86/asm.h"
28 #include "libavutil/x86/cpu.h"
29 #include "libavcodec/dsputil.h"
30 #include "libavcodec/mpegvideo.h"
31 #include "dsputil_x86.h"
32
33 #if HAVE_INLINE_ASM
34
35 static int sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
36                     int line_size, int h)
37 {
38     int tmp;
39
40     __asm__ volatile (
41         "movl         %4, %%ecx          \n"
42         "shr          $1, %%ecx          \n"
43         "pxor      %%mm0, %%mm0          \n" /* mm0 = 0 */
44         "pxor      %%mm7, %%mm7          \n" /* mm7 holds the sum */
45         "1:                              \n"
46         "movq       (%0), %%mm1          \n" /* mm1 = pix1[0][0 - 7] */
47         "movq       (%1), %%mm2          \n" /* mm2 = pix2[0][0 - 7] */
48         "movq   (%0, %3), %%mm3          \n" /* mm3 = pix1[1][0 - 7] */
49         "movq   (%1, %3), %%mm4          \n" /* mm4 = pix2[1][0 - 7] */
50
51         /* todo: mm1-mm2, mm3-mm4 */
52         /* algo: subtract mm1 from mm2 with saturation and vice versa */
53         /*       OR the results to get absolute difference */
54         "movq      %%mm1, %%mm5          \n"
55         "movq      %%mm3, %%mm6          \n"
56         "psubusb   %%mm2, %%mm1          \n"
57         "psubusb   %%mm4, %%mm3          \n"
58         "psubusb   %%mm5, %%mm2          \n"
59         "psubusb   %%mm6, %%mm4          \n"
60
61         "por       %%mm1, %%mm2          \n"
62         "por       %%mm3, %%mm4          \n"
63
64         /* now convert to 16-bit vectors so we can square them */
65         "movq      %%mm2, %%mm1          \n"
66         "movq      %%mm4, %%mm3          \n"
67
68         "punpckhbw %%mm0, %%mm2          \n"
69         "punpckhbw %%mm0, %%mm4          \n"
70         "punpcklbw %%mm0, %%mm1          \n" /* mm1 now spread over (mm1, mm2) */
71         "punpcklbw %%mm0, %%mm3          \n" /* mm4 now spread over (mm3, mm4) */
72
73         "pmaddwd   %%mm2, %%mm2          \n"
74         "pmaddwd   %%mm4, %%mm4          \n"
75         "pmaddwd   %%mm1, %%mm1          \n"
76         "pmaddwd   %%mm3, %%mm3          \n"
77
78         "lea (%0, %3, 2), %0             \n" /* pix1 += 2 * line_size */
79         "lea (%1, %3, 2), %1             \n" /* pix2 += 2 * line_size */
80
81         "paddd     %%mm2, %%mm1          \n"
82         "paddd     %%mm4, %%mm3          \n"
83         "paddd     %%mm1, %%mm7          \n"
84         "paddd     %%mm3, %%mm7          \n"
85
86         "decl      %%ecx                 \n"
87         "jnz       1b                    \n"
88
89         "movq      %%mm7, %%mm1          \n"
90         "psrlq       $32, %%mm7          \n" /* shift hi dword to lo */
91         "paddd     %%mm7, %%mm1          \n"
92         "movd      %%mm1, %2             \n"
93         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
94         : "r" ((x86_reg) line_size), "m" (h)
95         : "%ecx");
96
97     return tmp;
98 }
99
100 static int sse16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
101                      int line_size, int h)
102 {
103     int tmp;
104
105     __asm__ volatile (
106         "movl %4, %%ecx\n"
107         "pxor %%mm0, %%mm0\n"    /* mm0 = 0 */
108         "pxor %%mm7, %%mm7\n"    /* mm7 holds the sum */
109         "1:\n"
110         "movq (%0), %%mm1\n"     /* mm1 = pix1[0 -  7] */
111         "movq (%1), %%mm2\n"     /* mm2 = pix2[0 -  7] */
112         "movq 8(%0), %%mm3\n"    /* mm3 = pix1[8 - 15] */
113         "movq 8(%1), %%mm4\n"    /* mm4 = pix2[8 - 15] */
114
115         /* todo: mm1-mm2, mm3-mm4 */
116         /* algo: subtract mm1 from mm2 with saturation and vice versa */
117         /*       OR the results to get absolute difference */
118         "movq %%mm1, %%mm5\n"
119         "movq %%mm3, %%mm6\n"
120         "psubusb %%mm2, %%mm1\n"
121         "psubusb %%mm4, %%mm3\n"
122         "psubusb %%mm5, %%mm2\n"
123         "psubusb %%mm6, %%mm4\n"
124
125         "por %%mm1, %%mm2\n"
126         "por %%mm3, %%mm4\n"
127
128         /* now convert to 16-bit vectors so we can square them */
129         "movq %%mm2, %%mm1\n"
130         "movq %%mm4, %%mm3\n"
131
132         "punpckhbw %%mm0, %%mm2\n"
133         "punpckhbw %%mm0, %%mm4\n"
134         "punpcklbw %%mm0, %%mm1\n" /* mm1 now spread over (mm1, mm2) */
135         "punpcklbw %%mm0, %%mm3\n" /* mm4 now spread over (mm3, mm4) */
136
137         "pmaddwd %%mm2, %%mm2\n"
138         "pmaddwd %%mm4, %%mm4\n"
139         "pmaddwd %%mm1, %%mm1\n"
140         "pmaddwd %%mm3, %%mm3\n"
141
142         "add %3, %0\n"
143         "add %3, %1\n"
144
145         "paddd %%mm2, %%mm1\n"
146         "paddd %%mm4, %%mm3\n"
147         "paddd %%mm1, %%mm7\n"
148         "paddd %%mm3, %%mm7\n"
149
150         "decl %%ecx\n"
151         "jnz 1b\n"
152
153         "movq %%mm7, %%mm1\n"
154         "psrlq $32, %%mm7\n"    /* shift hi dword to lo */
155         "paddd %%mm7, %%mm1\n"
156         "movd %%mm1, %2\n"
157         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
158         : "r" ((x86_reg) line_size), "m" (h)
159         : "%ecx");
160
161     return tmp;
162 }
163
164 static int hf_noise8_mmx(uint8_t *pix1, int line_size, int h)
165 {
166     int tmp;
167
168     __asm__ volatile (
169         "movl %3, %%ecx\n"
170         "pxor %%mm7, %%mm7\n"
171         "pxor %%mm6, %%mm6\n"
172
173         "movq (%0), %%mm0\n"
174         "movq %%mm0, %%mm1\n"
175         "psllq $8, %%mm0\n"
176         "psrlq $8, %%mm1\n"
177         "psrlq $8, %%mm0\n"
178         "movq %%mm0, %%mm2\n"
179         "movq %%mm1, %%mm3\n"
180         "punpcklbw %%mm7, %%mm0\n"
181         "punpcklbw %%mm7, %%mm1\n"
182         "punpckhbw %%mm7, %%mm2\n"
183         "punpckhbw %%mm7, %%mm3\n"
184         "psubw %%mm1, %%mm0\n"
185         "psubw %%mm3, %%mm2\n"
186
187         "add %2, %0\n"
188
189         "movq (%0), %%mm4\n"
190         "movq %%mm4, %%mm1\n"
191         "psllq $8, %%mm4\n"
192         "psrlq $8, %%mm1\n"
193         "psrlq $8, %%mm4\n"
194         "movq %%mm4, %%mm5\n"
195         "movq %%mm1, %%mm3\n"
196         "punpcklbw %%mm7, %%mm4\n"
197         "punpcklbw %%mm7, %%mm1\n"
198         "punpckhbw %%mm7, %%mm5\n"
199         "punpckhbw %%mm7, %%mm3\n"
200         "psubw %%mm1, %%mm4\n"
201         "psubw %%mm3, %%mm5\n"
202         "psubw %%mm4, %%mm0\n"
203         "psubw %%mm5, %%mm2\n"
204         "pxor %%mm3, %%mm3\n"
205         "pxor %%mm1, %%mm1\n"
206         "pcmpgtw %%mm0, %%mm3\n\t"
207         "pcmpgtw %%mm2, %%mm1\n\t"
208         "pxor %%mm3, %%mm0\n"
209         "pxor %%mm1, %%mm2\n"
210         "psubw %%mm3, %%mm0\n"
211         "psubw %%mm1, %%mm2\n"
212         "paddw %%mm0, %%mm2\n"
213         "paddw %%mm2, %%mm6\n"
214
215         "add %2, %0\n"
216         "1:\n"
217
218         "movq (%0), %%mm0\n"
219         "movq %%mm0, %%mm1\n"
220         "psllq $8, %%mm0\n"
221         "psrlq $8, %%mm1\n"
222         "psrlq $8, %%mm0\n"
223         "movq %%mm0, %%mm2\n"
224         "movq %%mm1, %%mm3\n"
225         "punpcklbw %%mm7, %%mm0\n"
226         "punpcklbw %%mm7, %%mm1\n"
227         "punpckhbw %%mm7, %%mm2\n"
228         "punpckhbw %%mm7, %%mm3\n"
229         "psubw %%mm1, %%mm0\n"
230         "psubw %%mm3, %%mm2\n"
231         "psubw %%mm0, %%mm4\n"
232         "psubw %%mm2, %%mm5\n"
233         "pxor  %%mm3, %%mm3\n"
234         "pxor  %%mm1, %%mm1\n"
235         "pcmpgtw %%mm4, %%mm3\n\t"
236         "pcmpgtw %%mm5, %%mm1\n\t"
237         "pxor  %%mm3, %%mm4\n"
238         "pxor  %%mm1, %%mm5\n"
239         "psubw %%mm3, %%mm4\n"
240         "psubw %%mm1, %%mm5\n"
241         "paddw %%mm4, %%mm5\n"
242         "paddw %%mm5, %%mm6\n"
243
244         "add %2, %0\n"
245
246         "movq (%0), %%mm4\n"
247         "movq      %%mm4, %%mm1\n"
248         "psllq $8, %%mm4\n"
249         "psrlq $8, %%mm1\n"
250         "psrlq $8, %%mm4\n"
251         "movq      %%mm4, %%mm5\n"
252         "movq      %%mm1, %%mm3\n"
253         "punpcklbw %%mm7, %%mm4\n"
254         "punpcklbw %%mm7, %%mm1\n"
255         "punpckhbw %%mm7, %%mm5\n"
256         "punpckhbw %%mm7, %%mm3\n"
257         "psubw     %%mm1, %%mm4\n"
258         "psubw     %%mm3, %%mm5\n"
259         "psubw     %%mm4, %%mm0\n"
260         "psubw     %%mm5, %%mm2\n"
261         "pxor      %%mm3, %%mm3\n"
262         "pxor      %%mm1, %%mm1\n"
263         "pcmpgtw   %%mm0, %%mm3\n\t"
264         "pcmpgtw   %%mm2, %%mm1\n\t"
265         "pxor      %%mm3, %%mm0\n"
266         "pxor      %%mm1, %%mm2\n"
267         "psubw     %%mm3, %%mm0\n"
268         "psubw     %%mm1, %%mm2\n"
269         "paddw     %%mm0, %%mm2\n"
270         "paddw     %%mm2, %%mm6\n"
271
272         "add  %2, %0\n"
273         "subl $2, %%ecx\n"
274         " jnz 1b\n"
275
276         "movq      %%mm6, %%mm0\n"
277         "punpcklwd %%mm7, %%mm0\n"
278         "punpckhwd %%mm7, %%mm6\n"
279         "paddd     %%mm0, %%mm6\n"
280
281         "movq  %%mm6, %%mm0\n"
282         "psrlq $32,   %%mm6\n"
283         "paddd %%mm6, %%mm0\n"
284         "movd  %%mm0, %1\n"
285         : "+r" (pix1), "=r" (tmp)
286         : "r" ((x86_reg) line_size), "g" (h - 2)
287         : "%ecx");
288
289     return tmp;
290 }
291
292 static int hf_noise16_mmx(uint8_t *pix1, int line_size, int h)
293 {
294     int tmp;
295     uint8_t *pix = pix1;
296
297     __asm__ volatile (
298         "movl %3, %%ecx\n"
299         "pxor %%mm7, %%mm7\n"
300         "pxor %%mm6, %%mm6\n"
301
302         "movq (%0), %%mm0\n"
303         "movq 1(%0), %%mm1\n"
304         "movq %%mm0, %%mm2\n"
305         "movq %%mm1, %%mm3\n"
306         "punpcklbw %%mm7, %%mm0\n"
307         "punpcklbw %%mm7, %%mm1\n"
308         "punpckhbw %%mm7, %%mm2\n"
309         "punpckhbw %%mm7, %%mm3\n"
310         "psubw %%mm1, %%mm0\n"
311         "psubw %%mm3, %%mm2\n"
312
313         "add %2, %0\n"
314
315         "movq (%0), %%mm4\n"
316         "movq 1(%0), %%mm1\n"
317         "movq %%mm4, %%mm5\n"
318         "movq %%mm1, %%mm3\n"
319         "punpcklbw %%mm7, %%mm4\n"
320         "punpcklbw %%mm7, %%mm1\n"
321         "punpckhbw %%mm7, %%mm5\n"
322         "punpckhbw %%mm7, %%mm3\n"
323         "psubw %%mm1, %%mm4\n"
324         "psubw %%mm3, %%mm5\n"
325         "psubw %%mm4, %%mm0\n"
326         "psubw %%mm5, %%mm2\n"
327         "pxor %%mm3, %%mm3\n"
328         "pxor %%mm1, %%mm1\n"
329         "pcmpgtw %%mm0, %%mm3\n\t"
330         "pcmpgtw %%mm2, %%mm1\n\t"
331         "pxor %%mm3, %%mm0\n"
332         "pxor %%mm1, %%mm2\n"
333         "psubw %%mm3, %%mm0\n"
334         "psubw %%mm1, %%mm2\n"
335         "paddw %%mm0, %%mm2\n"
336         "paddw %%mm2, %%mm6\n"
337
338         "add %2, %0\n"
339         "1:\n"
340
341         "movq (%0), %%mm0\n"
342         "movq 1(%0), %%mm1\n"
343         "movq %%mm0, %%mm2\n"
344         "movq %%mm1, %%mm3\n"
345         "punpcklbw %%mm7, %%mm0\n"
346         "punpcklbw %%mm7, %%mm1\n"
347         "punpckhbw %%mm7, %%mm2\n"
348         "punpckhbw %%mm7, %%mm3\n"
349         "psubw %%mm1, %%mm0\n"
350         "psubw %%mm3, %%mm2\n"
351         "psubw %%mm0, %%mm4\n"
352         "psubw %%mm2, %%mm5\n"
353         "pxor %%mm3, %%mm3\n"
354         "pxor %%mm1, %%mm1\n"
355         "pcmpgtw %%mm4, %%mm3\n\t"
356         "pcmpgtw %%mm5, %%mm1\n\t"
357         "pxor %%mm3, %%mm4\n"
358         "pxor %%mm1, %%mm5\n"
359         "psubw %%mm3, %%mm4\n"
360         "psubw %%mm1, %%mm5\n"
361         "paddw %%mm4, %%mm5\n"
362         "paddw %%mm5, %%mm6\n"
363
364         "add %2, %0\n"
365
366         "movq (%0), %%mm4\n"
367         "movq 1(%0), %%mm1\n"
368         "movq %%mm4, %%mm5\n"
369         "movq %%mm1, %%mm3\n"
370         "punpcklbw %%mm7, %%mm4\n"
371         "punpcklbw %%mm7, %%mm1\n"
372         "punpckhbw %%mm7, %%mm5\n"
373         "punpckhbw %%mm7, %%mm3\n"
374         "psubw %%mm1, %%mm4\n"
375         "psubw %%mm3, %%mm5\n"
376         "psubw %%mm4, %%mm0\n"
377         "psubw %%mm5, %%mm2\n"
378         "pxor %%mm3, %%mm3\n"
379         "pxor %%mm1, %%mm1\n"
380         "pcmpgtw %%mm0, %%mm3\n\t"
381         "pcmpgtw %%mm2, %%mm1\n\t"
382         "pxor %%mm3, %%mm0\n"
383         "pxor %%mm1, %%mm2\n"
384         "psubw %%mm3, %%mm0\n"
385         "psubw %%mm1, %%mm2\n"
386         "paddw %%mm0, %%mm2\n"
387         "paddw %%mm2, %%mm6\n"
388
389         "add %2, %0\n"
390         "subl $2, %%ecx\n"
391         " jnz 1b\n"
392
393         "movq %%mm6, %%mm0\n"
394         "punpcklwd %%mm7, %%mm0\n"
395         "punpckhwd %%mm7, %%mm6\n"
396         "paddd %%mm0, %%mm6\n"
397
398         "movq %%mm6, %%mm0\n"
399         "psrlq $32, %%mm6\n"
400         "paddd %%mm6, %%mm0\n"
401         "movd %%mm0, %1\n"
402         : "+r" (pix1), "=r" (tmp)
403         : "r" ((x86_reg) line_size), "g" (h - 2)
404         : "%ecx");
405
406     return tmp + hf_noise8_mmx(pix + 8, line_size, h);
407 }
408
409 static int nsse16_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2,
410                       int line_size, int h)
411 {
412     int score1, score2;
413
414     if (c)
415         score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h);
416     else
417         score1 = sse16_mmx(c, pix1, pix2, line_size, h);
418     score2 = hf_noise16_mmx(pix1, line_size, h) -
419              hf_noise16_mmx(pix2, line_size, h);
420
421     if (c)
422         return score1 + FFABS(score2) * c->avctx->nsse_weight;
423     else
424         return score1 + FFABS(score2) * 8;
425 }
426
427 static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2,
428                      int line_size, int h)
429 {
430     int score1 = sse8_mmx(c, pix1, pix2, line_size, h);
431     int score2 = hf_noise8_mmx(pix1, line_size, h) -
432                  hf_noise8_mmx(pix2, line_size, h);
433
434     if (c)
435         return score1 + FFABS(score2) * c->avctx->nsse_weight;
436     else
437         return score1 + FFABS(score2) * 8;
438 }
439
440 static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy,
441                             int line_size, int h)
442 {
443     int tmp;
444
445     assert((((int) pix) & 7) == 0);
446     assert((line_size & 7) == 0);
447
448 #define SUM(in0, in1, out0, out1)               \
449     "movq (%0), %%mm2\n"                        \
450     "movq 8(%0), %%mm3\n"                       \
451     "add %2,%0\n"                               \
452     "movq %%mm2, " #out0 "\n"                   \
453     "movq %%mm3, " #out1 "\n"                   \
454     "psubusb " #in0 ", %%mm2\n"                 \
455     "psubusb " #in1 ", %%mm3\n"                 \
456     "psubusb " #out0 ", " #in0 "\n"             \
457     "psubusb " #out1 ", " #in1 "\n"             \
458     "por %%mm2, " #in0 "\n"                     \
459     "por %%mm3, " #in1 "\n"                     \
460     "movq " #in0 ", %%mm2\n"                    \
461     "movq " #in1 ", %%mm3\n"                    \
462     "punpcklbw %%mm7, " #in0 "\n"               \
463     "punpcklbw %%mm7, " #in1 "\n"               \
464     "punpckhbw %%mm7, %%mm2\n"                  \
465     "punpckhbw %%mm7, %%mm3\n"                  \
466     "paddw " #in1 ", " #in0 "\n"                \
467     "paddw %%mm3, %%mm2\n"                      \
468     "paddw %%mm2, " #in0 "\n"                   \
469     "paddw " #in0 ", %%mm6\n"
470
471
472     __asm__ volatile (
473         "movl    %3, %%ecx\n"
474         "pxor %%mm6, %%mm6\n"
475         "pxor %%mm7, %%mm7\n"
476         "movq  (%0), %%mm0\n"
477         "movq 8(%0), %%mm1\n"
478         "add %2, %0\n"
479         "jmp 2f\n"
480         "1:\n"
481
482         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
483         "2:\n"
484         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
485
486         "subl $2, %%ecx\n"
487         "jnz 1b\n"
488
489         "movq  %%mm6, %%mm0\n"
490         "psrlq $32,   %%mm6\n"
491         "paddw %%mm6, %%mm0\n"
492         "movq  %%mm0, %%mm6\n"
493         "psrlq $16,   %%mm0\n"
494         "paddw %%mm6, %%mm0\n"
495         "movd  %%mm0, %1\n"
496         : "+r" (pix), "=r" (tmp)
497         : "r" ((x86_reg) line_size), "m" (h)
498         : "%ecx");
499
500     return tmp & 0xFFFF;
501 }
502 #undef SUM
503
504 static int vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix, uint8_t *dummy,
505                                int line_size, int h)
506 {
507     int tmp;
508
509     assert((((int) pix) & 7) == 0);
510     assert((line_size & 7) == 0);
511
512 #define SUM(in0, in1, out0, out1)               \
513     "movq (%0), " #out0 "\n"                    \
514     "movq 8(%0), " #out1 "\n"                   \
515     "add %2, %0\n"                              \
516     "psadbw " #out0 ", " #in0 "\n"              \
517     "psadbw " #out1 ", " #in1 "\n"              \
518     "paddw " #in1 ", " #in0 "\n"                \
519     "paddw " #in0 ", %%mm6\n"
520
521     __asm__ volatile (
522         "movl %3, %%ecx\n"
523         "pxor %%mm6, %%mm6\n"
524         "pxor %%mm7, %%mm7\n"
525         "movq (%0), %%mm0\n"
526         "movq 8(%0), %%mm1\n"
527         "add %2, %0\n"
528         "jmp 2f\n"
529         "1:\n"
530
531         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
532         "2:\n"
533         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
534
535         "subl $2, %%ecx\n"
536         "jnz 1b\n"
537
538         "movd %%mm6, %1\n"
539         : "+r" (pix), "=r" (tmp)
540         : "r" ((x86_reg) line_size), "m" (h)
541         : "%ecx");
542
543     return tmp;
544 }
545 #undef SUM
546
547 static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
548                       int line_size, int h)
549 {
550     int tmp;
551
552     assert((((int) pix1) & 7) == 0);
553     assert((((int) pix2) & 7) == 0);
554     assert((line_size & 7) == 0);
555
556 #define SUM(in0, in1, out0, out1)       \
557     "movq (%0), %%mm2\n"                \
558     "movq (%1), " #out0 "\n"            \
559     "movq 8(%0), %%mm3\n"               \
560     "movq 8(%1), " #out1 "\n"           \
561     "add %3, %0\n"                      \
562     "add %3, %1\n"                      \
563     "psubb " #out0 ", %%mm2\n"          \
564     "psubb " #out1 ", %%mm3\n"          \
565     "pxor %%mm7, %%mm2\n"               \
566     "pxor %%mm7, %%mm3\n"               \
567     "movq %%mm2, " #out0 "\n"           \
568     "movq %%mm3, " #out1 "\n"           \
569     "psubusb " #in0 ", %%mm2\n"         \
570     "psubusb " #in1 ", %%mm3\n"         \
571     "psubusb " #out0 ", " #in0 "\n"     \
572     "psubusb " #out1 ", " #in1 "\n"     \
573     "por %%mm2, " #in0 "\n"             \
574     "por %%mm3, " #in1 "\n"             \
575     "movq " #in0 ", %%mm2\n"            \
576     "movq " #in1 ", %%mm3\n"            \
577     "punpcklbw %%mm7, " #in0 "\n"       \
578     "punpcklbw %%mm7, " #in1 "\n"       \
579     "punpckhbw %%mm7, %%mm2\n"          \
580     "punpckhbw %%mm7, %%mm3\n"          \
581     "paddw " #in1 ", " #in0 "\n"        \
582     "paddw %%mm3, %%mm2\n"              \
583     "paddw %%mm2, " #in0 "\n"           \
584     "paddw " #in0 ", %%mm6\n"
585
586
587     __asm__ volatile (
588         "movl %4, %%ecx\n"
589         "pxor %%mm6, %%mm6\n"
590         "pcmpeqw %%mm7, %%mm7\n"
591         "psllw $15, %%mm7\n"
592         "packsswb %%mm7, %%mm7\n"
593         "movq (%0), %%mm0\n"
594         "movq (%1), %%mm2\n"
595         "movq 8(%0), %%mm1\n"
596         "movq 8(%1), %%mm3\n"
597         "add %3, %0\n"
598         "add %3, %1\n"
599         "psubb %%mm2, %%mm0\n"
600         "psubb %%mm3, %%mm1\n"
601         "pxor %%mm7, %%mm0\n"
602         "pxor %%mm7, %%mm1\n"
603         "jmp 2f\n"
604         "1:\n"
605
606         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
607         "2:\n"
608         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
609
610         "subl $2, %%ecx\n"
611         "jnz 1b\n"
612
613         "movq %%mm6, %%mm0\n"
614         "psrlq $32, %%mm6\n"
615         "paddw %%mm6, %%mm0\n"
616         "movq %%mm0, %%mm6\n"
617         "psrlq $16, %%mm0\n"
618         "paddw %%mm6, %%mm0\n"
619         "movd %%mm0, %2\n"
620         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
621         : "r" ((x86_reg) line_size), "m" (h)
622         : "%ecx");
623
624     return tmp & 0x7FFF;
625 }
626 #undef SUM
627
628 static int vsad16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
629                          int line_size, int h)
630 {
631     int tmp;
632
633     assert((((int) pix1) & 7) == 0);
634     assert((((int) pix2) & 7) == 0);
635     assert((line_size & 7) == 0);
636
637 #define SUM(in0, in1, out0, out1)               \
638     "movq (%0), " #out0 "\n"                    \
639     "movq (%1), %%mm2\n"                        \
640     "movq 8(%0), " #out1 "\n"                   \
641     "movq 8(%1), %%mm3\n"                       \
642     "add %3, %0\n"                              \
643     "add %3, %1\n"                              \
644     "psubb %%mm2, " #out0 "\n"                  \
645     "psubb %%mm3, " #out1 "\n"                  \
646     "pxor %%mm7, " #out0 "\n"                   \
647     "pxor %%mm7, " #out1 "\n"                   \
648     "psadbw " #out0 ", " #in0 "\n"              \
649     "psadbw " #out1 ", " #in1 "\n"              \
650     "paddw " #in1 ", " #in0 "\n"                \
651     "paddw " #in0 ", %%mm6\n    "
652
653     __asm__ volatile (
654         "movl %4, %%ecx\n"
655         "pxor %%mm6, %%mm6\n"
656         "pcmpeqw %%mm7, %%mm7\n"
657         "psllw $15, %%mm7\n"
658         "packsswb %%mm7, %%mm7\n"
659         "movq (%0), %%mm0\n"
660         "movq (%1), %%mm2\n"
661         "movq 8(%0), %%mm1\n"
662         "movq 8(%1), %%mm3\n"
663         "add %3, %0\n"
664         "add %3, %1\n"
665         "psubb %%mm2, %%mm0\n"
666         "psubb %%mm3, %%mm1\n"
667         "pxor %%mm7, %%mm0\n"
668         "pxor %%mm7, %%mm1\n"
669         "jmp 2f\n"
670         "1:\n"
671
672         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
673         "2:\n"
674         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
675
676         "subl $2, %%ecx\n"
677         "jnz 1b\n"
678
679         "movd %%mm6, %2\n"
680         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
681         : "r" ((x86_reg) line_size), "m" (h)
682         : "%ecx");
683
684     return tmp;
685 }
686 #undef SUM
687
688 #define MMABS_MMX(a,z)                          \
689     "pxor "    #z ", " #z "             \n\t"   \
690     "pcmpgtw " #a ", " #z "             \n\t"   \
691     "pxor "    #z ", " #a "             \n\t"   \
692     "psubw "   #z ", " #a "             \n\t"
693
694 #define MMABS_MMXEXT(a, z)                      \
695     "pxor "    #z ", " #z "             \n\t"   \
696     "psubw "   #a ", " #z "             \n\t"   \
697     "pmaxsw "  #z ", " #a "             \n\t"
698
699 #define MMABS_SSSE3(a,z)                        \
700     "pabsw "   #a ", " #a "             \n\t"
701
702 #define MMABS_SUM(a,z, sum)                     \
703     MMABS(a,z)                                  \
704     "paddusw " #a ", " #sum "           \n\t"
705
706 /* FIXME: HSUM_* saturates at 64k, while an 8x8 hadamard or dct block can get
707  * up to about 100k on extreme inputs. But that's very unlikely to occur in
708  * natural video, and it's even more unlikely to not have any alternative
709  * mvs/modes with lower cost. */
710 #define HSUM_MMX(a, t, dst)                     \
711     "movq    " #a ", " #t "             \n\t"   \
712     "psrlq      $32, " #a "             \n\t"   \
713     "paddusw " #t ", " #a "             \n\t"   \
714     "movq    " #a ", " #t "             \n\t"   \
715     "psrlq      $16, " #a "             \n\t"   \
716     "paddusw " #t ", " #a "             \n\t"   \
717     "movd    " #a ", " #dst "           \n\t"   \
718
719 #define HSUM_MMXEXT(a, t, dst)                  \
720     "pshufw   $0x0E, " #a ", " #t "     \n\t"   \
721     "paddusw " #t ", " #a "             \n\t"   \
722     "pshufw   $0x01, " #a ", " #t "     \n\t"   \
723     "paddusw " #t ", " #a "             \n\t"   \
724     "movd    " #a ", " #dst "           \n\t"   \
725
726 #define HSUM_SSE2(a, t, dst)                    \
727     "movhlps " #a ", " #t "             \n\t"   \
728     "paddusw " #t ", " #a "             \n\t"   \
729     "pshuflw  $0x0E, " #a ", " #t "     \n\t"   \
730     "paddusw " #t ", " #a "             \n\t"   \
731     "pshuflw  $0x01, " #a ", " #t "     \n\t"   \
732     "paddusw " #t ", " #a "             \n\t"   \
733     "movd    " #a ", " #dst "           \n\t"   \
734
735 #define DCT_SAD4(m, mm, o)                      \
736     "mov"#m" "#o" +  0(%1), " #mm "2    \n\t"   \
737     "mov"#m" "#o" + 16(%1), " #mm "3    \n\t"   \
738     "mov"#m" "#o" + 32(%1), " #mm "4    \n\t"   \
739     "mov"#m" "#o" + 48(%1), " #mm "5    \n\t"   \
740     MMABS_SUM(mm ## 2, mm ## 6, mm ## 0)        \
741     MMABS_SUM(mm ## 3, mm ## 7, mm ## 1)        \
742     MMABS_SUM(mm ## 4, mm ## 6, mm ## 0)        \
743     MMABS_SUM(mm ## 5, mm ## 7, mm ## 1)        \
744
745 #define DCT_SAD_MMX                             \
746     "pxor    %%mm0, %%mm0               \n\t"   \
747     "pxor    %%mm1, %%mm1               \n\t"   \
748     DCT_SAD4(q, %%mm, 0)                        \
749     DCT_SAD4(q, %%mm, 8)                        \
750     DCT_SAD4(q, %%mm, 64)                       \
751     DCT_SAD4(q, %%mm, 72)                       \
752     "paddusw %%mm1, %%mm0               \n\t"   \
753     HSUM(%%mm0, %%mm1, %0)
754
755 #define DCT_SAD_SSE2                            \
756     "pxor    %%xmm0, %%xmm0             \n\t"   \
757     "pxor    %%xmm1, %%xmm1             \n\t"   \
758     DCT_SAD4(dqa, %%xmm, 0)                     \
759     DCT_SAD4(dqa, %%xmm, 64)                    \
760     "paddusw %%xmm1, %%xmm0             \n\t"   \
761     HSUM(%%xmm0, %%xmm1, %0)
762
763 #define DCT_SAD_FUNC(cpu)                           \
764 static int sum_abs_dctelem_ ## cpu(int16_t *block)  \
765 {                                                   \
766     int sum;                                        \
767     __asm__ volatile (                              \
768         DCT_SAD                                     \
769         :"=r"(sum)                                  \
770         :"r"(block));                               \
771     return sum & 0xFFFF;                            \
772 }
773
774 #define DCT_SAD         DCT_SAD_MMX
775 #define HSUM(a, t, dst) HSUM_MMX(a, t, dst)
776 #define MMABS(a, z)     MMABS_MMX(a, z)
777 DCT_SAD_FUNC(mmx)
778 #undef MMABS
779 #undef HSUM
780
781 #define HSUM(a, t, dst) HSUM_MMXEXT(a, t, dst)
782 #define MMABS(a, z)     MMABS_MMXEXT(a, z)
783 DCT_SAD_FUNC(mmxext)
784 #undef HSUM
785 #undef DCT_SAD
786
787 #define DCT_SAD         DCT_SAD_SSE2
788 #define HSUM(a, t, dst) HSUM_SSE2(a, t, dst)
789 DCT_SAD_FUNC(sse2)
790 #undef MMABS
791
792 #if HAVE_SSSE3_INLINE
793 #define MMABS(a, z)     MMABS_SSSE3(a, z)
794 DCT_SAD_FUNC(ssse3)
795 #undef MMABS
796 #endif
797 #undef HSUM
798 #undef DCT_SAD
799
800 #endif /* HAVE_INLINE_ASM */
801
802 int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
803                   int line_size, int h);
804
805 #define hadamard_func(cpu)                                              \
806     int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,     \
807                                   uint8_t *src2, int stride, int h);    \
808     int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1,   \
809                                     uint8_t *src2, int stride, int h);
810
811 hadamard_func(mmx)
812 hadamard_func(mmxext)
813 hadamard_func(sse2)
814 hadamard_func(ssse3)
815
816 av_cold void ff_dsputilenc_init_mmx(DSPContext *c, AVCodecContext *avctx)
817 {
818     int cpu_flags = av_get_cpu_flags();
819
820 #if HAVE_INLINE_ASM
821     if (INLINE_MMX(cpu_flags)) {
822         c->sum_abs_dctelem = sum_abs_dctelem_mmx;
823
824         c->sse[0]  = sse16_mmx;
825         c->sse[1]  = sse8_mmx;
826         c->vsad[4] = vsad_intra16_mmx;
827
828         c->nsse[0] = nsse16_mmx;
829         c->nsse[1] = nsse8_mmx;
830         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
831             c->vsad[0]      = vsad16_mmx;
832         }
833     }
834
835     if (INLINE_MMXEXT(cpu_flags)) {
836         c->sum_abs_dctelem = sum_abs_dctelem_mmxext;
837         c->vsad[4]         = vsad_intra16_mmxext;
838
839         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
840             c->vsad[0] = vsad16_mmxext;
841         }
842     }
843
844     if (INLINE_SSE2(cpu_flags)) {
845         c->sum_abs_dctelem = sum_abs_dctelem_sse2;
846     }
847
848 #if HAVE_SSSE3_INLINE
849     if (INLINE_SSSE3(cpu_flags)) {
850         c->sum_abs_dctelem = sum_abs_dctelem_ssse3;
851     }
852 #endif
853 #endif /* HAVE_INLINE_ASM */
854
855     if (EXTERNAL_MMX(cpu_flags)) {
856         c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx;
857         c->hadamard8_diff[1] = ff_hadamard8_diff_mmx;
858     }
859
860     if (EXTERNAL_MMXEXT(cpu_flags)) {
861         c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext;
862         c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext;
863     }
864
865     if (EXTERNAL_SSE2(cpu_flags)) {
866         c->sse[0] = ff_sse16_sse2;
867
868 #if HAVE_ALIGNED_STACK
869         c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2;
870         c->hadamard8_diff[1] = ff_hadamard8_diff_sse2;
871 #endif
872     }
873
874     if (EXTERNAL_SSSE3(cpu_flags) && HAVE_ALIGNED_STACK) {
875         c->hadamard8_diff[0] = ff_hadamard8_diff16_ssse3;
876         c->hadamard8_diff[1] = ff_hadamard8_diff_ssse3;
877     }
878
879     ff_dsputil_init_pix_mmx(c, avctx);
880 }