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