Revert "x86: dsputilenc: convert ff_sse{8, 16}_mmx() to yasm"
[ffmpeg.git] / libavcodec / x86 / dsputilenc.asm
1 ;*****************************************************************************
2 ;* MMX optimized DSP utils
3 ;*****************************************************************************
4 ;* Copyright (c) 2000, 2001 Fabrice Bellard
5 ;* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
6 ;*
7 ;* This file is part of FFmpeg.
8 ;*
9 ;* FFmpeg is free software; you can redistribute it and/or
10 ;* modify it under the terms of the GNU Lesser General Public
11 ;* License as published by the Free Software Foundation; either
12 ;* version 2.1 of the License, or (at your option) any later version.
13 ;*
14 ;* FFmpeg is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;* Lesser General Public License for more details.
18 ;*
19 ;* You should have received a copy of the GNU Lesser General Public
20 ;* License along with FFmpeg; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 ;*****************************************************************************
23
24 %include "libavutil/x86/x86util.asm"
25
26 SECTION .text
27
28 %macro DIFF_PIXELS_1 4
29     movh            %1, %3
30     movh            %2, %4
31     punpcklbw       %2, %1
32     punpcklbw       %1, %1
33     psubw           %1, %2
34 %endmacro
35
36 ; %1=uint8_t *pix1, %2=uint8_t *pix2, %3=static offset, %4=stride, %5=stride*3
37 ; %6=temporary storage location
38 ; this macro requires $mmsize stack space (aligned) on %6 (except on SSE+x86-64)
39 %macro DIFF_PIXELS_8 6
40     DIFF_PIXELS_1   m0, m7, [%1     +%3], [%2     +%3]
41     DIFF_PIXELS_1   m1, m7, [%1+%4  +%3], [%2+%4  +%3]
42     DIFF_PIXELS_1   m2, m7, [%1+%4*2+%3], [%2+%4*2+%3]
43     add             %1, %5
44     add             %2, %5
45     DIFF_PIXELS_1   m3, m7, [%1     +%3], [%2     +%3]
46     DIFF_PIXELS_1   m4, m7, [%1+%4  +%3], [%2+%4  +%3]
47     DIFF_PIXELS_1   m5, m7, [%1+%4*2+%3], [%2+%4*2+%3]
48     DIFF_PIXELS_1   m6, m7, [%1+%5  +%3], [%2+%5  +%3]
49 %ifdef m8
50     DIFF_PIXELS_1   m7, m8, [%1+%4*4+%3], [%2+%4*4+%3]
51 %else
52     mova          [%6], m0
53     DIFF_PIXELS_1   m7, m0, [%1+%4*4+%3], [%2+%4*4+%3]
54     mova            m0, [%6]
55 %endif
56     sub             %1, %5
57     sub             %2, %5
58 %endmacro
59
60 %macro HADAMARD8 0
61     SUMSUB_BADC       w, 0, 1, 2, 3
62     SUMSUB_BADC       w, 4, 5, 6, 7
63     SUMSUB_BADC       w, 0, 2, 1, 3
64     SUMSUB_BADC       w, 4, 6, 5, 7
65     SUMSUB_BADC       w, 0, 4, 1, 5
66     SUMSUB_BADC       w, 2, 6, 3, 7
67 %endmacro
68
69 %macro ABS1_SUM 3
70     ABS1            %1, %2
71     paddusw         %3, %1
72 %endmacro
73
74 %macro ABS2_SUM 6
75     ABS2            %1, %2, %3, %4
76     paddusw         %5, %1
77     paddusw         %6, %2
78 %endmacro
79
80 %macro ABS_SUM_8x8_64 1
81     ABS2            m0, m1, m8, m9
82     ABS2_SUM        m2, m3, m8, m9, m0, m1
83     ABS2_SUM        m4, m5, m8, m9, m0, m1
84     ABS2_SUM        m6, m7, m8, m9, m0, m1
85     paddusw         m0, m1
86 %endmacro
87
88 %macro ABS_SUM_8x8_32 1
89     mova          [%1], m7
90     ABS1            m0, m7
91     ABS1            m1, m7
92     ABS1_SUM        m2, m7, m0
93     ABS1_SUM        m3, m7, m1
94     ABS1_SUM        m4, m7, m0
95     ABS1_SUM        m5, m7, m1
96     ABS1_SUM        m6, m7, m0
97     mova            m2, [%1]
98     ABS1_SUM        m2, m7, m1
99     paddusw         m0, m1
100 %endmacro
101
102 ; FIXME: HSUM saturates at 64k, while an 8x8 hadamard or dct block can get up to
103 ; about 100k on extreme inputs. But that's very unlikely to occur in natural video,
104 ; and it's even more unlikely to not have any alternative mvs/modes with lower cost.
105 %macro HSUM 3
106 %if cpuflag(sse2)
107     movhlps         %2, %1
108     paddusw         %1, %2
109     pshuflw         %2, %1, 0xE
110     paddusw         %1, %2
111     pshuflw         %2, %1, 0x1
112     paddusw         %1, %2
113     movd            %3, %1
114 %elif cpuflag(mmxext)
115     pshufw          %2, %1, 0xE
116     paddusw         %1, %2
117     pshufw          %2, %1, 0x1
118     paddusw         %1, %2
119     movd            %3, %1
120 %elif cpuflag(mmx)
121     mova            %2, %1
122     psrlq           %1, 32
123     paddusw         %1, %2
124     mova            %2, %1
125     psrlq           %1, 16
126     paddusw         %1, %2
127     movd            %3, %1
128 %endif
129 %endmacro
130
131 %macro STORE4 5
132     mova [%1+mmsize*0], %2
133     mova [%1+mmsize*1], %3
134     mova [%1+mmsize*2], %4
135     mova [%1+mmsize*3], %5
136 %endmacro
137
138 %macro LOAD4 5
139     mova            %2, [%1+mmsize*0]
140     mova            %3, [%1+mmsize*1]
141     mova            %4, [%1+mmsize*2]
142     mova            %5, [%1+mmsize*3]
143 %endmacro
144
145 %macro hadamard8_16_wrapper 2
146 cglobal hadamard8_diff, 4, 4, %1
147 %ifndef m8
148     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
149     SUB            rsp, pad
150 %endif
151     call hadamard8x8_diff %+ SUFFIX
152 %ifndef m8
153     ADD            rsp, pad
154 %endif
155     RET
156
157 cglobal hadamard8_diff16, 5, 6, %1
158 %ifndef m8
159     %assign pad %2*mmsize-(4+stack_offset&(mmsize-1))
160     SUB            rsp, pad
161 %endif
162
163     call hadamard8x8_diff %+ SUFFIX
164     mov            r5d, eax
165
166     add             r1, 8
167     add             r2, 8
168     call hadamard8x8_diff %+ SUFFIX
169     add            r5d, eax
170
171     cmp            r4d, 16
172     jne .done
173
174     lea             r1, [r1+r3*8-8]
175     lea             r2, [r2+r3*8-8]
176     call hadamard8x8_diff %+ SUFFIX
177     add            r5d, eax
178
179     add             r1, 8
180     add             r2, 8
181     call hadamard8x8_diff %+ SUFFIX
182     add            r5d, eax
183
184 .done:
185     mov            eax, r5d
186 %ifndef m8
187     ADD            rsp, pad
188 %endif
189     RET
190 %endmacro
191
192 %macro HADAMARD8_DIFF 0-1
193 %if cpuflag(sse2)
194 hadamard8x8_diff %+ SUFFIX:
195     lea                          r0, [r3*3]
196     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize
197     HADAMARD8
198 %if ARCH_X86_64
199     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7,  8
200 %else
201     TRANSPOSE8x8W                 0,  1,  2,  3,  4,  5,  6,  7, [rsp+gprsize], [rsp+mmsize+gprsize]
202 %endif
203     HADAMARD8
204     ABS_SUM_8x8         rsp+gprsize
205     HSUM                        m0, m1, eax
206     and                         eax, 0xFFFF
207     ret
208
209 hadamard8_16_wrapper %1, 3
210 %elif cpuflag(mmx)
211 ALIGN 16
212 ; int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,
213 ;                               uint8_t *src2, int stride, int h)
214 ; r0 = void *s = unused, int h = unused (always 8)
215 ; note how r1, r2 and r3 are not clobbered in this function, so 16x16
216 ; can simply call this 2x2x (and that's why we access rsp+gprsize
217 ; everywhere, which is rsp of calling func
218 hadamard8x8_diff %+ SUFFIX:
219     lea                          r0, [r3*3]
220
221     ; first 4x8 pixels
222     DIFF_PIXELS_8                r1, r2,  0, r3, r0, rsp+gprsize+0x60
223     HADAMARD8
224     mova         [rsp+gprsize+0x60], m7
225     TRANSPOSE4x4W                 0,  1,  2,  3,  7
226     STORE4              rsp+gprsize, m0, m1, m2, m3
227     mova                         m7, [rsp+gprsize+0x60]
228     TRANSPOSE4x4W                 4,  5,  6,  7,  0
229     STORE4         rsp+gprsize+0x40, m4, m5, m6, m7
230
231     ; second 4x8 pixels
232     DIFF_PIXELS_8                r1, r2,  4, r3, r0, rsp+gprsize+0x60
233     HADAMARD8
234     mova         [rsp+gprsize+0x60], m7
235     TRANSPOSE4x4W                 0,  1,  2,  3,  7
236     STORE4         rsp+gprsize+0x20, m0, m1, m2, m3
237     mova                         m7, [rsp+gprsize+0x60]
238     TRANSPOSE4x4W                 4,  5,  6,  7,  0
239
240     LOAD4          rsp+gprsize+0x40, m0, m1, m2, m3
241     HADAMARD8
242     ABS_SUM_8x8_32 rsp+gprsize+0x60
243     mova         [rsp+gprsize+0x60], m0
244
245     LOAD4          rsp+gprsize     , m0, m1, m2, m3
246     LOAD4          rsp+gprsize+0x20, m4, m5, m6, m7
247     HADAMARD8
248     ABS_SUM_8x8_32 rsp+gprsize
249     paddusw                      m0, [rsp+gprsize+0x60]
250
251     HSUM                         m0, m1, eax
252     and                         rax, 0xFFFF
253     ret
254
255 hadamard8_16_wrapper 0, 14
256 %endif
257 %endmacro
258
259 INIT_MMX mmx
260 HADAMARD8_DIFF
261
262 INIT_MMX mmxext
263 HADAMARD8_DIFF
264
265 INIT_XMM sse2
266 %if ARCH_X86_64
267 %define ABS_SUM_8x8 ABS_SUM_8x8_64
268 %else
269 %define ABS_SUM_8x8 ABS_SUM_8x8_32
270 %endif
271 HADAMARD8_DIFF 10
272
273 INIT_XMM ssse3
274 %define ABS_SUM_8x8 ABS_SUM_8x8_64
275 HADAMARD8_DIFF 9
276
277 INIT_XMM sse2
278 ; int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
279 ;                   int line_size, int h);
280 cglobal sse16, 5, 5, 8
281     shr      r4d, 1
282     pxor      m0, m0         ; mm0 = 0
283     pxor      m7, m7         ; mm7 holds the sum
284
285 .next2lines: ; FIXME why are these unaligned movs? pix1[] is aligned
286     movu      m1, [r1   ]    ; mm1 = pix1[0][0-15]
287     movu      m2, [r2   ]    ; mm2 = pix2[0][0-15]
288     movu      m3, [r1+r3]    ; mm3 = pix1[1][0-15]
289     movu      m4, [r2+r3]    ; mm4 = pix2[1][0-15]
290
291     ; todo: mm1-mm2, mm3-mm4
292     ; algo: subtract mm1 from mm2 with saturation and vice versa
293     ;       OR the result to get the absolute difference
294     mova      m5, m1
295     mova      m6, m3
296     psubusb   m1, m2
297     psubusb   m3, m4
298     psubusb   m2, m5
299     psubusb   m4, m6
300
301     por       m2, m1
302     por       m4, m3
303
304     ; now convert to 16-bit vectors so we can square them
305     mova      m1, m2
306     mova      m3, m4
307
308     punpckhbw m2, m0
309     punpckhbw m4, m0
310     punpcklbw m1, m0         ; mm1 not spread over (mm1,mm2)
311     punpcklbw m3, m0         ; mm4 not spread over (mm3,mm4)
312
313     pmaddwd   m2, m2
314     pmaddwd   m4, m4
315     pmaddwd   m1, m1
316     pmaddwd   m3, m3
317
318     lea       r1, [r1+r3*2]  ; pix1 += 2*line_size
319     lea       r2, [r2+r3*2]  ; pix2 += 2*line_size
320
321     paddd     m1, m2
322     paddd     m3, m4
323     paddd     m7, m1
324     paddd     m7, m3
325
326     dec       r4
327     jnz .next2lines
328
329     mova      m1, m7
330     psrldq    m7, 8          ; shift hi qword to lo
331     paddd     m7, m1
332     mova      m1, m7
333     psrldq    m7, 4          ; shift hi dword to lo
334     paddd     m7, m1
335     movd     eax, m7         ; return value
336     RET
337
338 INIT_MMX mmx
339 ; void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, int line_size)
340 cglobal get_pixels, 3,4
341     movsxdifnidn r2, r2d
342     add          r0, 128
343     mov          r3, -128
344     pxor         m7, m7
345 .loop:
346     mova         m0, [r1]
347     mova         m2, [r1+r2]
348     mova         m1, m0
349     mova         m3, m2
350     punpcklbw    m0, m7
351     punpckhbw    m1, m7
352     punpcklbw    m2, m7
353     punpckhbw    m3, m7
354     mova [r0+r3+ 0], m0
355     mova [r0+r3+ 8], m1
356     mova [r0+r3+16], m2
357     mova [r0+r3+24], m3
358     lea          r1, [r1+r2*2]
359     add          r3, 32
360     js .loop
361     REP_RET
362
363 INIT_XMM sse2
364 cglobal get_pixels, 3, 4
365     movsxdifnidn r2, r2d
366     lea          r3, [r2*3]
367     pxor         m4, m4
368     movh         m0, [r1]
369     movh         m1, [r1+r2]
370     movh         m2, [r1+r2*2]
371     movh         m3, [r1+r3]
372     lea          r1, [r1+r2*4]
373     punpcklbw    m0, m4
374     punpcklbw    m1, m4
375     punpcklbw    m2, m4
376     punpcklbw    m3, m4
377     mova       [r0], m0
378     mova  [r0+0x10], m1
379     mova  [r0+0x20], m2
380     mova  [r0+0x30], m3
381     movh         m0, [r1]
382     movh         m1, [r1+r2*1]
383     movh         m2, [r1+r2*2]
384     movh         m3, [r1+r3]
385     punpcklbw    m0, m4
386     punpcklbw    m1, m4
387     punpcklbw    m2, m4
388     punpcklbw    m3, m4
389     mova  [r0+0x40], m0
390     mova  [r0+0x50], m1
391     mova  [r0+0x60], m2
392     mova  [r0+0x70], m3
393     RET
394
395 INIT_MMX mmx
396 ; void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2,
397 ;                         int stride);
398 cglobal diff_pixels, 4,5
399     movsxdifnidn r3, r3d
400     pxor         m7, m7
401     add          r0,  128
402     mov          r4, -128
403 .loop:
404     mova         m0, [r1]
405     mova         m2, [r2]
406     mova         m1, m0
407     mova         m3, m2
408     punpcklbw    m0, m7
409     punpckhbw    m1, m7
410     punpcklbw    m2, m7
411     punpckhbw    m3, m7
412     psubw        m0, m2
413     psubw        m1, m3
414     mova  [r0+r4+0], m0
415     mova  [r0+r4+8], m1
416     add          r1, r3
417     add          r2, r3
418     add          r4, 16
419     jne .loop
420     REP_RET
421
422 INIT_MMX mmx
423 ; int ff_pix_sum16_mmx(uint8_t *pix, int line_size)
424 cglobal pix_sum16, 2, 3
425     movsxdifnidn r1, r1d
426     mov          r2, r1
427     neg          r2
428     shl          r2, 4
429     sub          r0, r2
430     pxor         m7, m7
431     pxor         m6, m6
432 .loop:
433     mova         m0, [r0+r2+0]
434     mova         m1, [r0+r2+0]
435     mova         m2, [r0+r2+8]
436     mova         m3, [r0+r2+8]
437     punpcklbw    m0, m7
438     punpckhbw    m1, m7
439     punpcklbw    m2, m7
440     punpckhbw    m3, m7
441     paddw        m1, m0
442     paddw        m3, m2
443     paddw        m3, m1
444     paddw        m6, m3
445     add          r2, r1
446     js .loop
447     mova         m5, m6
448     psrlq        m6, 32
449     paddw        m6, m5
450     mova         m5, m6
451     psrlq        m6, 16
452     paddw        m6, m5
453     movd        eax, m6
454     and         eax, 0xffff
455     RET
456
457 INIT_MMX mmx
458 ; int ff_pix_norm1_mmx(uint8_t *pix, int line_size)
459 cglobal pix_norm1, 2, 4
460     movsxdifnidn r1, r1d
461     mov          r2, 16
462     pxor         m0, m0
463     pxor         m7, m7
464 .loop:
465     mova         m2, [r0+0]
466     mova         m3, [r0+8]
467     mova         m1, m2
468     punpckhbw    m1, m0
469     punpcklbw    m2, m0
470     mova         m4, m3
471     punpckhbw    m3, m0
472     punpcklbw    m4, m0
473     pmaddwd      m1, m1
474     pmaddwd      m2, m2
475     pmaddwd      m3, m3
476     pmaddwd      m4, m4
477     paddd        m2, m1
478     paddd        m4, m3
479     paddd        m7, m2
480     add          r0, r1
481     paddd        m7, m4
482     dec r2
483     jne .loop
484     mova         m1, m7
485     psrlq        m7, 32
486     paddd        m1, m7
487     movd        eax, m1
488     RET
489
490 ;-----------------------------------------------
491 ;int ff_sum_abs_dctelem(int16_t *block)
492 ;-----------------------------------------------
493 ; %1 = number of xmm registers used
494 ; %2 = number of inline loops
495
496 %macro SUM_ABS_DCTELEM 2
497 cglobal sum_abs_dctelem, 1, 1, %1, block
498     pxor    m0, m0
499     pxor    m1, m1
500 %assign %%i 0
501 %rep %2
502     mova      m2, [blockq+mmsize*(0+%%i)]
503     mova      m3, [blockq+mmsize*(1+%%i)]
504     mova      m4, [blockq+mmsize*(2+%%i)]
505     mova      m5, [blockq+mmsize*(3+%%i)]
506     ABS1_SUM  m2, m6, m0
507     ABS1_SUM  m3, m6, m1
508     ABS1_SUM  m4, m6, m0
509     ABS1_SUM  m5, m6, m1
510 %assign %%i %%i+4
511 %endrep
512     paddusw m0, m1
513     HSUM    m0, m1, eax
514     and     eax, 0xFFFF
515     RET
516 %endmacro
517
518 INIT_MMX mmx
519 SUM_ABS_DCTELEM 0, 4
520 INIT_MMX mmxext
521 SUM_ABS_DCTELEM 0, 4
522 INIT_XMM sse2
523 SUM_ABS_DCTELEM 7, 2
524 INIT_XMM ssse3
525 SUM_ABS_DCTELEM 6, 2