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