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