]> git.sesse.net Git - x264/blob - common/x86/pixel-a.asm
Faster width4 SSD+SATD, SSE4 optimizations
[x264] / common / x86 / pixel-a.asm
1 ;*****************************************************************************
2 ;* pixel.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2003-2008 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
7 ;*          Laurent Aimar <fenrir@via.ecp.fr>
8 ;*          Alex Izvorski <aizvorksi@gmail.com>
9 ;*
10 ;* This program is free software; you can redistribute it and/or modify
11 ;* it under the terms of the GNU General Public License as published by
12 ;* the Free Software Foundation; either version 2 of the License, or
13 ;* (at your option) any later version.
14 ;*
15 ;* This program 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
18 ;* GNU General Public License for more details.
19 ;*
20 ;* You should have received a copy of the GNU General Public License
21 ;* along with this program; if not, write to the Free Software
22 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
23 ;*****************************************************************************
24
25 %include "x86inc.asm"
26 %include "x86util.asm"
27
28 SECTION_RODATA
29 pw_1:    times 8 dw 1
30 ssim_c1: times 4 dd 416    ; .01*.01*255*255*64
31 ssim_c2: times 4 dd 235963 ; .03*.03*255*255*64*63
32 mask_ff: times 16 db 0xff
33          times 16 db 0
34 mask_ac4: dw 0,-1,-1,-1, 0,-1,-1,-1
35 mask_ac8: dw 0,-1,-1,-1,-1,-1,-1,-1
36
37 SECTION .text
38
39 %macro HADDD 2 ; sum junk
40 %if mmsize == 16
41     movhlps %2, %1
42     paddd   %1, %2
43     pshuflw %2, %1, 0xE
44     paddd   %1, %2
45 %else
46     mova    %2, %1
47     psrlq   %2, 32
48     paddd   %1, %2
49 %endif
50 %endmacro
51
52 %macro HADDW 2
53     pmaddwd %1, [pw_1 GLOBAL]
54     HADDD   %1, %2
55 %endmacro
56
57 %macro HADDUW 2
58     mova  %2, %1
59     pslld %1, 16
60     psrld %2, 16
61     psrld %1, 16
62     paddd %1, %2
63     HADDD %1, %2
64 %endmacro
65
66 ;=============================================================================
67 ; SSD
68 ;=============================================================================
69
70 %macro SSD_FULL 6
71     mova      m1, [r0+%1]
72     mova      m2, [r2+%2]
73     mova      m3, [r0+%3]
74     mova      m4, [r2+%4]
75
76     mova      m5, m2
77     mova      m6, m4
78     psubusb   m2, m1
79     psubusb   m4, m3
80     psubusb   m1, m5
81     psubusb   m3, m6
82     por       m1, m2
83     por       m3, m4
84
85     mova      m2, m1
86     mova      m4, m3
87     punpcklbw m1, m7
88     punpcklbw m3, m7
89     punpckhbw m2, m7
90     punpckhbw m4, m7
91     pmaddwd   m1, m1
92     pmaddwd   m2, m2
93     pmaddwd   m3, m3
94     pmaddwd   m4, m4
95
96 %if %6
97     lea       r0, [r0+2*r1]
98     lea       r2, [r2+2*r3]
99 %endif
100     paddd     m1, m2
101     paddd     m3, m4
102 %if %5
103     paddd     m0, m1
104 %else
105     SWAP      m0, m1
106 %endif
107     paddd     m0, m3
108 %endmacro
109
110 %macro SSD_HALF 6
111     movh      m1, [r0+%1]
112     movh      m2, [r2+%2]
113     movh      m3, [r0+%3]
114     movh      m4, [r2+%4]
115
116     punpcklbw m1, m7
117     punpcklbw m2, m7
118     punpcklbw m3, m7
119     punpcklbw m4, m7
120     psubw     m1, m2
121     psubw     m3, m4
122     pmaddwd   m1, m1
123     pmaddwd   m3, m3
124
125 %if %6
126     lea       r0, [r0+2*r1]
127     lea       r2, [r2+2*r3]
128 %endif
129 %if %5
130     paddd     m0, m1
131 %else
132     SWAP      m0, m1
133 %endif
134     paddd     m0, m3
135 %endmacro
136
137 %macro SSD_QUARTER 6
138     movd      m1, [r0+%1]
139     movd      m2, [r2+%2]
140     movd      m3, [r0+%3]
141     movd      m4, [r2+%4]
142     lea       r0, [r0+2*r1]
143     lea       r2, [r2+2*r3]
144     pinsrd    m1, [r0+%1], 1
145     pinsrd    m2, [r2+%2], 1
146     pinsrd    m3, [r0+%3], 1
147     pinsrd    m4, [r2+%4], 1
148     punpcklbw m1, m7
149     punpcklbw m2, m7
150     punpcklbw m3, m7
151     punpcklbw m4, m7
152     psubw     m1, m2
153     psubw     m3, m4
154     pmaddwd   m1, m1
155     pmaddwd   m3, m3
156
157 %if %6
158     lea       r0, [r0+2*r1]
159     lea       r2, [r2+2*r3]
160 %endif
161 %if %5
162     paddd     m0, m1
163 %else
164     SWAP      m0, m1
165 %endif
166     paddd     m0, m3
167 %endmacro
168
169 ;-----------------------------------------------------------------------------
170 ; int x264_pixel_ssd_16x16_mmx( uint8_t *, int, uint8_t *, int )
171 ;-----------------------------------------------------------------------------
172 %macro SSD 3
173 cglobal x264_pixel_ssd_%1x%2_%3, 4,4
174 %if %1 >= mmsize
175     pxor    m7, m7
176 %endif
177 %assign i 0
178 %rep %2/2
179 %if %1 > mmsize
180     SSD_FULL 0,  0,     mmsize,    mmsize, i, 0
181     SSD_FULL r1, r3, r1+mmsize, r3+mmsize, 1, i<%2/2-1
182 %elif %1 == mmsize
183     SSD_FULL 0, 0, r1, r3, i, i<%2/2-1
184 %else
185     SSD_HALF 0, 0, r1, r3, i, i<%2/2-1
186 %endif
187 %assign i i+1
188 %endrep
189     HADDD   m0, m1
190     movd   eax, m0
191     RET
192 %endmacro
193
194 INIT_MMX
195 SSD 16, 16, mmx
196 SSD 16,  8, mmx
197 SSD  8, 16, mmx
198 SSD  8,  8, mmx
199 SSD  8,  4, mmx
200 SSD  4,  8, mmx
201 SSD  4,  4, mmx
202 INIT_XMM
203 SSD 16, 16, sse2
204 SSD 16,  8, sse2
205 SSD  8, 16, sse2
206 SSD  8,  8, sse2
207 SSD  8,  4, sse2
208
209 cglobal x264_pixel_ssd_4x8_sse4, 4,4
210     SSD_QUARTER 0, 0, r1, r3, 0, 1
211     SSD_QUARTER 0, 0, r1, r3, 1, 0
212     HADDD   m0, m1
213     movd   eax, m0
214     RET
215
216 cglobal x264_pixel_ssd_4x4_sse4, 4,4
217     SSD_QUARTER 0, 0, r1, r3, 0, 0
218     HADDD   m0, m1
219     movd   eax, m0
220     RET
221
222
223 ;=============================================================================
224 ; variance
225 ;=============================================================================
226
227 %macro VAR_START 0
228     pxor  m5, m5    ; sum
229     pxor  m6, m6    ; sum squared
230     pxor  m7, m7    ; zero
231 %ifdef ARCH_X86_64
232     %define t3d r3d
233 %else
234     %define t3d r2d
235 %endif
236 %endmacro
237
238 %macro VAR_END 1
239 %if mmsize == 16
240     movhlps m0, m5
241     paddw   m5, m0
242 %endif
243     movifnidn r2d, r2m
244     movd   r1d, m5
245     movd  [r2], m5  ; return sum
246     imul   r1d, r1d
247     HADDD   m6, m1
248     shr    r1d, %1
249     movd   eax, m6
250     sub    eax, r1d  ; sqr - (sum * sum >> shift)
251     RET
252 %endmacro
253
254 %macro VAR_2ROW 2
255     mov      t3d, %2
256 .loop:
257     mova      m0, [r0]
258     mova      m1, m0
259     mova      m3, [r0+%1]
260     mova      m2, m0
261     punpcklbw m0, m7
262     mova      m4, m3
263     punpckhbw m1, m7
264 %ifidn %1, r1
265     lea       r0, [r0+%1*2]
266 %else
267     add       r0, r1
268 %endif
269     punpckhbw m4, m7
270     psadbw    m2, m7
271     paddw     m5, m2
272     mova      m2, m3
273     punpcklbw m3, m7
274     dec t3d
275     psadbw    m2, m7
276     pmaddwd   m0, m0
277     paddw     m5, m2
278     pmaddwd   m1, m1
279     paddd     m6, m0
280     pmaddwd   m3, m3
281     paddd     m6, m1
282     pmaddwd   m4, m4
283     paddd     m6, m3
284     paddd     m6, m4
285     jg .loop
286 %endmacro
287
288 ;-----------------------------------------------------------------------------
289 ; int x264_pixel_var_wxh_mmxext( uint8_t *, int, int * )
290 ;-----------------------------------------------------------------------------
291 INIT_MMX
292 cglobal x264_pixel_var_16x16_mmxext, 2,3
293     VAR_START
294     VAR_2ROW 8, 16
295     VAR_END 8
296
297 cglobal x264_pixel_var_8x8_mmxext, 2,3
298     VAR_START
299     VAR_2ROW r1, 4
300     VAR_END 6
301
302 INIT_XMM
303 cglobal x264_pixel_var_16x16_sse2, 2,3
304     VAR_START
305     VAR_2ROW r1, 8
306     VAR_END 8
307
308 cglobal x264_pixel_var_8x8_sse2, 2,3
309     VAR_START
310     mov t3d, 4
311 .loop:
312     movh      m0, [r0]
313     movhps    m0, [r0+r1]
314     lea       r0, [r0+r1*2]
315     mova      m1, m0
316     punpcklbw m0, m7
317     mova      m2, m1
318     punpckhbw m1, m7
319     dec t3d
320     pmaddwd   m0, m0
321     pmaddwd   m1, m1
322     psadbw    m2, m7
323     paddw     m5, m2
324     paddd     m6, m0
325     paddd     m6, m1
326     jnz .loop
327     VAR_END 6
328
329
330 ;=============================================================================
331 ; SATD
332 ;=============================================================================
333
334 ; phaddw is used only in 4x4 hadamard, because in 8x8 it's slower:
335 ; even on Penryn, phaddw has latency 3 while paddw and punpck* have 1.
336 ; 4x4 is special in that 4x4 transpose in xmmregs takes extra munging,
337 ; whereas phaddw-based transform doesn't care what order the coefs end up in.
338
339 %macro PHSUMSUB 3
340     movdqa m%3, m%1
341     phaddw m%1, m%2
342     phsubw m%3, m%2
343     SWAP %2, %3
344 %endmacro
345
346 %macro HADAMARD4_ROW_PHADD 5
347     PHSUMSUB %1, %2, %5
348     PHSUMSUB %3, %4, %5
349     PHSUMSUB %1, %3, %5
350     PHSUMSUB %2, %4, %5
351     SWAP %3, %4
352 %endmacro
353
354 %macro HADAMARD4_1D 4
355     SUMSUB_BADC %1, %2, %3, %4
356     SUMSUB_BADC %1, %3, %2, %4
357 %endmacro
358
359 %macro HADAMARD4x4_SUM 1    ; %1 = dest (row sum of one block)
360     %xdefine %%n n%1
361     HADAMARD4_1D  m4, m5, m6, m7
362     TRANSPOSE4x4W  4,  5,  6,  7, %%n
363     HADAMARD4_1D  m4, m5, m6, m7
364     ABS2          m4, m5, m3, m %+ %%n
365     ABS2          m6, m7, m3, m %+ %%n
366     paddw         m6, m4
367     paddw         m7, m5
368     pavgw         m6, m7
369     SWAP %%n, 6
370 %endmacro
371
372 ; in: r4=3*stride1, r5=3*stride2
373 ; in: %2 = horizontal offset
374 ; in: %3 = whether we need to increment pix1 and pix2
375 ; clobber: m3..m7
376 ; out: %1 = satd
377 %macro SATD_4x4_MMX 3
378     LOAD_DIFF m4, m3, none, [r0+%2],      [r2+%2]
379     LOAD_DIFF m5, m3, none, [r0+r1+%2],   [r2+r3+%2]
380     LOAD_DIFF m6, m3, none, [r0+2*r1+%2], [r2+2*r3+%2]
381     LOAD_DIFF m7, m3, none, [r0+r4+%2],   [r2+r5+%2]
382 %if %3
383     lea  r0, [r0+4*r1]
384     lea  r2, [r2+4*r3]
385 %endif
386     HADAMARD4x4_SUM %1
387 %endmacro
388
389 %macro SATD_8x4_SSE2 1
390     HADAMARD4_1D    m0, m1, m2, m3
391 %ifidn %1, ssse3_phadd
392     HADAMARD4_ROW_PHADD 0, 1, 2, 3, 4
393 %else
394     TRANSPOSE2x4x4W  0,  1,  2,  3,  4
395     HADAMARD4_1D    m0, m1, m2, m3
396 %endif
397     ABS4            m0, m1, m2, m3, m4, m5
398     paddusw  m0, m1
399     paddusw  m2, m3
400     paddusw  m6, m0
401     paddusw  m6, m2
402 %endmacro
403
404 %macro SATD_START_MMX 0
405     lea  r4, [3*r1] ; 3*stride1
406     lea  r5, [3*r3] ; 3*stride2
407 %endmacro
408
409 %macro SATD_END_MMX 0
410     pshufw      m1, m0, 01001110b
411     paddw       m0, m1
412     pshufw      m1, m0, 10110001b
413     paddw       m0, m1
414     movd       eax, m0
415     and        eax, 0xffff
416     RET
417 %endmacro
418
419 ; FIXME avoid the spilling of regs to hold 3*stride.
420 ; for small blocks on x86_32, modify pixel pointer instead.
421
422 ;-----------------------------------------------------------------------------
423 ; int x264_pixel_satd_16x16_mmxext (uint8_t *, int, uint8_t *, int )
424 ;-----------------------------------------------------------------------------
425 INIT_MMX
426 cglobal x264_pixel_satd_16x4_internal_mmxext
427     SATD_4x4_MMX m2,  0, 0
428     SATD_4x4_MMX m1,  4, 0
429     paddw        m0, m2
430     SATD_4x4_MMX m2,  8, 0
431     paddw        m0, m1
432     SATD_4x4_MMX m1, 12, 0
433     paddw        m0, m2
434     paddw        m0, m1
435     ret
436
437 cglobal x264_pixel_satd_8x8_internal_mmxext
438     SATD_4x4_MMX m2,  0, 0
439     SATD_4x4_MMX m1,  4, 1
440     paddw        m0, m2
441     paddw        m0, m1
442 x264_pixel_satd_8x4_internal_mmxext:
443     SATD_4x4_MMX m2,  0, 0
444     SATD_4x4_MMX m1,  4, 0
445     paddw        m0, m2
446     paddw        m0, m1
447     ret
448
449 cglobal x264_pixel_satd_16x16_mmxext, 4,6
450     SATD_START_MMX
451     pxor   m0, m0
452 %rep 3
453     call x264_pixel_satd_16x4_internal_mmxext
454     lea  r0, [r0+4*r1]
455     lea  r2, [r2+4*r3]
456 %endrep
457     call x264_pixel_satd_16x4_internal_mmxext
458     HADDUW m0, m1
459     movd  eax, m0
460     RET
461
462 cglobal x264_pixel_satd_16x8_mmxext, 4,6
463     SATD_START_MMX
464     pxor   m0, m0
465     call x264_pixel_satd_16x4_internal_mmxext
466     lea  r0, [r0+4*r1]
467     lea  r2, [r2+4*r3]
468     call x264_pixel_satd_16x4_internal_mmxext
469     SATD_END_MMX
470
471 cglobal x264_pixel_satd_8x16_mmxext, 4,6
472     SATD_START_MMX
473     pxor   m0, m0
474     call x264_pixel_satd_8x8_internal_mmxext
475     lea  r0, [r0+4*r1]
476     lea  r2, [r2+4*r3]
477     call x264_pixel_satd_8x8_internal_mmxext
478     SATD_END_MMX
479
480 cglobal x264_pixel_satd_8x8_mmxext, 4,6
481     SATD_START_MMX
482     pxor   m0, m0
483     call x264_pixel_satd_8x8_internal_mmxext
484     SATD_END_MMX
485
486 cglobal x264_pixel_satd_8x4_mmxext, 4,6
487     SATD_START_MMX
488     pxor   m0, m0
489     call x264_pixel_satd_8x4_internal_mmxext
490     SATD_END_MMX
491
492 cglobal x264_pixel_satd_4x8_mmxext, 4,6
493     SATD_START_MMX
494     SATD_4x4_MMX m0, 0, 1
495     SATD_4x4_MMX m1, 0, 0
496     paddw  m0, m1
497     SATD_END_MMX
498
499 %macro SATD_W4 1
500 INIT_MMX
501 cglobal x264_pixel_satd_4x4_%1, 4,6
502     SATD_START_MMX
503     SATD_4x4_MMX m0, 0, 0
504     SATD_END_MMX
505 %endmacro
506
507 SATD_W4 mmxext
508
509 %macro SATD_START_SSE2 0
510     pxor    m6, m6
511     lea     r4, [3*r1]
512     lea     r5, [3*r3]
513 %endmacro
514
515 %macro SATD_END_SSE2 0
516     psrlw   m6, 1
517     HADDW   m6, m7
518     movd   eax, m6
519     RET
520 %endmacro
521
522 %macro BACKUP_POINTERS 0
523 %ifdef ARCH_X86_64
524     mov    r10, r0
525     mov    r11, r2
526 %endif
527 %endmacro
528
529 %macro RESTORE_AND_INC_POINTERS 0
530 %ifdef ARCH_X86_64
531     lea     r0, [r10+8]
532     lea     r2, [r11+8]
533 %else
534     mov     r0, r0m
535     mov     r2, r2m
536     add     r0, 8
537     add     r2, 8
538 %endif
539 %endmacro
540
541 ;-----------------------------------------------------------------------------
542 ; int x264_pixel_satd_8x4_sse2 (uint8_t *, int, uint8_t *, int )
543 ;-----------------------------------------------------------------------------
544 %macro SATDS_SSE2 1
545 INIT_XMM
546 cglobal x264_pixel_satd_8x8_internal_%1
547     LOAD_DIFF_8x4P  m0, m1, m2, m3, m4, m5
548     SATD_8x4_SSE2 %1
549     lea  r0, [r0+4*r1]
550     lea  r2, [r2+4*r3]
551 x264_pixel_satd_8x4_internal_%1:
552     LOAD_DIFF_8x4P  m0, m1, m2, m3, m4, m5
553 x264_pixel_satd_4x8_internal_%1:
554     SAVE_MM_PERMUTATION satd_4x8_internal
555     SATD_8x4_SSE2 %1
556     ret
557
558 cglobal x264_pixel_satd_16x16_%1, 4,6
559     SATD_START_SSE2
560     BACKUP_POINTERS
561     call x264_pixel_satd_8x8_internal_%1
562     lea  r0, [r0+4*r1]
563     lea  r2, [r2+4*r3]
564     call x264_pixel_satd_8x8_internal_%1
565     RESTORE_AND_INC_POINTERS
566     call x264_pixel_satd_8x8_internal_%1
567     lea  r0, [r0+4*r1]
568     lea  r2, [r2+4*r3]
569     call x264_pixel_satd_8x8_internal_%1
570     SATD_END_SSE2
571
572 cglobal x264_pixel_satd_16x8_%1, 4,6
573     SATD_START_SSE2
574     BACKUP_POINTERS
575     call x264_pixel_satd_8x8_internal_%1
576     RESTORE_AND_INC_POINTERS
577     call x264_pixel_satd_8x8_internal_%1
578     SATD_END_SSE2
579
580 cglobal x264_pixel_satd_8x16_%1, 4,6
581     SATD_START_SSE2
582     call x264_pixel_satd_8x8_internal_%1
583     lea  r0, [r0+4*r1]
584     lea  r2, [r2+4*r3]
585     call x264_pixel_satd_8x8_internal_%1
586     SATD_END_SSE2
587
588 cglobal x264_pixel_satd_8x8_%1, 4,6
589     SATD_START_SSE2
590     call x264_pixel_satd_8x8_internal_%1
591     SATD_END_SSE2
592
593 cglobal x264_pixel_satd_8x4_%1, 4,6
594     SATD_START_SSE2
595     call x264_pixel_satd_8x4_internal_%1
596     SATD_END_SSE2
597
598 cglobal x264_pixel_satd_4x8_%1, 4,6
599     INIT_XMM
600     LOAD_MM_PERMUTATION satd_4x8_internal
601     %define movh movd
602     SATD_START_SSE2
603     LOAD_DIFF  m0, m7, m6, [r0],      [r2]
604     LOAD_DIFF  m1, m7, m6, [r0+r1],   [r2+r3]
605     LOAD_DIFF  m2, m7, m6, [r0+2*r1], [r2+2*r3]
606     LOAD_DIFF  m3, m7, m6, [r0+r4],   [r2+r5]
607     lea        r0, [r0+4*r1]
608     lea        r2, [r2+4*r3]
609     LOAD_DIFF  m4, m7, m6, [r0],      [r2]
610     LOAD_DIFF  m5, m7, m6, [r0+r1],   [r2+r3]
611     punpcklqdq m0, m4
612     punpcklqdq m1, m5
613     LOAD_DIFF  m4, m7, m6, [r0+2*r1], [r2+2*r3]
614     LOAD_DIFF  m5, m7, m6, [r0+r4],   [r2+r5]
615     punpcklqdq m2, m4
616     punpcklqdq m3, m5
617     %define movh movq
618     call x264_pixel_satd_4x8_internal_%1
619     SATD_END_SSE2
620
621 %ifdef ARCH_X86_64
622 ;-----------------------------------------------------------------------------
623 ; int x264_pixel_sa8d_8x8_sse2( uint8_t *, int, uint8_t *, int )
624 ;-----------------------------------------------------------------------------
625 cglobal x264_pixel_sa8d_8x8_internal_%1
626     lea  r10, [r0+4*r1]
627     lea  r11, [r2+4*r3]
628     LOAD_DIFF_8x4P m0, m1, m2, m3, m8, m9, r0, r2
629     LOAD_DIFF_8x4P m4, m5, m6, m7, m8, m9, r10, r11
630
631     HADAMARD8_1D  m0, m1, m2, m3, m4, m5, m6, m7
632     TRANSPOSE8x8W  0,  1,  2,  3,  4,  5,  6,  7,  8
633     HADAMARD8_1D  m0, m1, m2, m3, m4, m5, m6, m7
634
635     ABS4 m0, m1, m2, m3, m8, m9
636     ABS4 m4, m5, m6, m7, m8, m9
637     paddusw  m0, m1
638     paddusw  m2, m3
639     paddusw  m4, m5
640     paddusw  m6, m7
641     paddusw  m0, m2
642     paddusw  m4, m6
643     pavgw    m0, m4
644     ret
645
646 cglobal x264_pixel_sa8d_8x8_%1, 4,6
647     lea  r4, [3*r1]
648     lea  r5, [3*r3]
649     call x264_pixel_sa8d_8x8_internal_%1
650     HADDW m0, m1
651     movd eax, m0
652     add eax, 1
653     shr eax, 1
654     ret
655
656 cglobal x264_pixel_sa8d_16x16_%1, 4,6
657     lea  r4, [3*r1]
658     lea  r5, [3*r3]
659     call x264_pixel_sa8d_8x8_internal_%1 ; pix[0]
660     add  r0, 8
661     add  r2, 8
662     mova m10, m0
663     call x264_pixel_sa8d_8x8_internal_%1 ; pix[8]
664     lea  r0, [r0+8*r1]
665     lea  r2, [r2+8*r3]
666     paddusw m10, m0
667     call x264_pixel_sa8d_8x8_internal_%1 ; pix[8*stride+8]
668     sub  r0, 8
669     sub  r2, 8
670     paddusw m10, m0
671     call x264_pixel_sa8d_8x8_internal_%1 ; pix[8*stride]
672     paddusw m0, m10
673     HADDUW m0, m1
674     movd eax, m0
675     add  eax, 1
676     shr  eax, 1
677     ret
678
679 %else ; ARCH_X86_32
680 cglobal x264_pixel_sa8d_8x8_internal_%1
681     LOAD_DIFF_8x4P m0, m1, m2, m3, m6, m7
682     movdqa [esp+4], m2
683     lea  r0, [r0+4*r1]
684     lea  r2, [r2+4*r3]
685     LOAD_DIFF_8x4P m4, m5, m6, m7, m2, m2
686     movdqa m2, [esp+4]
687
688     HADAMARD8_1D  m0, m1, m2, m3, m4, m5, m6, m7
689     TRANSPOSE8x8W  0,  1,  2,  3,  4,  5,  6,  7, [esp+4], [esp+20]
690     HADAMARD8_1D  m0, m1, m2, m3, m4, m5, m6, m7
691
692 %ifidn %1, sse2
693     movdqa [esp+4], m4
694     movdqa [esp+20], m2
695 %endif
696     ABS2 m6, m3, m4, m2
697     ABS2 m0, m7, m4, m2
698     paddusw m0, m6
699     paddusw m7, m3
700 %ifidn %1, sse2
701     movdqa m4, [esp+4]
702     movdqa m2, [esp+20]
703 %endif
704     ABS2 m5, m1, m6, m3
705     ABS2 m4, m2, m6, m3
706     paddusw m5, m1
707     paddusw m4, m2
708     paddusw m0, m7
709     paddusw m5, m4
710     pavgw   m0, m5
711     ret
712 %endif ; ARCH
713 %endmacro ; SATDS_SSE2
714
715 %macro SA8D_16x16_32 1
716 %ifndef ARCH_X86_64
717 cglobal x264_pixel_sa8d_8x8_%1, 4,7
718     mov  r6, esp
719     and  esp, ~15
720     sub  esp, 32
721     lea  r4, [3*r1]
722     lea  r5, [3*r3]
723     call x264_pixel_sa8d_8x8_internal_%1
724     HADDW m0, m1
725     movd eax, m0
726     add  eax, 1
727     shr  eax, 1
728     mov  esp, r6
729     RET
730
731 cglobal x264_pixel_sa8d_16x16_%1, 4,7
732     mov  r6, esp
733     and  esp, ~15
734     sub  esp, 48
735     lea  r4, [3*r1]
736     lea  r5, [3*r3]
737     call x264_pixel_sa8d_8x8_internal_%1
738     lea  r0, [r0+4*r1]
739     lea  r2, [r2+4*r3]
740     mova [esp+32], m0
741     call x264_pixel_sa8d_8x8_internal_%1
742     mov  r0, [r6+20]
743     mov  r2, [r6+28]
744     add  r0, 8
745     add  r2, 8
746     paddusw m0, [esp+32]
747     mova [esp+32], m0
748     call x264_pixel_sa8d_8x8_internal_%1
749     lea  r0, [r0+4*r1]
750     lea  r2, [r2+4*r3]
751 %if mmsize == 16
752     paddusw m0, [esp+32]
753 %endif
754     mova [esp+48-mmsize], m0
755     call x264_pixel_sa8d_8x8_internal_%1
756     paddusw m0, [esp+48-mmsize]
757 %if mmsize == 16
758     HADDUW m0, m1
759 %else
760     mova m2, [esp+32]
761     pxor m7, m7
762     mova m1, m0
763     mova m3, m2
764     punpcklwd m0, m7
765     punpckhwd m1, m7
766     punpcklwd m2, m7
767     punpckhwd m3, m7
768     paddd m0, m1
769     paddd m2, m3
770     paddd m0, m2
771     HADDD m0, m1
772 %endif
773     movd eax, m0
774     add  eax, 1
775     shr  eax, 1
776     mov  esp, r6
777     RET
778 %endif ; !ARCH_X86_64
779 %endmacro ; SA8D_16x16_32
780
781
782
783 ;=============================================================================
784 ; INTRA SATD
785 ;=============================================================================
786
787 %macro INTRA_SA8D_SSE2 1
788 %ifdef ARCH_X86_64
789 INIT_XMM
790 ;-----------------------------------------------------------------------------
791 ; void x264_intra_sa8d_x3_8x8_core_sse2( uint8_t *fenc, int16_t edges[2][8], int *res )
792 ;-----------------------------------------------------------------------------
793 cglobal x264_intra_sa8d_x3_8x8_core_%1
794     ; 8x8 hadamard
795     pxor        m8, m8
796     movq        m0, [r0+0*FENC_STRIDE]
797     movq        m1, [r0+1*FENC_STRIDE]
798     movq        m2, [r0+2*FENC_STRIDE]
799     movq        m3, [r0+3*FENC_STRIDE]
800     movq        m4, [r0+4*FENC_STRIDE]
801     movq        m5, [r0+5*FENC_STRIDE]
802     movq        m6, [r0+6*FENC_STRIDE]
803     movq        m7, [r0+7*FENC_STRIDE]
804     punpcklbw   m0, m8
805     punpcklbw   m1, m8
806     punpcklbw   m2, m8
807     punpcklbw   m3, m8
808     punpcklbw   m4, m8
809     punpcklbw   m5, m8
810     punpcklbw   m6, m8
811     punpcklbw   m7, m8
812     HADAMARD8_1D  m0, m1, m2, m3, m4, m5, m6, m7
813     TRANSPOSE8x8W  0,  1,  2,  3,  4,  5,  6,  7,  8
814     HADAMARD8_1D  m0, m1, m2, m3, m4, m5, m6, m7
815
816     ; dc
817     movzx       edi, word [r1+0]
818     add          di, word [r1+16]
819     add         edi, 8
820     and         edi, -16
821     shl         edi, 2
822
823     pxor        m15, m15
824     movdqa      m8,  m2
825     movdqa      m9,  m3
826     movdqa      m10, m4
827     movdqa      m11, m5
828     ABS4        m8, m9, m10, m11, m12, m13
829     paddusw     m8,  m10
830     paddusw     m9,  m11
831 %ifidn %1, ssse3
832     pabsw       m10, m6
833     pabsw       m11, m7
834     pabsw       m15, m1
835 %else
836     movdqa      m10, m6
837     movdqa      m11, m7
838     movdqa      m15, m1
839     ABS2        m10, m11, m13, m14
840     ABS1        m15, m13
841 %endif
842     paddusw     m10, m11
843     paddusw     m8,  m9
844     paddusw     m15, m10
845     paddusw     m15, m8
846     movdqa      m14, m15 ; 7x8 sum
847
848     movdqa      m8,  [r1+0] ; left edge
849     movd        m9,  edi
850     psllw       m8,  3
851     psubw       m8,  m0
852     psubw       m9,  m0
853     ABS1        m8,  m10
854     ABS1        m9,  m11 ; 1x8 sum
855     paddusw     m14, m8
856     paddusw     m15, m9
857     punpcklwd   m0,  m1
858     punpcklwd   m2,  m3
859     punpcklwd   m4,  m5
860     punpcklwd   m6,  m7
861     punpckldq   m0,  m2
862     punpckldq   m4,  m6
863     punpcklqdq  m0,  m4 ; transpose
864     movdqa      m1,  [r1+16] ; top edge
865     movdqa      m2,  m15
866     psllw       m1,  3
867     psrldq      m2,  2     ; 8x7 sum
868     psubw       m0,  m1  ; 8x1 sum
869     ABS1        m0,  m1
870     paddusw     m2,  m0
871
872     ; 3x HADDW
873     movdqa      m7,  [pw_1 GLOBAL]
874     pmaddwd     m2,  m7
875     pmaddwd     m14, m7
876     pmaddwd     m15, m7
877     movdqa      m3,  m2
878     punpckldq   m2,  m14
879     punpckhdq   m3,  m14
880     pshufd      m5,  m15, 0xf5
881     paddd       m2,  m3
882     paddd       m5,  m15
883     movdqa      m3,  m2
884     punpcklqdq  m2,  m5
885     punpckhqdq  m3,  m5
886     pavgw       m3,  m2
887     pxor        m0,  m0
888     pavgw       m3,  m0
889     movq      [r2],  m3 ; i8x8_v, i8x8_h
890     psrldq      m3,  8
891     movd    [r2+8],  m3 ; i8x8_dc
892     ret
893 %endif ; ARCH_X86_64
894 %endmacro ; INTRA_SA8D_SSE2
895
896 ; in: r0 = fenc
897 ; out: m0..m3 = hadamard coefs
898 INIT_MMX
899 ALIGN 16
900 load_hadamard:
901     pxor        m7, m7
902     movd        m0, [r0+0*FENC_STRIDE]
903     movd        m1, [r0+1*FENC_STRIDE]
904     movd        m2, [r0+2*FENC_STRIDE]
905     movd        m3, [r0+3*FENC_STRIDE]
906     punpcklbw   m0, m7
907     punpcklbw   m1, m7
908     punpcklbw   m2, m7
909     punpcklbw   m3, m7
910     HADAMARD4_1D  m0, m1, m2, m3
911     TRANSPOSE4x4W  0,  1,  2,  3,  4
912     HADAMARD4_1D  m0, m1, m2, m3
913     SAVE_MM_PERMUTATION load_hadamard
914     ret
915
916 %macro SCALAR_SUMSUB 4
917     add %1, %2
918     add %3, %4
919     add %2, %2
920     add %4, %4
921     sub %2, %1
922     sub %4, %3
923 %endmacro
924
925 %macro SCALAR_HADAMARD_LEFT 5 ; y, 4x tmp
926 %ifnidn %1, 0
927     shl         %1d, 5 ; log(FDEC_STRIDE)
928 %endif
929     movzx       %2d, byte [r1+%1-1+0*FDEC_STRIDE]
930     movzx       %3d, byte [r1+%1-1+1*FDEC_STRIDE]
931     movzx       %4d, byte [r1+%1-1+2*FDEC_STRIDE]
932     movzx       %5d, byte [r1+%1-1+3*FDEC_STRIDE]
933 %ifnidn %1, 0
934     shr         %1d, 5
935 %endif
936     SCALAR_SUMSUB %2d, %3d, %4d, %5d
937     SCALAR_SUMSUB %2d, %4d, %3d, %5d
938     mov         [left_1d+2*%1+0], %2w
939     mov         [left_1d+2*%1+2], %3w
940     mov         [left_1d+2*%1+4], %4w
941     mov         [left_1d+2*%1+6], %5w
942 %endmacro
943
944 %macro SCALAR_HADAMARD_TOP 5 ; x, 4x tmp
945     movzx       %2d, byte [r1+%1-FDEC_STRIDE+0]
946     movzx       %3d, byte [r1+%1-FDEC_STRIDE+1]
947     movzx       %4d, byte [r1+%1-FDEC_STRIDE+2]
948     movzx       %5d, byte [r1+%1-FDEC_STRIDE+3]
949     SCALAR_SUMSUB %2d, %3d, %4d, %5d
950     SCALAR_SUMSUB %2d, %4d, %3d, %5d
951     mov         [top_1d+2*%1+0], %2w
952     mov         [top_1d+2*%1+2], %3w
953     mov         [top_1d+2*%1+4], %4w
954     mov         [top_1d+2*%1+6], %5w
955 %endmacro
956
957 %macro SUM_MM_X3 8 ; 3x sum, 4x tmp, op
958     pxor        %7, %7
959     pshufw      %4, %1, 01001110b
960     pshufw      %5, %2, 01001110b
961     pshufw      %6, %3, 01001110b
962     paddw       %1, %4
963     paddw       %2, %5
964     paddw       %3, %6
965     punpcklwd   %1, %7
966     punpcklwd   %2, %7
967     punpcklwd   %3, %7
968     pshufw      %4, %1, 01001110b
969     pshufw      %5, %2, 01001110b
970     pshufw      %6, %3, 01001110b
971     %8          %1, %4
972     %8          %2, %5
973     %8          %3, %6
974 %endmacro
975
976 %macro CLEAR_SUMS 0
977 %ifdef ARCH_X86_64
978     mov   qword [sums+0], 0
979     mov   qword [sums+8], 0
980     mov   qword [sums+16], 0
981 %else
982     pxor  m7, m7
983     movq  [sums+0], m7
984     movq  [sums+8], m7
985     movq  [sums+16], m7
986 %endif
987 %endmacro
988
989 ; in: m1..m3
990 ; out: m7
991 ; clobber: m4..m6
992 %macro SUM3x4 1
993 %ifidn %1, ssse3
994     pabsw       m4, m1
995     pabsw       m5, m2
996     pabsw       m7, m3
997     paddw       m4, m5
998 %else
999     movq        m4, m1
1000     movq        m5, m2
1001     ABS2        m4, m5, m6, m7
1002     movq        m7, m3
1003     paddw       m4, m5
1004     ABS1        m7, m6
1005 %endif
1006     paddw       m7, m4
1007 %endmacro
1008
1009 ; in: m0..m3 (4x4), m7 (3x4)
1010 ; out: m0 v, m4 h, m5 dc
1011 ; clobber: m6
1012 %macro SUM4x3 3 ; dc, left, top
1013     movq        m4, %2
1014     movd        m5, %1
1015     psllw       m4, 2
1016     psubw       m4, m0
1017     psubw       m5, m0
1018     punpcklwd   m0, m1
1019     punpcklwd   m2, m3
1020     punpckldq   m0, m2 ; transpose
1021     movq        m1, %3
1022     psllw       m1, 2
1023     psubw       m0, m1
1024     ABS2        m4, m5, m2, m3 ; 1x4 sum
1025     ABS1        m0, m1 ; 4x1 sum
1026 %endmacro
1027
1028 %macro INTRA_SATDS_MMX 1
1029 INIT_MMX
1030 ;-----------------------------------------------------------------------------
1031 ; void x264_intra_satd_x3_4x4_mmxext( uint8_t *fenc, uint8_t *fdec, int *res )
1032 ;-----------------------------------------------------------------------------
1033 cglobal x264_intra_satd_x3_4x4_%1, 2,6
1034 %ifdef ARCH_X86_64
1035     ; stack is 16 byte aligned because abi says so
1036     %define  top_1d  rsp-8  ; size 8
1037     %define  left_1d rsp-16 ; size 8
1038     %define  t0  r10
1039     %define  t0d r10d
1040 %else
1041     ; stack is 16 byte aligned at least in gcc, and we've pushed 3 regs + return address, so it's still aligned
1042     SUB         esp, 16
1043     %define  top_1d  esp+8
1044     %define  left_1d esp
1045     %define  t0  r2
1046     %define  t0d r2d
1047 %endif
1048
1049     call load_hadamard
1050     SCALAR_HADAMARD_LEFT 0, r0, r3, r4, r5
1051     mov         t0d, r0d
1052     SCALAR_HADAMARD_TOP  0, r0, r3, r4, r5
1053     lea         t0d, [t0d + r0d + 4]
1054     and         t0d, -8
1055     shl         t0d, 1 ; dc
1056
1057     SUM3x4 %1
1058     SUM4x3 t0d, [left_1d], [top_1d]
1059     paddw       m4, m7
1060     paddw       m5, m7
1061     movq        m1, m5
1062     psrlq       m1, 16  ; 4x3 sum
1063     paddw       m0, m1
1064
1065     SUM_MM_X3   m0, m4, m5, m1, m2, m3, m6, pavgw
1066 %ifndef ARCH_X86_64
1067     mov         r2, r2m
1068 %endif
1069     movd        [r2+0], m0 ; i4x4_v satd
1070     movd        [r2+4], m4 ; i4x4_h satd
1071     movd        [r2+8], m5 ; i4x4_dc satd
1072 %ifndef ARCH_X86_64
1073     ADD         esp, 16
1074 %endif
1075     RET
1076
1077 %ifdef ARCH_X86_64
1078     %define  t0  r10
1079     %define  t0d r10d
1080     %define  t2  r11
1081     %define  t2w r11w
1082     %define  t2d r11d
1083 %else
1084     %define  t0  r0
1085     %define  t0d r0d
1086     %define  t2  r2
1087     %define  t2w r2w
1088     %define  t2d r2d
1089 %endif
1090
1091 ;-----------------------------------------------------------------------------
1092 ; void x264_intra_satd_x3_16x16_mmxext( uint8_t *fenc, uint8_t *fdec, int *res )
1093 ;-----------------------------------------------------------------------------
1094 cglobal x264_intra_satd_x3_16x16_%1, 0,7
1095 %ifdef ARCH_X86_64
1096     %assign  stack_pad  88
1097 %else
1098     %assign  stack_pad  88 + ((stack_offset+88+4)&15)
1099 %endif
1100     ; not really needed on x86_64, just shuts up valgrind about storing data below the stack across a function call
1101     SUB         rsp, stack_pad
1102 %define sums    rsp+64 ; size 24
1103 %define top_1d  rsp+32 ; size 32
1104 %define left_1d rsp    ; size 32
1105     movifnidn   r1d, r1m
1106     CLEAR_SUMS
1107
1108     ; 1D hadamards
1109     xor         t2d, t2d
1110     mov         t0d, 12
1111 .loop_edge:
1112     SCALAR_HADAMARD_LEFT t0, r3, r4, r5, r6
1113     add         t2d, r3d
1114     SCALAR_HADAMARD_TOP  t0, r3, r4, r5, r6
1115     add         t2d, r3d
1116     sub         t0d, 4
1117     jge .loop_edge
1118     shr         t2d, 1
1119     add         t2d, 8
1120     and         t2d, -16 ; dc
1121
1122     ; 2D hadamards
1123     movifnidn   r0d, r0m
1124     xor         r3d, r3d
1125 .loop_y:
1126     xor         r4d, r4d
1127 .loop_x:
1128     call load_hadamard
1129
1130     SUM3x4 %1
1131     SUM4x3 t2d, [left_1d+8*r3], [top_1d+8*r4]
1132     pavgw       m4, m7
1133     pavgw       m5, m7
1134     paddw       m0, [sums+0]  ; i16x16_v satd
1135     paddw       m4, [sums+8]  ; i16x16_h satd
1136     paddw       m5, [sums+16] ; i16x16_dc satd
1137     movq        [sums+0], m0
1138     movq        [sums+8], m4
1139     movq        [sums+16], m5
1140
1141     add         r0, 4
1142     inc         r4d
1143     cmp         r4d, 4
1144     jl  .loop_x
1145     add         r0, 4*FENC_STRIDE-16
1146     inc         r3d
1147     cmp         r3d, 4
1148     jl  .loop_y
1149
1150 ; horizontal sum
1151     movifnidn   r2d, r2m
1152     movq        m2, [sums+16]
1153     movq        m1, [sums+8]
1154     movq        m0, [sums+0]
1155     movq        m7, m2
1156     SUM_MM_X3   m0, m1, m2, m3, m4, m5, m6, paddd
1157     psrld       m0, 1
1158     pslld       m7, 16
1159     psrld       m7, 16
1160     paddd       m0, m2
1161     psubd       m0, m7
1162     movd        [r2+8], m2 ; i16x16_dc satd
1163     movd        [r2+4], m1 ; i16x16_h satd
1164     movd        [r2+0], m0 ; i16x16_v satd
1165     ADD         rsp, stack_pad
1166     RET
1167
1168 ;-----------------------------------------------------------------------------
1169 ; void x264_intra_satd_x3_8x8c_mmxext( uint8_t *fenc, uint8_t *fdec, int *res )
1170 ;-----------------------------------------------------------------------------
1171 cglobal x264_intra_satd_x3_8x8c_%1, 0,6
1172     ; not really needed on x86_64, just shuts up valgrind about storing data below the stack across a function call
1173     SUB          rsp, 72
1174 %define  sums    rsp+48 ; size 24
1175 %define  dc_1d   rsp+32 ; size 16
1176 %define  top_1d  rsp+16 ; size 16
1177 %define  left_1d rsp    ; size 16
1178     movifnidn   r1d, r1m
1179     CLEAR_SUMS
1180
1181     ; 1D hadamards
1182     mov         t0d, 4
1183 .loop_edge:
1184     SCALAR_HADAMARD_LEFT t0, t2, r3, r4, r5
1185     SCALAR_HADAMARD_TOP  t0, t2, r3, r4, r5
1186     sub         t0d, 4
1187     jge .loop_edge
1188
1189     ; dc
1190     movzx       t2d, word [left_1d+0]
1191     movzx       r3d, word [top_1d+0]
1192     movzx       r4d, word [left_1d+8]
1193     movzx       r5d, word [top_1d+8]
1194     add         t2d, r3d
1195     lea         r3, [r4 + r5]
1196     lea         t2, [2*t2 + 8]
1197     lea         r3, [2*r3 + 8]
1198     lea         r4, [4*r4 + 8]
1199     lea         r5, [4*r5 + 8]
1200     and         t2d, -16 ; tl
1201     and         r3d, -16 ; br
1202     and         r4d, -16 ; bl
1203     and         r5d, -16 ; tr
1204     mov         [dc_1d+ 0], t2d ; tl
1205     mov         [dc_1d+ 4], r5d ; tr
1206     mov         [dc_1d+ 8], r4d ; bl
1207     mov         [dc_1d+12], r3d ; br
1208     lea         r5, [dc_1d]
1209
1210     ; 2D hadamards
1211     movifnidn   r0d, r0m
1212     movifnidn   r2d, r2m
1213     xor         r3d, r3d
1214 .loop_y:
1215     xor         r4d, r4d
1216 .loop_x:
1217     call load_hadamard
1218
1219     SUM3x4 %1
1220     SUM4x3 [r5+4*r4], [left_1d+8*r3], [top_1d+8*r4]
1221     pavgw       m4, m7
1222     pavgw       m5, m7
1223     paddw       m0, [sums+16] ; i4x4_v satd
1224     paddw       m4, [sums+8]  ; i4x4_h satd
1225     paddw       m5, [sums+0]  ; i4x4_dc satd
1226     movq        [sums+16], m0
1227     movq        [sums+8], m4
1228     movq        [sums+0], m5
1229
1230     add         r0, 4
1231     inc         r4d
1232     cmp         r4d, 2
1233     jl  .loop_x
1234     add         r0, 4*FENC_STRIDE-8
1235     add         r5, 8
1236     inc         r3d
1237     cmp         r3d, 2
1238     jl  .loop_y
1239
1240 ; horizontal sum
1241     movq        m0, [sums+0]
1242     movq        m1, [sums+8]
1243     movq        m2, [sums+16]
1244     movq        m7, m0
1245     psrlq       m7, 15
1246     paddw       m2, m7
1247     SUM_MM_X3   m0, m1, m2, m3, m4, m5, m6, paddd
1248     psrld       m2, 1
1249     movd        [r2+0], m0 ; i8x8c_dc satd
1250     movd        [r2+4], m1 ; i8x8c_h satd
1251     movd        [r2+8], m2 ; i8x8c_v satd
1252     ADD         rsp, 72
1253     RET
1254 %endmacro ; INTRA_SATDS_MMX
1255
1256
1257 %macro ABS_MOV_SSSE3 2
1258     pabsw   %1, %2
1259 %endmacro
1260
1261 %macro ABS_MOV_MMX 2
1262     pxor    %1, %1
1263     psubw   %1, %2
1264     pmaxsw  %1, %2
1265 %endmacro
1266
1267 %define ABS_MOV ABS_MOV_MMX
1268
1269 ; in:  r0=pix, r1=stride, r2=stride*3, r3=tmp, m6=mask_ac4, m7=0
1270 ; out: [tmp]=hadamard4, m0=satd
1271 cglobal x264_hadamard_ac_4x4_mmxext
1272     movh      m0, [r0]
1273     movh      m1, [r0+r1]
1274     movh      m2, [r0+r1*2]
1275     movh      m3, [r0+r2]
1276     punpcklbw m0, m7
1277     punpcklbw m1, m7
1278     punpcklbw m2, m7
1279     punpcklbw m3, m7
1280     HADAMARD4_1D m0, m1, m2, m3
1281     TRANSPOSE4x4W 0, 1, 2, 3, 4
1282     HADAMARD4_1D m0, m1, m2, m3
1283     mova [r3],    m0
1284     mova [r3+8],  m1
1285     mova [r3+16], m2
1286     mova [r3+24], m3
1287     ABS1      m0, m4
1288     ABS1      m1, m4
1289     pand      m0, m6
1290     ABS1      m2, m4
1291     ABS1      m3, m4
1292     paddw     m0, m1
1293     paddw     m2, m3
1294     paddw     m0, m2
1295     SAVE_MM_PERMUTATION x264_hadamard_ac_4x4_mmxext
1296     ret
1297
1298 cglobal x264_hadamard_ac_2x2_mmxext
1299     mova      m0, [r3+0x00]
1300     mova      m1, [r3+0x20]
1301     mova      m2, [r3+0x40]
1302     mova      m3, [r3+0x60]
1303     HADAMARD4_1D m0, m1, m2, m3
1304     ABS2      m0, m1, m4, m5
1305     ABS2      m2, m3, m4, m5
1306     SAVE_MM_PERMUTATION x264_hadamard_ac_2x2_mmxext
1307     ret
1308
1309 cglobal x264_hadamard_ac_8x8_mmxext
1310     mova      m6, [mask_ac4 GLOBAL]
1311     pxor      m7, m7
1312     call x264_hadamard_ac_4x4_mmxext
1313     add       r0, 4
1314     add       r3, 32
1315     mova      m5, m0
1316     call x264_hadamard_ac_4x4_mmxext
1317     lea       r0, [r0+4*r1]
1318     add       r3, 64
1319     paddw     m5, m0
1320     call x264_hadamard_ac_4x4_mmxext
1321     sub       r0, 4
1322     sub       r3, 32
1323     paddw     m5, m0
1324     call x264_hadamard_ac_4x4_mmxext
1325     paddw     m5, m0
1326     sub       r3, 64
1327     mova [rsp+gprsize+8], m5 ; save satd
1328     call x264_hadamard_ac_2x2_mmxext
1329     add       r3, 8
1330     pand      m6, m0
1331     mova      m7, m1
1332     paddw     m6, m2
1333     paddw     m7, m3
1334 %rep 2
1335     call x264_hadamard_ac_2x2_mmxext
1336     add       r3, 8
1337     paddw     m6, m0
1338     paddw     m7, m1
1339     paddw     m6, m2
1340     paddw     m7, m3
1341 %endrep
1342     call x264_hadamard_ac_2x2_mmxext
1343     sub       r3, 24
1344     paddw     m6, m0
1345     paddw     m7, m1
1346     paddw     m6, m2
1347     paddw     m7, m3
1348     paddw     m6, m7
1349     mova [rsp+gprsize], m6 ; save sa8d
1350     SWAP      m0, m6
1351     SAVE_MM_PERMUTATION x264_hadamard_ac_8x8_mmxext
1352     ret
1353
1354 %macro HADAMARD_AC_WXH_MMX 2
1355 cglobal x264_pixel_hadamard_ac_%1x%2_mmxext, 2,4
1356     %assign pad 16-gprsize-(stack_offset&15)
1357     %define ysub r1
1358     sub  rsp, 16+128+pad
1359     lea  r2, [r1*3]
1360     lea  r3, [rsp+16]
1361     call x264_hadamard_ac_8x8_mmxext
1362 %if %2==16
1363     %define ysub r2
1364     lea  r0, [r0+r1*4]
1365     sub  rsp, 16
1366     call x264_hadamard_ac_8x8_mmxext
1367 %endif
1368 %if %1==16
1369     neg  ysub
1370     sub  rsp, 16
1371     lea  r0, [r0+ysub*4+8]
1372     neg  ysub
1373     call x264_hadamard_ac_8x8_mmxext
1374 %if %2==16
1375     lea  r0, [r0+r1*4]
1376     sub  rsp, 16
1377     call x264_hadamard_ac_8x8_mmxext
1378 %endif
1379 %endif
1380     mova    m1, [rsp+0x08]
1381 %if %1*%2 >= 128
1382     paddusw m0, [rsp+0x10]
1383     paddusw m1, [rsp+0x18]
1384 %endif
1385 %if %1*%2 == 256
1386     mova    m2, [rsp+0x20]
1387     paddusw m1, [rsp+0x28]
1388     paddusw m2, [rsp+0x30]
1389     mova    m3, m0
1390     paddusw m1, [rsp+0x38]
1391     pxor    m3, m2
1392     pand    m3, [pw_1 GLOBAL]
1393     pavgw   m0, m2
1394     psubusw m0, m3
1395     HADDUW  m0, m2
1396 %else
1397     psrlw m0, 1
1398     HADDW m0, m2
1399 %endif
1400     psrlw m1, 1
1401     HADDW m1, m3
1402     movd edx, m0
1403     movd eax, m1
1404     shr  edx, 1
1405 %ifdef ARCH_X86_64
1406     shl  rdx, 32
1407     add  rax, rdx
1408 %endif
1409     add  rsp, 128+%1*%2/4+pad
1410     RET
1411 %endmacro ; HADAMARD_AC_WXH_MMX
1412
1413 HADAMARD_AC_WXH_MMX 16, 16
1414 HADAMARD_AC_WXH_MMX  8, 16
1415 HADAMARD_AC_WXH_MMX 16,  8
1416 HADAMARD_AC_WXH_MMX  8,  8
1417
1418 %macro HADAMARD_AC_SSE2 1
1419 INIT_XMM
1420 ; in:  r0=pix, r1=stride, r2=stride*3
1421 ; out: [esp+16]=sa8d, [esp+32]=satd, r0+=stride*4
1422 cglobal x264_hadamard_ac_8x8_%1
1423 %ifdef ARCH_X86_64
1424     %define spill0 m8
1425     %define spill1 m9
1426     %define spill2 m10
1427 %else
1428     %define spill0 [rsp+gprsize]
1429     %define spill1 [rsp+gprsize+16]
1430     %define spill2 [rsp+gprsize+32]
1431 %endif
1432     pxor      m7, m7
1433     movh      m0, [r0]
1434     movh      m1, [r0+r1]
1435     movh      m2, [r0+r1*2]
1436     movh      m3, [r0+r2]
1437     lea       r0, [r0+r1*4]
1438     punpcklbw m0, m7
1439     punpcklbw m1, m7
1440     punpcklbw m2, m7
1441     punpcklbw m3, m7
1442     HADAMARD4_1D m0, m1, m2, m3
1443     mova  spill0, m3
1444     SWAP      m3, m7
1445     movh      m4, [r0]
1446     movh      m5, [r0+r1]
1447     movh      m6, [r0+r1*2]
1448     movh      m7, [r0+r2]
1449     punpcklbw m4, m3
1450     punpcklbw m5, m3
1451     punpcklbw m6, m3
1452     punpcklbw m7, m3
1453     HADAMARD4_1D m4, m5, m6, m7
1454     mova      m3, spill0
1455 %ifdef ARCH_X86_64
1456     TRANSPOSE8x8W 0,1,2,3,4,5,6,7,8
1457 %else
1458     TRANSPOSE8x8W 0,1,2,3,4,5,6,7,spill0,spill1
1459 %endif
1460     HADAMARD4_1D m0, m1, m2, m3
1461     HADAMARD4_1D m4, m5, m6, m7
1462     mova  spill0, m1
1463     mova  spill1, m2
1464     mova  spill2, m3
1465     ABS_MOV   m1, m0
1466     ABS_MOV   m2, m4
1467     ABS_MOV   m3, m5
1468     paddw     m1, m2
1469     SUMSUB_BA m0, m4
1470     pand      m1, [mask_ac4 GLOBAL]
1471     ABS_MOV   m2, spill0
1472     paddw     m1, m3
1473     ABS_MOV   m3, spill1
1474     paddw     m1, m2
1475     ABS_MOV   m2, spill2
1476     paddw     m1, m3
1477     ABS_MOV   m3, m6
1478     paddw     m1, m2
1479     ABS_MOV   m2, m7
1480     paddw     m1, m3
1481     mova      m3, m7
1482     paddw     m1, m2
1483     mova      m2, m6
1484     psubw     m7, spill2
1485     paddw     m3, spill2
1486     mova  [rsp+gprsize+32], m1 ; save satd
1487     mova      m1, m5
1488     psubw     m6, spill1
1489     paddw     m2, spill1
1490     psubw     m5, spill0
1491     paddw     m1, spill0
1492     mova  spill1, m7
1493     SBUTTERFLY qdq, 0, 4, 7
1494     SBUTTERFLY qdq, 1, 5, 7
1495     SBUTTERFLY qdq, 2, 6, 7
1496     SUMSUB_BADC m0, m4, m1, m5
1497     SUMSUB_BA m2, m6
1498     ABS1      m0, m7
1499     ABS1      m1, m7
1500     pand      m0, [mask_ac8 GLOBAL]
1501     ABS1      m2, m7
1502     ABS1      m4, m7
1503     ABS1      m5, m7
1504     ABS1      m6, m7
1505     mova      m7, spill1
1506     paddw     m0, m4
1507     SBUTTERFLY qdq, 3, 7, 4
1508     SUMSUB_BA m3, m7
1509     paddw     m1, m5
1510     ABS1      m3, m4
1511     ABS1      m7, m4
1512     paddw     m2, m6
1513     paddw     m3, m7
1514     paddw     m0, m1
1515     paddw     m2, m3
1516     paddw     m0, m2
1517     mova  [rsp+gprsize+16], m0 ; save sa8d
1518     SAVE_MM_PERMUTATION x264_hadamard_ac_8x8_%1
1519     ret
1520
1521 HADAMARD_AC_WXH_SSE2 16, 16, %1
1522 HADAMARD_AC_WXH_SSE2  8, 16, %1
1523 HADAMARD_AC_WXH_SSE2 16,  8, %1
1524 HADAMARD_AC_WXH_SSE2  8,  8, %1
1525 %endmacro ; HADAMARD_AC_SSE2
1526
1527 ; struct { int satd, int sa8d; } x264_pixel_hadamard_ac_16x16( uint8_t *pix, int stride )
1528 %macro HADAMARD_AC_WXH_SSE2 3
1529 cglobal x264_pixel_hadamard_ac_%1x%2_%3, 2,3
1530     %assign pad 16-gprsize-(stack_offset&15)
1531     %define ysub r1
1532     sub  rsp, 48+pad
1533     lea  r2, [r1*3]
1534     call x264_hadamard_ac_8x8_%3
1535 %if %2==16
1536     %define ysub r2
1537     lea  r0, [r0+r1*4]
1538     sub  rsp, 32
1539     call x264_hadamard_ac_8x8_%3
1540 %endif
1541 %if %1==16
1542     neg  ysub
1543     sub  rsp, 32
1544     lea  r0, [r0+ysub*4+8]
1545     neg  ysub
1546     call x264_hadamard_ac_8x8_%3
1547 %if %2==16
1548     lea  r0, [r0+r1*4]
1549     sub  rsp, 32
1550     call x264_hadamard_ac_8x8_%3
1551 %endif
1552 %endif
1553     mova    m1, [rsp+0x20]
1554 %if %1*%2 >= 128
1555     paddusw m0, [rsp+0x30]
1556     paddusw m1, [rsp+0x40]
1557 %endif
1558 %if %1*%2 == 256
1559     paddusw m0, [rsp+0x50]
1560     paddusw m1, [rsp+0x60]
1561     paddusw m0, [rsp+0x70]
1562     paddusw m1, [rsp+0x80]
1563     psrlw m0, 1
1564 %endif
1565     HADDW m0, m2
1566     HADDW m1, m3
1567     movd edx, m0
1568     movd eax, m1
1569     shr  edx, 2 - (%1*%2 >> 8)
1570     shr  eax, 1
1571 %ifdef ARCH_X86_64
1572     shl  rdx, 32
1573     add  rax, rdx
1574 %endif
1575     add  rsp, 16+%1*%2/2+pad
1576     RET
1577 %endmacro ; HADAMARD_AC_WXH_SSE2
1578
1579 ; instantiate satds
1580
1581 %ifndef ARCH_X86_64
1582 cextern x264_pixel_sa8d_8x8_internal_mmxext
1583 SA8D_16x16_32 mmxext
1584 %endif
1585
1586 %define ABS1 ABS1_MMX
1587 %define ABS2 ABS2_MMX
1588 SATDS_SSE2 sse2
1589 SA8D_16x16_32 sse2
1590 INTRA_SA8D_SSE2 sse2
1591 INTRA_SATDS_MMX mmxext
1592 HADAMARD_AC_SSE2 sse2
1593 %define ABS1 ABS1_SSSE3
1594 %define ABS2 ABS2_SSSE3
1595 %define ABS_MOV ABS_MOV_SSSE3
1596 SATD_W4 ssse3 ; mmx, but uses pabsw from ssse3.
1597 SATDS_SSE2 ssse3
1598 SA8D_16x16_32 ssse3
1599 INTRA_SA8D_SSE2 ssse3
1600 INTRA_SATDS_MMX ssse3
1601 HADAMARD_AC_SSE2 ssse3
1602 SATDS_SSE2 ssse3_phadd
1603
1604
1605
1606 ;=============================================================================
1607 ; SSIM
1608 ;=============================================================================
1609
1610 ;-----------------------------------------------------------------------------
1611 ; void x264_pixel_ssim_4x4x2_core_sse2( const uint8_t *pix1, int stride1,
1612 ;                                       const uint8_t *pix2, int stride2, int sums[2][4] )
1613 ;-----------------------------------------------------------------------------
1614 cglobal x264_pixel_ssim_4x4x2_core_sse2, 4,4
1615     pxor      m0, m0
1616     pxor      m1, m1
1617     pxor      m2, m2
1618     pxor      m3, m3
1619     pxor      m4, m4
1620 %rep 4
1621     movq      m5, [r0]
1622     movq      m6, [r2]
1623     punpcklbw m5, m0
1624     punpcklbw m6, m0
1625     paddw     m1, m5
1626     paddw     m2, m6
1627     movdqa    m7, m5
1628     pmaddwd   m5, m5
1629     pmaddwd   m7, m6
1630     pmaddwd   m6, m6
1631     paddd     m3, m5
1632     paddd     m4, m7
1633     paddd     m3, m6
1634     add       r0, r1
1635     add       r2, r3
1636 %endrep
1637     ; PHADDW m1, m2
1638     ; PHADDD m3, m4
1639     movdqa    m7, [pw_1 GLOBAL]
1640     pshufd    m5, m3, 0xb1
1641     pmaddwd   m1, m7
1642     pmaddwd   m2, m7
1643     pshufd    m6, m4, 0xb1
1644     packssdw  m1, m2
1645     paddd     m3, m5
1646     pshufd    m1, m1, 0xd8
1647     paddd     m4, m6
1648     pmaddwd   m1, m7
1649     movdqa    m5, m3
1650     punpckldq m3, m4
1651     punpckhdq m5, m4
1652
1653 %ifdef ARCH_X86_64
1654     %define t0 r4
1655 %else
1656     %define t0 eax
1657     mov t0, r4m
1658 %endif
1659
1660     movq      [t0+ 0], m1
1661     movq      [t0+ 8], m3
1662     psrldq    m1, 8
1663     movq      [t0+16], m1
1664     movq      [t0+24], m5
1665     RET
1666
1667 ;-----------------------------------------------------------------------------
1668 ; float x264_pixel_ssim_end_sse2( int sum0[5][4], int sum1[5][4], int width )
1669 ;-----------------------------------------------------------------------------
1670 cglobal x264_pixel_ssim_end4_sse2, 3,3
1671     movdqa    m0, [r0+ 0]
1672     movdqa    m1, [r0+16]
1673     movdqa    m2, [r0+32]
1674     movdqa    m3, [r0+48]
1675     movdqa    m4, [r0+64]
1676     paddd     m0, [r1+ 0]
1677     paddd     m1, [r1+16]
1678     paddd     m2, [r1+32]
1679     paddd     m3, [r1+48]
1680     paddd     m4, [r1+64]
1681     paddd     m0, m1
1682     paddd     m1, m2
1683     paddd     m2, m3
1684     paddd     m3, m4
1685     movdqa    m5, [ssim_c1 GLOBAL]
1686     movdqa    m6, [ssim_c2 GLOBAL]
1687     TRANSPOSE4x4D  0, 1, 2, 3, 4
1688
1689 ;   s1=m0, s2=m1, ss=m2, s12=m3
1690     movdqa    m4, m1
1691     pslld     m1, 16
1692     pmaddwd   m4, m0  ; s1*s2
1693     por       m0, m1
1694     pmaddwd   m0, m0  ; s1*s1 + s2*s2
1695     pslld     m4, 1
1696     pslld     m3, 7
1697     pslld     m2, 6
1698     psubd     m3, m4  ; covar*2
1699     psubd     m2, m0  ; vars
1700     paddd     m0, m5
1701     paddd     m4, m5
1702     paddd     m3, m6
1703     paddd     m2, m6
1704     cvtdq2ps  m0, m0  ; (float)(s1*s1 + s2*s2 + ssim_c1)
1705     cvtdq2ps  m4, m4  ; (float)(s1*s2*2 + ssim_c1)
1706     cvtdq2ps  m3, m3  ; (float)(covar*2 + ssim_c2)
1707     cvtdq2ps  m2, m2  ; (float)(vars + ssim_c2)
1708     mulps     m4, m3
1709     mulps     m0, m2
1710     divps     m4, m0  ; ssim
1711
1712     cmp       r2d, 4
1713     je .skip ; faster only if this is the common case; remove branch if we use ssim on a macroblock level
1714     neg       r2
1715 %ifdef PIC
1716     lea       r3, [mask_ff + 16 GLOBAL]
1717     movdqu    m1, [r3 + r2*4]
1718 %else
1719     movdqu    m1, [mask_ff + r2*4 + 16 GLOBAL]
1720 %endif
1721     pand      m4, m1
1722 .skip:
1723     movhlps   m0, m4
1724     addps     m0, m4
1725     pshuflw   m4, m0, 0xE
1726     addss     m0, m4
1727 %ifndef ARCH_X86_64
1728     movd     r0m, m0
1729     fld     dword r0m
1730 %endif
1731     RET
1732
1733
1734
1735 ;=============================================================================
1736 ; Successive Elimination ADS
1737 ;=============================================================================
1738
1739 %macro ADS_START 1 ; unroll_size
1740 %ifdef ARCH_X86_64
1741     %define t0  r6
1742     mov     r10, rsp
1743 %else
1744     %define t0  r4
1745     mov     rbp, rsp
1746 %endif
1747     mov     r0d, r5m
1748     sub     rsp, r0
1749     sub     rsp, %1*4-1
1750     and     rsp, ~15
1751     mov     t0,  rsp
1752     shl     r2d,  1
1753 %endmacro
1754
1755 %macro ADS_END 1
1756     add     r1, 8*%1
1757     add     r3, 8*%1
1758     add     t0, 4*%1
1759     sub     r0d, 4*%1
1760     jg .loop
1761     jmp ads_mvs
1762 %endmacro
1763
1764 %define ABS1 ABS1_MMX
1765
1766 ;-----------------------------------------------------------------------------
1767 ; int x264_pixel_ads4_mmxext( int enc_dc[4], uint16_t *sums, int delta,
1768 ;                             uint16_t *cost_mvx, int16_t *mvs, int width, int thresh )
1769 ;-----------------------------------------------------------------------------
1770 cglobal x264_pixel_ads4_mmxext, 4,7
1771     movq    mm6, [r0]
1772     movq    mm4, [r0+8]
1773     pshufw  mm7, mm6, 0
1774     pshufw  mm6, mm6, 0xAA
1775     pshufw  mm5, mm4, 0
1776     pshufw  mm4, mm4, 0xAA
1777     ADS_START 1
1778 .loop:
1779     movq    mm0, [r1]
1780     movq    mm1, [r1+16]
1781     psubw   mm0, mm7
1782     psubw   mm1, mm6
1783     ABS1    mm0, mm2
1784     ABS1    mm1, mm3
1785     movq    mm2, [r1+r2]
1786     movq    mm3, [r1+r2+16]
1787     psubw   mm2, mm5
1788     psubw   mm3, mm4
1789     paddw   mm0, mm1
1790     ABS1    mm2, mm1
1791     ABS1    mm3, mm1
1792     paddw   mm0, mm2
1793     paddw   mm0, mm3
1794 %ifdef ARCH_X86_64
1795     pshufw  mm1, [r10+8], 0
1796 %else
1797     pshufw  mm1, [ebp+stack_offset+28], 0
1798 %endif
1799     paddusw mm0, [r3]
1800     psubusw mm1, mm0
1801     packsswb mm1, mm1
1802     movd    [t0], mm1
1803     ADS_END 1
1804
1805 cglobal x264_pixel_ads2_mmxext, 4,7
1806     movq    mm6, [r0]
1807     pshufw  mm5, r6m, 0
1808     pshufw  mm7, mm6, 0
1809     pshufw  mm6, mm6, 0xAA
1810     ADS_START 1
1811 .loop:
1812     movq    mm0, [r1]
1813     movq    mm1, [r1+r2]
1814     psubw   mm0, mm7
1815     psubw   mm1, mm6
1816     ABS1    mm0, mm2
1817     ABS1    mm1, mm3
1818     paddw   mm0, mm1
1819     paddusw mm0, [r3]
1820     movq    mm4, mm5
1821     psubusw mm4, mm0
1822     packsswb mm4, mm4
1823     movd    [t0], mm4
1824     ADS_END 1
1825
1826 cglobal x264_pixel_ads1_mmxext, 4,7
1827     pshufw  mm7, [r0], 0
1828     pshufw  mm6, r6m, 0
1829     ADS_START 2
1830 .loop:
1831     movq    mm0, [r1]
1832     movq    mm1, [r1+8]
1833     psubw   mm0, mm7
1834     psubw   mm1, mm7
1835     ABS1    mm0, mm2
1836     ABS1    mm1, mm3
1837     paddusw mm0, [r3]
1838     paddusw mm1, [r3+8]
1839     movq    mm4, mm6
1840     movq    mm5, mm6
1841     psubusw mm4, mm0
1842     psubusw mm5, mm1
1843     packsswb mm4, mm5
1844     movq    [t0], mm4
1845     ADS_END 2
1846
1847 %macro ADS_SSE2 1
1848 cglobal x264_pixel_ads4_%1, 4,7
1849     movdqa  xmm4, [r0]
1850     pshuflw xmm7, xmm4, 0
1851     pshuflw xmm6, xmm4, 0xAA
1852     pshufhw xmm5, xmm4, 0
1853     pshufhw xmm4, xmm4, 0xAA
1854     punpcklqdq xmm7, xmm7
1855     punpcklqdq xmm6, xmm6
1856     punpckhqdq xmm5, xmm5
1857     punpckhqdq xmm4, xmm4
1858 %ifdef ARCH_X86_64
1859     pshuflw xmm8, r6m, 0
1860     punpcklqdq xmm8, xmm8
1861     ADS_START 2
1862     movdqu  xmm10, [r1]
1863     movdqu  xmm11, [r1+r2]
1864 .loop:
1865     movdqa  xmm0, xmm10
1866     movdqu  xmm1, [r1+16]
1867     movdqa  xmm10, xmm1
1868     psubw   xmm0, xmm7
1869     psubw   xmm1, xmm6
1870     ABS1    xmm0, xmm2
1871     ABS1    xmm1, xmm3
1872     movdqa  xmm2, xmm11
1873     movdqu  xmm3, [r1+r2+16]
1874     movdqa  xmm11, xmm3
1875     psubw   xmm2, xmm5
1876     psubw   xmm3, xmm4
1877     paddw   xmm0, xmm1
1878     movdqu  xmm9, [r3]
1879     ABS1    xmm2, xmm1
1880     ABS1    xmm3, xmm1
1881     paddw   xmm0, xmm2
1882     paddw   xmm0, xmm3
1883     paddusw xmm0, xmm9
1884     movdqa  xmm1, xmm8
1885     psubusw xmm1, xmm0
1886     packsswb xmm1, xmm1
1887     movq    [t0], xmm1
1888 %else
1889     ADS_START 2
1890 .loop:
1891     movdqu  xmm0, [r1]
1892     movdqu  xmm1, [r1+16]
1893     psubw   xmm0, xmm7
1894     psubw   xmm1, xmm6
1895     ABS1    xmm0, xmm2
1896     ABS1    xmm1, xmm3
1897     movdqu  xmm2, [r1+r2]
1898     movdqu  xmm3, [r1+r2+16]
1899     psubw   xmm2, xmm5
1900     psubw   xmm3, xmm4
1901     paddw   xmm0, xmm1
1902     ABS1    xmm2, xmm1
1903     ABS1    xmm3, xmm1
1904     paddw   xmm0, xmm2
1905     paddw   xmm0, xmm3
1906     movd    xmm1, [ebp+stack_offset+28]
1907     movdqu  xmm2, [r3]
1908     pshuflw xmm1, xmm1, 0
1909     punpcklqdq xmm1, xmm1
1910     paddusw xmm0, xmm2
1911     psubusw xmm1, xmm0
1912     packsswb xmm1, xmm1
1913     movq    [t0], xmm1
1914 %endif ; ARCH
1915     ADS_END 2
1916
1917 cglobal x264_pixel_ads2_%1, 4,7
1918     movq    xmm6, [r0]
1919     movd    xmm5, r6m
1920     pshuflw xmm7, xmm6, 0
1921     pshuflw xmm6, xmm6, 0xAA
1922     pshuflw xmm5, xmm5, 0
1923     punpcklqdq xmm7, xmm7
1924     punpcklqdq xmm6, xmm6
1925     punpcklqdq xmm5, xmm5
1926     ADS_START 2
1927 .loop:
1928     movdqu  xmm0, [r1]
1929     movdqu  xmm1, [r1+r2]
1930     psubw   xmm0, xmm7
1931     psubw   xmm1, xmm6
1932     movdqu  xmm4, [r3]
1933     ABS1    xmm0, xmm2
1934     ABS1    xmm1, xmm3
1935     paddw   xmm0, xmm1
1936     paddusw xmm0, xmm4
1937     movdqa  xmm1, xmm5
1938     psubusw xmm1, xmm0
1939     packsswb xmm1, xmm1
1940     movq    [t0], xmm1
1941     ADS_END 2
1942
1943 cglobal x264_pixel_ads1_%1, 4,7
1944     movd    xmm7, [r0]
1945     movd    xmm6, r6m
1946     pshuflw xmm7, xmm7, 0
1947     pshuflw xmm6, xmm6, 0
1948     punpcklqdq xmm7, xmm7
1949     punpcklqdq xmm6, xmm6
1950     ADS_START 4
1951 .loop:
1952     movdqu  xmm0, [r1]
1953     movdqu  xmm1, [r1+16]
1954     psubw   xmm0, xmm7
1955     psubw   xmm1, xmm7
1956     movdqu  xmm2, [r3]
1957     movdqu  xmm3, [r3+16]
1958     ABS1    xmm0, xmm4
1959     ABS1    xmm1, xmm5
1960     paddusw xmm0, xmm2
1961     paddusw xmm1, xmm3
1962     movdqa  xmm4, xmm6
1963     movdqa  xmm5, xmm6
1964     psubusw xmm4, xmm0
1965     psubusw xmm5, xmm1
1966     packsswb xmm4, xmm5
1967     movdqa  [t0], xmm4
1968     ADS_END 4
1969 %endmacro
1970
1971 ADS_SSE2 sse2
1972 %define ABS1 ABS1_SSSE3
1973 ADS_SSE2 ssse3
1974
1975 ; int x264_pixel_ads_mvs( int16_t *mvs, uint8_t *masks, int width )
1976 ; {
1977 ;     int nmv=0, i, j;
1978 ;     *(uint32_t*)(masks+width) = 0;
1979 ;     for( i=0; i<width; i+=8 )
1980 ;     {
1981 ;         uint64_t mask = *(uint64_t*)(masks+i);
1982 ;         if( !mask ) continue;
1983 ;         for( j=0; j<8; j++ )
1984 ;             if( mask & (255<<j*8) )
1985 ;                 mvs[nmv++] = i+j;
1986 ;     }
1987 ;     return nmv;
1988 ; }
1989 cglobal x264_pixel_ads_mvs
1990 ads_mvs:
1991     xor     eax, eax
1992     xor     esi, esi
1993 %ifdef ARCH_X86_64
1994     ; mvs = r4
1995     ; masks = rsp
1996     ; width = r5
1997     ; clear last block in case width isn't divisible by 8. (assume divisible by 4, so clearing 4 bytes is enough.)
1998     mov     dword [rsp+r5], 0
1999     jmp .loopi
2000 .loopi0:
2001     add     esi, 8
2002     cmp     esi, r5d
2003     jge .end
2004 .loopi:
2005     mov     rdi, [rsp+rsi]
2006     test    rdi, rdi
2007     jz .loopi0
2008     xor     ecx, ecx
2009 %macro TEST 1
2010     mov     [r4+rax*2], si
2011     test    edi, 0xff<<(%1*8)
2012     setne   cl
2013     add     eax, ecx
2014     inc     esi
2015 %endmacro
2016     TEST 0
2017     TEST 1
2018     TEST 2
2019     TEST 3
2020     shr     rdi, 32
2021     TEST 0
2022     TEST 1
2023     TEST 2
2024     TEST 3
2025     cmp     esi, r5d
2026     jl .loopi
2027 .end:
2028     mov     rsp, r10
2029     ret
2030
2031 %else
2032     ; no PROLOGUE, inherit from x264_pixel_ads1
2033     mov     ebx, [ebp+stack_offset+20] ; mvs
2034     mov     edi, [ebp+stack_offset+24] ; width
2035     mov     dword [esp+edi], 0
2036     push    ebp
2037     jmp .loopi
2038 .loopi0:
2039     add     esi, 8
2040     cmp     esi, edi
2041     jge .end
2042 .loopi:
2043     mov     ebp, [esp+esi+4]
2044     mov     edx, [esp+esi+8]
2045     mov     ecx, ebp
2046     or      ecx, edx
2047     jz .loopi0
2048     xor     ecx, ecx
2049 %macro TEST 2
2050     mov     [ebx+eax*2], si
2051     test    %2, 0xff<<(%1*8)
2052     setne   cl
2053     add     eax, ecx
2054     inc     esi
2055 %endmacro
2056     TEST 0, ebp
2057     TEST 1, ebp
2058     TEST 2, ebp
2059     TEST 3, ebp
2060     TEST 0, edx
2061     TEST 1, edx
2062     TEST 2, edx
2063     TEST 3, edx
2064     cmp     esi, edi
2065     jl .loopi
2066 .end:
2067     pop     esp
2068     RET
2069 %endif ; ARCH
2070