dsputil: Propagate bit depth information to all (sub)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/dct.h"
30 #include "libavcodec/dsputil.h"
31 #include "libavcodec/mpegvideo.h"
32 #include "libavcodec/mathops.h"
33 #include "dsputil_x86.h"
34
35 void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size);
36 void ff_get_pixels_sse2(int16_t *block, const uint8_t *pixels, int line_size);
37 void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2,
38                         int stride);
39 int ff_pix_sum16_mmx(uint8_t *pix, int line_size);
40 int ff_pix_norm1_mmx(uint8_t *pix, int line_size);
41
42 #if HAVE_INLINE_ASM
43
44 static int sse8_mmx(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
45 {
46     int tmp;
47
48     __asm__ volatile (
49         "movl         %4, %%ecx          \n"
50         "shr          $1, %%ecx          \n"
51         "pxor      %%mm0, %%mm0          \n" /* mm0 = 0 */
52         "pxor      %%mm7, %%mm7          \n" /* mm7 holds the sum */
53         "1:                              \n"
54         "movq       (%0), %%mm1          \n" /* mm1 = pix1[0][0 - 7] */
55         "movq       (%1), %%mm2          \n" /* mm2 = pix2[0][0 - 7] */
56         "movq   (%0, %3), %%mm3          \n" /* mm3 = pix1[1][0 - 7] */
57         "movq   (%1, %3), %%mm4          \n" /* mm4 = pix2[1][0 - 7] */
58
59         /* todo: mm1-mm2, mm3-mm4 */
60         /* algo: subtract mm1 from mm2 with saturation and vice versa */
61         /*       OR the results to get absolute difference */
62         "movq      %%mm1, %%mm5          \n"
63         "movq      %%mm3, %%mm6          \n"
64         "psubusb   %%mm2, %%mm1          \n"
65         "psubusb   %%mm4, %%mm3          \n"
66         "psubusb   %%mm5, %%mm2          \n"
67         "psubusb   %%mm6, %%mm4          \n"
68
69         "por       %%mm1, %%mm2          \n"
70         "por       %%mm3, %%mm4          \n"
71
72         /* now convert to 16-bit vectors so we can square them */
73         "movq      %%mm2, %%mm1          \n"
74         "movq      %%mm4, %%mm3          \n"
75
76         "punpckhbw %%mm0, %%mm2          \n"
77         "punpckhbw %%mm0, %%mm4          \n"
78         "punpcklbw %%mm0, %%mm1          \n" /* mm1 now spread over (mm1, mm2) */
79         "punpcklbw %%mm0, %%mm3          \n" /* mm4 now spread over (mm3, mm4) */
80
81         "pmaddwd   %%mm2, %%mm2          \n"
82         "pmaddwd   %%mm4, %%mm4          \n"
83         "pmaddwd   %%mm1, %%mm1          \n"
84         "pmaddwd   %%mm3, %%mm3          \n"
85
86         "lea (%0, %3, 2), %0             \n" /* pix1 += 2 * line_size */
87         "lea (%1, %3, 2), %1             \n" /* pix2 += 2 * line_size */
88
89         "paddd     %%mm2, %%mm1          \n"
90         "paddd     %%mm4, %%mm3          \n"
91         "paddd     %%mm1, %%mm7          \n"
92         "paddd     %%mm3, %%mm7          \n"
93
94         "decl      %%ecx                 \n"
95         "jnz       1b                    \n"
96
97         "movq      %%mm7, %%mm1          \n"
98         "psrlq       $32, %%mm7          \n" /* shift hi dword to lo */
99         "paddd     %%mm7, %%mm1          \n"
100         "movd      %%mm1, %2             \n"
101         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
102         : "r" ((x86_reg) line_size), "m" (h)
103         : "%ecx");
104
105     return tmp;
106 }
107
108 static int sse16_mmx(void *v, uint8_t *pix1, uint8_t *pix2,
109                      int line_size, int h)
110 {
111     int tmp;
112
113     __asm__ volatile (
114         "movl %4, %%ecx\n"
115         "pxor %%mm0, %%mm0\n"    /* mm0 = 0 */
116         "pxor %%mm7, %%mm7\n"    /* mm7 holds the sum */
117         "1:\n"
118         "movq (%0), %%mm1\n"     /* mm1 = pix1[0 -  7] */
119         "movq (%1), %%mm2\n"     /* mm2 = pix2[0 -  7] */
120         "movq 8(%0), %%mm3\n"    /* mm3 = pix1[8 - 15] */
121         "movq 8(%1), %%mm4\n"    /* mm4 = pix2[8 - 15] */
122
123         /* todo: mm1-mm2, mm3-mm4 */
124         /* algo: subtract mm1 from mm2 with saturation and vice versa */
125         /*       OR the results to get absolute difference */
126         "movq %%mm1, %%mm5\n"
127         "movq %%mm3, %%mm6\n"
128         "psubusb %%mm2, %%mm1\n"
129         "psubusb %%mm4, %%mm3\n"
130         "psubusb %%mm5, %%mm2\n"
131         "psubusb %%mm6, %%mm4\n"
132
133         "por %%mm1, %%mm2\n"
134         "por %%mm3, %%mm4\n"
135
136         /* now convert to 16-bit vectors so we can square them */
137         "movq %%mm2, %%mm1\n"
138         "movq %%mm4, %%mm3\n"
139
140         "punpckhbw %%mm0, %%mm2\n"
141         "punpckhbw %%mm0, %%mm4\n"
142         "punpcklbw %%mm0, %%mm1\n" /* mm1 now spread over (mm1, mm2) */
143         "punpcklbw %%mm0, %%mm3\n" /* mm4 now spread over (mm3, mm4) */
144
145         "pmaddwd %%mm2, %%mm2\n"
146         "pmaddwd %%mm4, %%mm4\n"
147         "pmaddwd %%mm1, %%mm1\n"
148         "pmaddwd %%mm3, %%mm3\n"
149
150         "add %3, %0\n"
151         "add %3, %1\n"
152
153         "paddd %%mm2, %%mm1\n"
154         "paddd %%mm4, %%mm3\n"
155         "paddd %%mm1, %%mm7\n"
156         "paddd %%mm3, %%mm7\n"
157
158         "decl %%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, %2\n"
165         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
166         : "r" ((x86_reg) line_size), "m" (h)
167         : "%ecx");
168
169     return tmp;
170 }
171
172 static int hf_noise8_mmx(uint8_t *pix1, int line_size, int h)
173 {
174     int tmp;
175
176     __asm__ volatile (
177         "movl %3, %%ecx\n"
178         "pxor %%mm7, %%mm7\n"
179         "pxor %%mm6, %%mm6\n"
180
181         "movq (%0), %%mm0\n"
182         "movq %%mm0, %%mm1\n"
183         "psllq $8, %%mm0\n"
184         "psrlq $8, %%mm1\n"
185         "psrlq $8, %%mm0\n"
186         "movq %%mm0, %%mm2\n"
187         "movq %%mm1, %%mm3\n"
188         "punpcklbw %%mm7, %%mm0\n"
189         "punpcklbw %%mm7, %%mm1\n"
190         "punpckhbw %%mm7, %%mm2\n"
191         "punpckhbw %%mm7, %%mm3\n"
192         "psubw %%mm1, %%mm0\n"
193         "psubw %%mm3, %%mm2\n"
194
195         "add %2, %0\n"
196
197         "movq (%0), %%mm4\n"
198         "movq %%mm4, %%mm1\n"
199         "psllq $8, %%mm4\n"
200         "psrlq $8, %%mm1\n"
201         "psrlq $8, %%mm4\n"
202         "movq %%mm4, %%mm5\n"
203         "movq %%mm1, %%mm3\n"
204         "punpcklbw %%mm7, %%mm4\n"
205         "punpcklbw %%mm7, %%mm1\n"
206         "punpckhbw %%mm7, %%mm5\n"
207         "punpckhbw %%mm7, %%mm3\n"
208         "psubw %%mm1, %%mm4\n"
209         "psubw %%mm3, %%mm5\n"
210         "psubw %%mm4, %%mm0\n"
211         "psubw %%mm5, %%mm2\n"
212         "pxor %%mm3, %%mm3\n"
213         "pxor %%mm1, %%mm1\n"
214         "pcmpgtw %%mm0, %%mm3\n\t"
215         "pcmpgtw %%mm2, %%mm1\n\t"
216         "pxor %%mm3, %%mm0\n"
217         "pxor %%mm1, %%mm2\n"
218         "psubw %%mm3, %%mm0\n"
219         "psubw %%mm1, %%mm2\n"
220         "paddw %%mm0, %%mm2\n"
221         "paddw %%mm2, %%mm6\n"
222
223         "add %2, %0\n"
224         "1:\n"
225
226         "movq (%0), %%mm0\n"
227         "movq %%mm0, %%mm1\n"
228         "psllq $8, %%mm0\n"
229         "psrlq $8, %%mm1\n"
230         "psrlq $8, %%mm0\n"
231         "movq %%mm0, %%mm2\n"
232         "movq %%mm1, %%mm3\n"
233         "punpcklbw %%mm7, %%mm0\n"
234         "punpcklbw %%mm7, %%mm1\n"
235         "punpckhbw %%mm7, %%mm2\n"
236         "punpckhbw %%mm7, %%mm3\n"
237         "psubw %%mm1, %%mm0\n"
238         "psubw %%mm3, %%mm2\n"
239         "psubw %%mm0, %%mm4\n"
240         "psubw %%mm2, %%mm5\n"
241         "pxor  %%mm3, %%mm3\n"
242         "pxor  %%mm1, %%mm1\n"
243         "pcmpgtw %%mm4, %%mm3\n\t"
244         "pcmpgtw %%mm5, %%mm1\n\t"
245         "pxor  %%mm3, %%mm4\n"
246         "pxor  %%mm1, %%mm5\n"
247         "psubw %%mm3, %%mm4\n"
248         "psubw %%mm1, %%mm5\n"
249         "paddw %%mm4, %%mm5\n"
250         "paddw %%mm5, %%mm6\n"
251
252         "add %2, %0\n"
253
254         "movq (%0), %%mm4\n"
255         "movq      %%mm4, %%mm1\n"
256         "psllq $8, %%mm4\n"
257         "psrlq $8, %%mm1\n"
258         "psrlq $8, %%mm4\n"
259         "movq      %%mm4, %%mm5\n"
260         "movq      %%mm1, %%mm3\n"
261         "punpcklbw %%mm7, %%mm4\n"
262         "punpcklbw %%mm7, %%mm1\n"
263         "punpckhbw %%mm7, %%mm5\n"
264         "punpckhbw %%mm7, %%mm3\n"
265         "psubw     %%mm1, %%mm4\n"
266         "psubw     %%mm3, %%mm5\n"
267         "psubw     %%mm4, %%mm0\n"
268         "psubw     %%mm5, %%mm2\n"
269         "pxor      %%mm3, %%mm3\n"
270         "pxor      %%mm1, %%mm1\n"
271         "pcmpgtw   %%mm0, %%mm3\n\t"
272         "pcmpgtw   %%mm2, %%mm1\n\t"
273         "pxor      %%mm3, %%mm0\n"
274         "pxor      %%mm1, %%mm2\n"
275         "psubw     %%mm3, %%mm0\n"
276         "psubw     %%mm1, %%mm2\n"
277         "paddw     %%mm0, %%mm2\n"
278         "paddw     %%mm2, %%mm6\n"
279
280         "add  %2, %0\n"
281         "subl $2, %%ecx\n"
282         " jnz 1b\n"
283
284         "movq      %%mm6, %%mm0\n"
285         "punpcklwd %%mm7, %%mm0\n"
286         "punpckhwd %%mm7, %%mm6\n"
287         "paddd     %%mm0, %%mm6\n"
288
289         "movq  %%mm6, %%mm0\n"
290         "psrlq $32,   %%mm6\n"
291         "paddd %%mm6, %%mm0\n"
292         "movd  %%mm0, %1\n"
293         : "+r" (pix1), "=r" (tmp)
294         : "r" ((x86_reg) line_size), "g" (h - 2)
295         : "%ecx");
296
297     return tmp;
298 }
299
300 static int hf_noise16_mmx(uint8_t *pix1, int line_size, int h)
301 {
302     int tmp;
303     uint8_t *pix = pix1;
304
305     __asm__ volatile (
306         "movl %3, %%ecx\n"
307         "pxor %%mm7, %%mm7\n"
308         "pxor %%mm6, %%mm6\n"
309
310         "movq (%0), %%mm0\n"
311         "movq 1(%0), %%mm1\n"
312         "movq %%mm0, %%mm2\n"
313         "movq %%mm1, %%mm3\n"
314         "punpcklbw %%mm7, %%mm0\n"
315         "punpcklbw %%mm7, %%mm1\n"
316         "punpckhbw %%mm7, %%mm2\n"
317         "punpckhbw %%mm7, %%mm3\n"
318         "psubw %%mm1, %%mm0\n"
319         "psubw %%mm3, %%mm2\n"
320
321         "add %2, %0\n"
322
323         "movq (%0), %%mm4\n"
324         "movq 1(%0), %%mm1\n"
325         "movq %%mm4, %%mm5\n"
326         "movq %%mm1, %%mm3\n"
327         "punpcklbw %%mm7, %%mm4\n"
328         "punpcklbw %%mm7, %%mm1\n"
329         "punpckhbw %%mm7, %%mm5\n"
330         "punpckhbw %%mm7, %%mm3\n"
331         "psubw %%mm1, %%mm4\n"
332         "psubw %%mm3, %%mm5\n"
333         "psubw %%mm4, %%mm0\n"
334         "psubw %%mm5, %%mm2\n"
335         "pxor %%mm3, %%mm3\n"
336         "pxor %%mm1, %%mm1\n"
337         "pcmpgtw %%mm0, %%mm3\n\t"
338         "pcmpgtw %%mm2, %%mm1\n\t"
339         "pxor %%mm3, %%mm0\n"
340         "pxor %%mm1, %%mm2\n"
341         "psubw %%mm3, %%mm0\n"
342         "psubw %%mm1, %%mm2\n"
343         "paddw %%mm0, %%mm2\n"
344         "paddw %%mm2, %%mm6\n"
345
346         "add %2, %0\n"
347         "1:\n"
348
349         "movq (%0), %%mm0\n"
350         "movq 1(%0), %%mm1\n"
351         "movq %%mm0, %%mm2\n"
352         "movq %%mm1, %%mm3\n"
353         "punpcklbw %%mm7, %%mm0\n"
354         "punpcklbw %%mm7, %%mm1\n"
355         "punpckhbw %%mm7, %%mm2\n"
356         "punpckhbw %%mm7, %%mm3\n"
357         "psubw %%mm1, %%mm0\n"
358         "psubw %%mm3, %%mm2\n"
359         "psubw %%mm0, %%mm4\n"
360         "psubw %%mm2, %%mm5\n"
361         "pxor %%mm3, %%mm3\n"
362         "pxor %%mm1, %%mm1\n"
363         "pcmpgtw %%mm4, %%mm3\n\t"
364         "pcmpgtw %%mm5, %%mm1\n\t"
365         "pxor %%mm3, %%mm4\n"
366         "pxor %%mm1, %%mm5\n"
367         "psubw %%mm3, %%mm4\n"
368         "psubw %%mm1, %%mm5\n"
369         "paddw %%mm4, %%mm5\n"
370         "paddw %%mm5, %%mm6\n"
371
372         "add %2, %0\n"
373
374         "movq (%0), %%mm4\n"
375         "movq 1(%0), %%mm1\n"
376         "movq %%mm4, %%mm5\n"
377         "movq %%mm1, %%mm3\n"
378         "punpcklbw %%mm7, %%mm4\n"
379         "punpcklbw %%mm7, %%mm1\n"
380         "punpckhbw %%mm7, %%mm5\n"
381         "punpckhbw %%mm7, %%mm3\n"
382         "psubw %%mm1, %%mm4\n"
383         "psubw %%mm3, %%mm5\n"
384         "psubw %%mm4, %%mm0\n"
385         "psubw %%mm5, %%mm2\n"
386         "pxor %%mm3, %%mm3\n"
387         "pxor %%mm1, %%mm1\n"
388         "pcmpgtw %%mm0, %%mm3\n\t"
389         "pcmpgtw %%mm2, %%mm1\n\t"
390         "pxor %%mm3, %%mm0\n"
391         "pxor %%mm1, %%mm2\n"
392         "psubw %%mm3, %%mm0\n"
393         "psubw %%mm1, %%mm2\n"
394         "paddw %%mm0, %%mm2\n"
395         "paddw %%mm2, %%mm6\n"
396
397         "add %2, %0\n"
398         "subl $2, %%ecx\n"
399         " jnz 1b\n"
400
401         "movq %%mm6, %%mm0\n"
402         "punpcklwd %%mm7, %%mm0\n"
403         "punpckhwd %%mm7, %%mm6\n"
404         "paddd %%mm0, %%mm6\n"
405
406         "movq %%mm6, %%mm0\n"
407         "psrlq $32, %%mm6\n"
408         "paddd %%mm6, %%mm0\n"
409         "movd %%mm0, %1\n"
410         : "+r" (pix1), "=r" (tmp)
411         : "r" ((x86_reg) line_size), "g" (h - 2)
412         : "%ecx");
413
414     return tmp + hf_noise8_mmx(pix + 8, line_size, h);
415 }
416
417 static int nsse16_mmx(void *p, uint8_t *pix1, uint8_t *pix2,
418                       int line_size, int h)
419 {
420     MpegEncContext *c = p;
421     int score1, score2;
422
423     if (c)
424         score1 = c->dsp.sse[0](c, pix1, pix2, line_size, h);
425     else
426         score1 = sse16_mmx(c, pix1, pix2, line_size, h);
427     score2 = hf_noise16_mmx(pix1, line_size, h) -
428              hf_noise16_mmx(pix2, line_size, h);
429
430     if (c)
431         return score1 + FFABS(score2) * c->avctx->nsse_weight;
432     else
433         return score1 + FFABS(score2) * 8;
434 }
435
436 static int nsse8_mmx(void *p, uint8_t *pix1, uint8_t *pix2,
437                      int line_size, int h)
438 {
439     MpegEncContext *c = p;
440     int score1 = sse8_mmx(c, pix1, pix2, line_size, h);
441     int score2 = hf_noise8_mmx(pix1, line_size, h) -
442                  hf_noise8_mmx(pix2, line_size, h);
443
444     if (c)
445         return score1 + FFABS(score2) * c->avctx->nsse_weight;
446     else
447         return score1 + FFABS(score2) * 8;
448 }
449
450 static int vsad_intra16_mmx(void *v, uint8_t *pix, uint8_t *dummy,
451                             int line_size, int h)
452 {
453     int tmp;
454
455     assert((((int) pix) & 7) == 0);
456     assert((line_size & 7) == 0);
457
458 #define SUM(in0, in1, out0, out1)               \
459     "movq (%0), %%mm2\n"                        \
460     "movq 8(%0), %%mm3\n"                       \
461     "add %2,%0\n"                               \
462     "movq %%mm2, " #out0 "\n"                   \
463     "movq %%mm3, " #out1 "\n"                   \
464     "psubusb " #in0 ", %%mm2\n"                 \
465     "psubusb " #in1 ", %%mm3\n"                 \
466     "psubusb " #out0 ", " #in0 "\n"             \
467     "psubusb " #out1 ", " #in1 "\n"             \
468     "por %%mm2, " #in0 "\n"                     \
469     "por %%mm3, " #in1 "\n"                     \
470     "movq " #in0 ", %%mm2\n"                    \
471     "movq " #in1 ", %%mm3\n"                    \
472     "punpcklbw %%mm7, " #in0 "\n"               \
473     "punpcklbw %%mm7, " #in1 "\n"               \
474     "punpckhbw %%mm7, %%mm2\n"                  \
475     "punpckhbw %%mm7, %%mm3\n"                  \
476     "paddw " #in1 ", " #in0 "\n"                \
477     "paddw %%mm3, %%mm2\n"                      \
478     "paddw %%mm2, " #in0 "\n"                   \
479     "paddw " #in0 ", %%mm6\n"
480
481
482     __asm__ volatile (
483         "movl    %3, %%ecx\n"
484         "pxor %%mm6, %%mm6\n"
485         "pxor %%mm7, %%mm7\n"
486         "movq  (%0), %%mm0\n"
487         "movq 8(%0), %%mm1\n"
488         "add %2, %0\n"
489         "jmp 2f\n"
490         "1:\n"
491
492         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
493         "2:\n"
494         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
495
496         "subl $2, %%ecx\n"
497         "jnz 1b\n"
498
499         "movq  %%mm6, %%mm0\n"
500         "psrlq $32,   %%mm6\n"
501         "paddw %%mm6, %%mm0\n"
502         "movq  %%mm0, %%mm6\n"
503         "psrlq $16,   %%mm0\n"
504         "paddw %%mm6, %%mm0\n"
505         "movd  %%mm0, %1\n"
506         : "+r" (pix), "=r" (tmp)
507         : "r" ((x86_reg) line_size), "m" (h)
508         : "%ecx");
509
510     return tmp & 0xFFFF;
511 }
512 #undef SUM
513
514 static int vsad_intra16_mmxext(void *v, uint8_t *pix, uint8_t *dummy,
515                                int line_size, int h)
516 {
517     int tmp;
518
519     assert((((int) pix) & 7) == 0);
520     assert((line_size & 7) == 0);
521
522 #define SUM(in0, in1, out0, out1)               \
523     "movq (%0), " #out0 "\n"                    \
524     "movq 8(%0), " #out1 "\n"                   \
525     "add %2, %0\n"                              \
526     "psadbw " #out0 ", " #in0 "\n"              \
527     "psadbw " #out1 ", " #in1 "\n"              \
528     "paddw " #in1 ", " #in0 "\n"                \
529     "paddw " #in0 ", %%mm6\n"
530
531     __asm__ volatile (
532         "movl %3, %%ecx\n"
533         "pxor %%mm6, %%mm6\n"
534         "pxor %%mm7, %%mm7\n"
535         "movq (%0), %%mm0\n"
536         "movq 8(%0), %%mm1\n"
537         "add %2, %0\n"
538         "jmp 2f\n"
539         "1:\n"
540
541         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
542         "2:\n"
543         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
544
545         "subl $2, %%ecx\n"
546         "jnz 1b\n"
547
548         "movd %%mm6, %1\n"
549         : "+r" (pix), "=r" (tmp)
550         : "r" ((x86_reg) line_size), "m" (h)
551         : "%ecx");
552
553     return tmp;
554 }
555 #undef SUM
556
557 static int vsad16_mmx(void *v, uint8_t *pix1, uint8_t *pix2,
558                       int line_size, int h)
559 {
560     int tmp;
561
562     assert((((int) pix1) & 7) == 0);
563     assert((((int) pix2) & 7) == 0);
564     assert((line_size & 7) == 0);
565
566 #define SUM(in0, in1, out0, out1)       \
567     "movq (%0), %%mm2\n"                \
568     "movq (%1), " #out0 "\n"            \
569     "movq 8(%0), %%mm3\n"               \
570     "movq 8(%1), " #out1 "\n"           \
571     "add %3, %0\n"                      \
572     "add %3, %1\n"                      \
573     "psubb " #out0 ", %%mm2\n"          \
574     "psubb " #out1 ", %%mm3\n"          \
575     "pxor %%mm7, %%mm2\n"               \
576     "pxor %%mm7, %%mm3\n"               \
577     "movq %%mm2, " #out0 "\n"           \
578     "movq %%mm3, " #out1 "\n"           \
579     "psubusb " #in0 ", %%mm2\n"         \
580     "psubusb " #in1 ", %%mm3\n"         \
581     "psubusb " #out0 ", " #in0 "\n"     \
582     "psubusb " #out1 ", " #in1 "\n"     \
583     "por %%mm2, " #in0 "\n"             \
584     "por %%mm3, " #in1 "\n"             \
585     "movq " #in0 ", %%mm2\n"            \
586     "movq " #in1 ", %%mm3\n"            \
587     "punpcklbw %%mm7, " #in0 "\n"       \
588     "punpcklbw %%mm7, " #in1 "\n"       \
589     "punpckhbw %%mm7, %%mm2\n"          \
590     "punpckhbw %%mm7, %%mm3\n"          \
591     "paddw " #in1 ", " #in0 "\n"        \
592     "paddw %%mm3, %%mm2\n"              \
593     "paddw %%mm2, " #in0 "\n"           \
594     "paddw " #in0 ", %%mm6\n"
595
596
597     __asm__ volatile (
598         "movl %4, %%ecx\n"
599         "pxor %%mm6, %%mm6\n"
600         "pcmpeqw %%mm7, %%mm7\n"
601         "psllw $15, %%mm7\n"
602         "packsswb %%mm7, %%mm7\n"
603         "movq (%0), %%mm0\n"
604         "movq (%1), %%mm2\n"
605         "movq 8(%0), %%mm1\n"
606         "movq 8(%1), %%mm3\n"
607         "add %3, %0\n"
608         "add %3, %1\n"
609         "psubb %%mm2, %%mm0\n"
610         "psubb %%mm3, %%mm1\n"
611         "pxor %%mm7, %%mm0\n"
612         "pxor %%mm7, %%mm1\n"
613         "jmp 2f\n"
614         "1:\n"
615
616         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
617         "2:\n"
618         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
619
620         "subl $2, %%ecx\n"
621         "jnz 1b\n"
622
623         "movq %%mm6, %%mm0\n"
624         "psrlq $32, %%mm6\n"
625         "paddw %%mm6, %%mm0\n"
626         "movq %%mm0, %%mm6\n"
627         "psrlq $16, %%mm0\n"
628         "paddw %%mm6, %%mm0\n"
629         "movd %%mm0, %2\n"
630         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
631         : "r" ((x86_reg) line_size), "m" (h)
632         : "%ecx");
633
634     return tmp & 0x7FFF;
635 }
636 #undef SUM
637
638 static int vsad16_mmxext(void *v, uint8_t *pix1, uint8_t *pix2,
639                          int line_size, int h)
640 {
641     int tmp;
642
643     assert((((int) pix1) & 7) == 0);
644     assert((((int) pix2) & 7) == 0);
645     assert((line_size & 7) == 0);
646
647 #define SUM(in0, in1, out0, out1)               \
648     "movq (%0), " #out0 "\n"                    \
649     "movq (%1), %%mm2\n"                        \
650     "movq 8(%0), " #out1 "\n"                   \
651     "movq 8(%1), %%mm3\n"                       \
652     "add %3, %0\n"                              \
653     "add %3, %1\n"                              \
654     "psubb %%mm2, " #out0 "\n"                  \
655     "psubb %%mm3, " #out1 "\n"                  \
656     "pxor %%mm7, " #out0 "\n"                   \
657     "pxor %%mm7, " #out1 "\n"                   \
658     "psadbw " #out0 ", " #in0 "\n"              \
659     "psadbw " #out1 ", " #in1 "\n"              \
660     "paddw " #in1 ", " #in0 "\n"                \
661     "paddw " #in0 ", %%mm6\n    "
662
663     __asm__ volatile (
664         "movl %4, %%ecx\n"
665         "pxor %%mm6, %%mm6\n"
666         "pcmpeqw %%mm7, %%mm7\n"
667         "psllw $15, %%mm7\n"
668         "packsswb %%mm7, %%mm7\n"
669         "movq (%0), %%mm0\n"
670         "movq (%1), %%mm2\n"
671         "movq 8(%0), %%mm1\n"
672         "movq 8(%1), %%mm3\n"
673         "add %3, %0\n"
674         "add %3, %1\n"
675         "psubb %%mm2, %%mm0\n"
676         "psubb %%mm3, %%mm1\n"
677         "pxor %%mm7, %%mm0\n"
678         "pxor %%mm7, %%mm1\n"
679         "jmp 2f\n"
680         "1:\n"
681
682         SUM(%%mm4, %%mm5, %%mm0, %%mm1)
683         "2:\n"
684         SUM(%%mm0, %%mm1, %%mm4, %%mm5)
685
686         "subl $2, %%ecx\n"
687         "jnz 1b\n"
688
689         "movd %%mm6, %2\n"
690         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
691         : "r" ((x86_reg) line_size), "m" (h)
692         : "%ecx");
693
694     return tmp;
695 }
696 #undef SUM
697
698 static void diff_bytes_mmx(uint8_t *dst, uint8_t *src1, uint8_t *src2, int w)
699 {
700     x86_reg i = 0;
701
702     __asm__ volatile (
703         "1:                             \n\t"
704         "movq  (%2, %0), %%mm0          \n\t"
705         "movq  (%1, %0), %%mm1          \n\t"
706         "psubb %%mm0, %%mm1             \n\t"
707         "movq %%mm1, (%3, %0)           \n\t"
708         "movq 8(%2, %0), %%mm0          \n\t"
709         "movq 8(%1, %0), %%mm1          \n\t"
710         "psubb %%mm0, %%mm1             \n\t"
711         "movq %%mm1, 8(%3, %0)          \n\t"
712         "add $16, %0                    \n\t"
713         "cmp %4, %0                     \n\t"
714         " jb 1b                         \n\t"
715         : "+r" (i)
716         : "r" (src1), "r" (src2), "r" (dst), "r" ((x86_reg) w - 15));
717
718     for (; i < w; i++)
719         dst[i + 0] = src1[i + 0] - src2[i + 0];
720 }
721
722 static void sub_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *src1,
723                                               const uint8_t *src2, int w,
724                                               int *left, int *left_top)
725 {
726     x86_reg i = 0;
727     uint8_t l, lt;
728
729     __asm__ volatile (
730         "movq  (%1, %0), %%mm0          \n\t" // LT
731         "psllq $8, %%mm0                \n\t"
732         "1:                             \n\t"
733         "movq  (%1, %0), %%mm1          \n\t" // T
734         "movq  -1(%2, %0), %%mm2        \n\t" // L
735         "movq  (%2, %0), %%mm3          \n\t" // X
736         "movq %%mm2, %%mm4              \n\t" // L
737         "psubb %%mm0, %%mm2             \n\t"
738         "paddb %%mm1, %%mm2             \n\t" // L + T - LT
739         "movq %%mm4, %%mm5              \n\t" // L
740         "pmaxub %%mm1, %%mm4            \n\t" // max(T, L)
741         "pminub %%mm5, %%mm1            \n\t" // min(T, L)
742         "pminub %%mm2, %%mm4            \n\t"
743         "pmaxub %%mm1, %%mm4            \n\t"
744         "psubb %%mm4, %%mm3             \n\t" // dst - pred
745         "movq %%mm3, (%3, %0)           \n\t"
746         "add $8, %0                     \n\t"
747         "movq -1(%1, %0), %%mm0         \n\t" // LT
748         "cmp %4, %0                     \n\t"
749         " jb 1b                         \n\t"
750         : "+r" (i)
751         : "r" (src1), "r" (src2), "r" (dst), "r" ((x86_reg) w));
752
753     l  = *left;
754     lt = *left_top;
755
756     dst[0] = src2[0] - mid_pred(l, src1[0], (l + src1[0] - lt) & 0xFF);
757
758     *left_top = src1[w - 1];
759     *left     = src2[w - 1];
760 }
761
762 #define MMABS_MMX(a,z)                          \
763     "pxor "    #z ", " #z "             \n\t"   \
764     "pcmpgtw " #a ", " #z "             \n\t"   \
765     "pxor "    #z ", " #a "             \n\t"   \
766     "psubw "   #z ", " #a "             \n\t"
767
768 #define MMABS_MMXEXT(a, z)                      \
769     "pxor "    #z ", " #z "             \n\t"   \
770     "psubw "   #a ", " #z "             \n\t"   \
771     "pmaxsw "  #z ", " #a "             \n\t"
772
773 #define MMABS_SSSE3(a,z)                        \
774     "pabsw "   #a ", " #a "             \n\t"
775
776 #define MMABS_SUM(a,z, sum)                     \
777     MMABS(a,z)                                  \
778     "paddusw " #a ", " #sum "           \n\t"
779
780 /* FIXME: HSUM_* saturates at 64k, while an 8x8 hadamard or dct block can get
781  * up to about 100k on extreme inputs. But that's very unlikely to occur in
782  * natural video, and it's even more unlikely to not have any alternative
783  * mvs/modes with lower cost. */
784 #define HSUM_MMX(a, t, dst)                     \
785     "movq    " #a ", " #t "             \n\t"   \
786     "psrlq      $32, " #a "             \n\t"   \
787     "paddusw " #t ", " #a "             \n\t"   \
788     "movq    " #a ", " #t "             \n\t"   \
789     "psrlq      $16, " #a "             \n\t"   \
790     "paddusw " #t ", " #a "             \n\t"   \
791     "movd    " #a ", " #dst "           \n\t"   \
792
793 #define HSUM_MMXEXT(a, t, dst)                  \
794     "pshufw   $0x0E, " #a ", " #t "     \n\t"   \
795     "paddusw " #t ", " #a "             \n\t"   \
796     "pshufw   $0x01, " #a ", " #t "     \n\t"   \
797     "paddusw " #t ", " #a "             \n\t"   \
798     "movd    " #a ", " #dst "           \n\t"   \
799
800 #define HSUM_SSE2(a, t, dst)                    \
801     "movhlps " #a ", " #t "             \n\t"   \
802     "paddusw " #t ", " #a "             \n\t"   \
803     "pshuflw  $0x0E, " #a ", " #t "     \n\t"   \
804     "paddusw " #t ", " #a "             \n\t"   \
805     "pshuflw  $0x01, " #a ", " #t "     \n\t"   \
806     "paddusw " #t ", " #a "             \n\t"   \
807     "movd    " #a ", " #dst "           \n\t"   \
808
809 #define DCT_SAD4(m, mm, o)                      \
810     "mov"#m" "#o" +  0(%1), " #mm "2    \n\t"   \
811     "mov"#m" "#o" + 16(%1), " #mm "3    \n\t"   \
812     "mov"#m" "#o" + 32(%1), " #mm "4    \n\t"   \
813     "mov"#m" "#o" + 48(%1), " #mm "5    \n\t"   \
814     MMABS_SUM(mm ## 2, mm ## 6, mm ## 0)        \
815     MMABS_SUM(mm ## 3, mm ## 7, mm ## 1)        \
816     MMABS_SUM(mm ## 4, mm ## 6, mm ## 0)        \
817     MMABS_SUM(mm ## 5, mm ## 7, mm ## 1)        \
818
819 #define DCT_SAD_MMX                             \
820     "pxor    %%mm0, %%mm0               \n\t"   \
821     "pxor    %%mm1, %%mm1               \n\t"   \
822     DCT_SAD4(q, %%mm, 0)                        \
823     DCT_SAD4(q, %%mm, 8)                        \
824     DCT_SAD4(q, %%mm, 64)                       \
825     DCT_SAD4(q, %%mm, 72)                       \
826     "paddusw %%mm1, %%mm0               \n\t"   \
827     HSUM(%%mm0, %%mm1, %0)
828
829 #define DCT_SAD_SSE2                            \
830     "pxor    %%xmm0, %%xmm0             \n\t"   \
831     "pxor    %%xmm1, %%xmm1             \n\t"   \
832     DCT_SAD4(dqa, %%xmm, 0)                     \
833     DCT_SAD4(dqa, %%xmm, 64)                    \
834     "paddusw %%xmm1, %%xmm0             \n\t"   \
835     HSUM(%%xmm0, %%xmm1, %0)
836
837 #define DCT_SAD_FUNC(cpu)                           \
838 static int sum_abs_dctelem_ ## cpu(int16_t *block)  \
839 {                                                   \
840     int sum;                                        \
841     __asm__ volatile (                              \
842         DCT_SAD                                     \
843         :"=r"(sum)                                  \
844         :"r"(block));                               \
845     return sum & 0xFFFF;                            \
846 }
847
848 #define DCT_SAD         DCT_SAD_MMX
849 #define HSUM(a, t, dst) HSUM_MMX(a, t, dst)
850 #define MMABS(a, z)     MMABS_MMX(a, z)
851 DCT_SAD_FUNC(mmx)
852 #undef MMABS
853 #undef HSUM
854
855 #define HSUM(a, t, dst) HSUM_MMXEXT(a, t, dst)
856 #define MMABS(a, z)     MMABS_MMXEXT(a, z)
857 DCT_SAD_FUNC(mmxext)
858 #undef HSUM
859 #undef DCT_SAD
860
861 #define DCT_SAD         DCT_SAD_SSE2
862 #define HSUM(a, t, dst) HSUM_SSE2(a, t, dst)
863 DCT_SAD_FUNC(sse2)
864 #undef MMABS
865
866 #if HAVE_SSSE3_INLINE
867 #define MMABS(a, z)     MMABS_SSSE3(a, z)
868 DCT_SAD_FUNC(ssse3)
869 #undef MMABS
870 #endif
871 #undef HSUM
872 #undef DCT_SAD
873
874 static int ssd_int8_vs_int16_mmx(const int8_t *pix1, const int16_t *pix2,
875                                  int size)
876 {
877     int sum;
878     x86_reg i = size;
879
880     __asm__ volatile (
881         "pxor %%mm4, %%mm4 \n"
882         "1: \n"
883         "sub $8, %0 \n"
884         "movq (%2, %0), %%mm2 \n"
885         "movq (%3, %0, 2), %%mm0 \n"
886         "movq 8(%3, %0, 2), %%mm1 \n"
887         "punpckhbw %%mm2, %%mm3 \n"
888         "punpcklbw %%mm2, %%mm2 \n"
889         "psraw $8, %%mm3 \n"
890         "psraw $8, %%mm2 \n"
891         "psubw %%mm3, %%mm1 \n"
892         "psubw %%mm2, %%mm0 \n"
893         "pmaddwd %%mm1, %%mm1 \n"
894         "pmaddwd %%mm0, %%mm0 \n"
895         "paddd %%mm1, %%mm4 \n"
896         "paddd %%mm0, %%mm4 \n"
897         "jg 1b \n"
898         "movq %%mm4, %%mm3 \n"
899         "psrlq $32, %%mm3 \n"
900         "paddd %%mm3, %%mm4 \n"
901         "movd %%mm4, %1 \n"
902         : "+r" (i), "=r" (sum)
903         : "r" (pix1), "r" (pix2));
904
905     return sum;
906 }
907
908 #define PHADDD(a, t)                            \
909     "movq  " #a ", " #t "               \n\t"   \
910     "psrlq    $32, " #a "               \n\t"   \
911     "paddd " #t ", " #a "               \n\t"
912
913 /*
914  * pmulhw:   dst[0 - 15] = (src[0 - 15] * dst[0 - 15])[16 - 31]
915  * pmulhrw:  dst[0 - 15] = (src[0 - 15] * dst[0 - 15] + 0x8000)[16 - 31]
916  * pmulhrsw: dst[0 - 15] = (src[0 - 15] * dst[0 - 15] + 0x4000)[15 - 30]
917  */
918 #define PMULHRW(x, y, s, o)                     \
919     "pmulhw " #s ", " #x "              \n\t"   \
920     "pmulhw " #s ", " #y "              \n\t"   \
921     "paddw  " #o ", " #x "              \n\t"   \
922     "paddw  " #o ", " #y "              \n\t"   \
923     "psraw      $1, " #x "              \n\t"   \
924     "psraw      $1, " #y "              \n\t"
925 #define DEF(x) x ## _mmx
926 #define SET_RND MOVQ_WONE
927 #define SCALE_OFFSET 1
928
929 #include "dsputil_qns_template.c"
930
931 #undef DEF
932 #undef SET_RND
933 #undef SCALE_OFFSET
934 #undef PMULHRW
935
936 #define DEF(x) x ## _3dnow
937 #define SET_RND(x)
938 #define SCALE_OFFSET 0
939 #define PMULHRW(x, y, s, o)                     \
940     "pmulhrw " #s ", " #x "             \n\t"   \
941     "pmulhrw " #s ", " #y "             \n\t"
942
943 #include "dsputil_qns_template.c"
944
945 #undef DEF
946 #undef SET_RND
947 #undef SCALE_OFFSET
948 #undef PMULHRW
949
950 #if HAVE_SSSE3_INLINE
951 #undef PHADDD
952 #define DEF(x) x ## _ssse3
953 #define SET_RND(x)
954 #define SCALE_OFFSET -1
955
956 #define PHADDD(a, t)                            \
957     "pshufw $0x0E, " #a ", " #t "       \n\t"   \
958     /* faster than phaddd on core2 */           \
959     "paddd " #t ", " #a "               \n\t"
960
961 #define PMULHRW(x, y, s, o)                     \
962     "pmulhrsw " #s ", " #x "            \n\t"   \
963     "pmulhrsw " #s ", " #y "            \n\t"
964
965 #include "dsputil_qns_template.c"
966
967 #undef DEF
968 #undef SET_RND
969 #undef SCALE_OFFSET
970 #undef PMULHRW
971 #undef PHADDD
972 #endif /* HAVE_SSSE3_INLINE */
973
974 #endif /* HAVE_INLINE_ASM */
975
976 int ff_sse16_sse2(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
977
978 #define hadamard_func(cpu)                                              \
979 int ff_hadamard8_diff_ ## cpu(void *s, uint8_t *src1, uint8_t *src2,    \
980                               int stride, int h);                       \
981 int ff_hadamard8_diff16_ ## cpu(void *s, uint8_t *src1, uint8_t *src2,  \
982                                 int stride, int h);
983
984 hadamard_func(mmx)
985 hadamard_func(mmxext)
986 hadamard_func(sse2)
987 hadamard_func(ssse3)
988
989 av_cold void ff_dsputilenc_init_mmx(DSPContext *c, AVCodecContext *avctx,
990                                     unsigned high_bit_depth)
991 {
992     int cpu_flags = av_get_cpu_flags();
993     const int dct_algo = avctx->dct_algo;
994
995 #if HAVE_YASM
996     if (EXTERNAL_MMX(cpu_flags)) {
997         if (!high_bit_depth)
998             c->get_pixels = ff_get_pixels_mmx;
999         c->diff_pixels = ff_diff_pixels_mmx;
1000         c->pix_sum     = ff_pix_sum16_mmx;
1001         c->pix_norm1   = ff_pix_norm1_mmx;
1002     }
1003
1004     if (EXTERNAL_SSE2(cpu_flags))
1005         if (!high_bit_depth)
1006             c->get_pixels = ff_get_pixels_sse2;
1007 #endif /* HAVE_YASM */
1008
1009 #if HAVE_INLINE_ASM
1010     if (INLINE_MMX(cpu_flags)) {
1011         if (!high_bit_depth &&
1012             (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX))
1013             c->fdct = ff_fdct_mmx;
1014
1015         c->diff_bytes      = diff_bytes_mmx;
1016         c->sum_abs_dctelem = sum_abs_dctelem_mmx;
1017
1018         c->sse[0]  = sse16_mmx;
1019         c->sse[1]  = sse8_mmx;
1020         c->vsad[4] = vsad_intra16_mmx;
1021
1022         c->nsse[0] = nsse16_mmx;
1023         c->nsse[1] = nsse8_mmx;
1024         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
1025             c->vsad[0]      = vsad16_mmx;
1026             c->try_8x8basis = try_8x8basis_mmx;
1027         }
1028         c->add_8x8basis = add_8x8basis_mmx;
1029
1030         c->ssd_int8_vs_int16 = ssd_int8_vs_int16_mmx;
1031     }
1032
1033     if (INLINE_AMD3DNOW(cpu_flags)) {
1034         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
1035             c->try_8x8basis = try_8x8basis_3dnow;
1036         }
1037         c->add_8x8basis = add_8x8basis_3dnow;
1038     }
1039
1040     if (INLINE_MMXEXT(cpu_flags)) {
1041         if (!high_bit_depth &&
1042             (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX))
1043             c->fdct = ff_fdct_mmxext;
1044
1045         c->sum_abs_dctelem = sum_abs_dctelem_mmxext;
1046         c->vsad[4]         = vsad_intra16_mmxext;
1047
1048         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
1049             c->vsad[0] = vsad16_mmxext;
1050         }
1051
1052         c->sub_hfyu_median_prediction = sub_hfyu_median_prediction_mmxext;
1053     }
1054
1055     if (INLINE_SSE2(cpu_flags)) {
1056         if (!high_bit_depth &&
1057             (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX))
1058             c->fdct = ff_fdct_sse2;
1059
1060         c->sum_abs_dctelem = sum_abs_dctelem_sse2;
1061     }
1062
1063 #if HAVE_SSSE3_INLINE
1064     if (INLINE_SSSE3(cpu_flags)) {
1065         if (!(avctx->flags & CODEC_FLAG_BITEXACT)) {
1066             c->try_8x8basis = try_8x8basis_ssse3;
1067         }
1068         c->add_8x8basis    = add_8x8basis_ssse3;
1069         c->sum_abs_dctelem = sum_abs_dctelem_ssse3;
1070     }
1071 #endif
1072 #endif /* HAVE_INLINE_ASM */
1073
1074     if (EXTERNAL_MMX(cpu_flags)) {
1075         c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx;
1076         c->hadamard8_diff[1] = ff_hadamard8_diff_mmx;
1077     }
1078
1079     if (EXTERNAL_MMXEXT(cpu_flags)) {
1080         c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext;
1081         c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext;
1082     }
1083
1084     if (EXTERNAL_SSE2(cpu_flags)) {
1085         c->sse[0] = ff_sse16_sse2;
1086
1087 #if HAVE_ALIGNED_STACK
1088         c->hadamard8_diff[0] = ff_hadamard8_diff16_sse2;
1089         c->hadamard8_diff[1] = ff_hadamard8_diff_sse2;
1090 #endif
1091     }
1092
1093     if (EXTERNAL_SSSE3(cpu_flags) && HAVE_ALIGNED_STACK) {
1094         c->hadamard8_diff[0] = ff_hadamard8_diff16_ssse3;
1095         c->hadamard8_diff[1] = ff_hadamard8_diff_ssse3;
1096     }
1097
1098     ff_dsputil_init_pix_mmx(c, avctx);
1099 }