]> git.sesse.net Git - x264/blob - common/amd64/pixel-sse2.asm
SSIM computation. (default on, disable by --no-ssim)
[x264] / common / amd64 / pixel-sse2.asm
1 ;*****************************************************************************
2 ;* pixel-sse2.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2005 x264 project
5 ;*
6 ;* Authors: Alex Izvorski <aizvorksi@gmail.com>
7 ;*
8 ;* This program is free software; you can redistribute it and/or modify
9 ;* it under the terms of the GNU General Public License as published by
10 ;* the Free Software Foundation; either version 2 of the License, or
11 ;* (at your option) any later version.
12 ;*
13 ;* This program is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;* GNU General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU General Public License
19 ;* along with this program; if not, write to the Free Software
20 ;* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21 ;*****************************************************************************
22
23 BITS 64
24
25 ;=============================================================================
26 ; Macros and other preprocessor constants
27 ;=============================================================================
28
29 %include "amd64inc.asm"
30
31 SECTION .rodata align=16
32
33 pb_1:    times 16 db 1
34 pw_1:    times 8 dw 1
35 ssim_c1: times 4 dd 416    ; .01*.01*255*255*64
36 ssim_c2: times 4 dd 235963 ; .03*.03*255*255*64*63
37 mask_ff: times 16 db 0xff
38          times 16 db 0
39
40 SECTION .text
41
42
43 cglobal x264_pixel_sad_16x16_sse2
44 cglobal x264_pixel_sad_16x8_sse2
45 cglobal x264_pixel_ssd_16x16_sse2
46 cglobal x264_pixel_ssd_16x8_sse2
47 cglobal x264_pixel_satd_8x4_sse2
48 cglobal x264_pixel_satd_8x8_sse2
49 cglobal x264_pixel_satd_16x8_sse2
50 cglobal x264_pixel_satd_8x16_sse2
51 cglobal x264_pixel_satd_16x16_sse2
52 cglobal x264_pixel_sa8d_8x8_sse2
53 cglobal x264_pixel_sa8d_16x16_sse2
54 cglobal x264_intra_sa8d_x3_8x8_core_sse2
55 cglobal x264_pixel_ssim_4x4x2_core_sse2
56 cglobal x264_pixel_ssim_end4_sse2
57
58 %macro HADDD 2 ; sum junk
59     movhlps %2, %1
60     paddd   %1, %2
61     pshuflw %2, %1, 0xE 
62     paddd   %1, %2
63 %endmacro
64
65 %macro HADDW 2
66     pmaddwd %1, [pw_1 GLOBAL]
67     HADDD   %1, %2
68 %endmacro
69
70 %macro SAD_INC_4x16P_SSE2 0
71     movdqu  xmm1,   [rdx]
72     movdqu  xmm2,   [rdx+rcx]
73     lea     rdx,    [rdx+2*rcx]
74     movdqu  xmm3,   [rdx]
75     movdqu  xmm4,   [rdx+rcx]
76     psadbw  xmm1,   [rdi]
77     psadbw  xmm2,   [rdi+rsi]
78     lea     rdi,    [rdi+2*rsi]
79     psadbw  xmm3,   [rdi]
80     psadbw  xmm4,   [rdi+rsi]
81     lea     rdi,    [rdi+2*rsi]
82     lea     rdx,    [rdx+2*rcx]
83     paddw   xmm1,   xmm2
84     paddw   xmm3,   xmm4
85     paddw   xmm0,   xmm1
86     paddw   xmm0,   xmm3
87 %endmacro
88
89 %macro SAD_START_SSE2 0
90 ;   mov     rdi, rdi            ; pix1
91     movsxd  rsi, esi            ; stride1
92 ;   mov     rdx, rdx            ; pix2
93     movsxd  rcx, ecx            ; stride2
94 %endmacro
95
96 %macro SAD_END_SSE2 0
97     movdqa  xmm1, xmm0
98     psrldq  xmm0,  8
99     paddw   xmm0, xmm1
100     movd    eax,  xmm0
101     ret
102 %endmacro
103
104 ALIGN 16
105 ;-----------------------------------------------------------------------------
106 ;   int x264_pixel_sad_16x16_sse2 (uint8_t *, int, uint8_t *, int )
107 ;-----------------------------------------------------------------------------
108 x264_pixel_sad_16x16_sse2:
109     SAD_START_SSE2
110     movdqu xmm0, [rdx]
111     movdqu xmm1, [rdx+rcx]
112     lea    rdx,  [rdx+2*rcx]
113     movdqu xmm2, [rdx]
114     movdqu xmm3, [rdx+rcx]
115     lea    rdx,  [rdx+2*rcx]
116     psadbw xmm0, [rdi]
117     psadbw xmm1, [rdi+rsi]
118     lea    rdi,  [rdi+2*rsi]
119     movdqu xmm4, [rdx]
120     paddw  xmm0, xmm1
121     psadbw xmm2, [rdi]
122     psadbw xmm3, [rdi+rsi]
123     lea    rdi,  [rdi+2*rsi]
124     movdqu xmm5, [rdx+rcx]
125     lea    rdx,  [rdx+2*rcx]
126     paddw  xmm2, xmm3
127     movdqu xmm6, [rdx]
128     movdqu xmm7, [rdx+rcx]
129     lea    rdx,  [rdx+2*rcx]
130     paddw  xmm0, xmm2
131     psadbw xmm4, [rdi]
132     psadbw xmm5, [rdi+rsi]
133     lea    rdi,  [rdi+2*rsi]
134     movdqu xmm1, [rdx]
135     paddw  xmm4, xmm5
136     psadbw xmm6, [rdi]
137     psadbw xmm7, [rdi+rsi]
138     lea    rdi,  [rdi+2*rsi]
139     movdqu xmm2, [rdx+rcx]
140     lea    rdx,  [rdx+2*rcx]
141     paddw  xmm6, xmm7
142     movdqu xmm3, [rdx]
143     paddw  xmm0, xmm4
144     movdqu xmm4, [rdx+rcx]
145     lea    rdx,  [rdx+2*rcx]
146     paddw  xmm0, xmm6
147     psadbw xmm1, [rdi]
148     psadbw xmm2, [rdi+rsi]
149     lea    rdi,  [rdi+2*rsi]
150     movdqu xmm5, [rdx]
151     paddw  xmm1, xmm2
152     psadbw xmm3, [rdi]
153     psadbw xmm4, [rdi+rsi]
154     lea    rdi,  [rdi+2*rsi]
155     movdqu xmm6, [rdx+rcx]
156     lea    rdx,  [rdx+2*rcx]
157     paddw  xmm3, xmm4
158     movdqu xmm7, [rdx]
159     paddw  xmm0, xmm1
160     movdqu xmm1, [rdx+rcx]
161     paddw  xmm0, xmm3
162     psadbw xmm5, [rdi]
163     psadbw xmm6, [rdi+rsi]
164     lea    rdi,  [rdi+2*rsi]
165     paddw  xmm5, xmm6
166     psadbw xmm7, [rdi]
167     psadbw xmm1, [rdi+rsi]
168     paddw  xmm7, xmm1
169     paddw  xmm0, xmm5
170     paddw  xmm0, xmm7
171     SAD_END_SSE2
172
173 ALIGN 16
174 ;-----------------------------------------------------------------------------
175 ;   int x264_pixel_sad_16x8_sse2 (uint8_t *, int, uint8_t *, int )
176 ;-----------------------------------------------------------------------------
177 x264_pixel_sad_16x8_sse2:
178     SAD_START_SSE2
179     pxor    xmm0,   xmm0
180     SAD_INC_4x16P_SSE2
181     SAD_INC_4x16P_SSE2
182     SAD_END_SSE2
183
184 %macro SSD_INC_2x16P_SSE2 0
185     movdqu  xmm1,   [rdi]
186     movdqu  xmm2,   [rdx]
187     movdqu  xmm3,   [rdi+rsi]
188     movdqu  xmm4,   [rdx+rcx]
189
190     movdqa  xmm5,   xmm1
191     movdqa  xmm6,   xmm3
192     psubusb xmm1,   xmm2
193     psubusb xmm3,   xmm4
194     psubusb xmm2,   xmm5
195     psubusb xmm4,   xmm6
196     por     xmm1,   xmm2
197     por     xmm3,   xmm4
198
199     movdqa  xmm2,   xmm1
200     movdqa  xmm4,   xmm3
201     punpcklbw xmm1, xmm7
202     punpckhbw xmm2, xmm7
203     punpcklbw xmm3, xmm7
204     punpckhbw xmm4, xmm7
205     pmaddwd xmm1,   xmm1
206     pmaddwd xmm2,   xmm2
207     pmaddwd xmm3,   xmm3
208     pmaddwd xmm4,   xmm4
209
210     lea     rdi,    [rdi+2*rsi]
211     lea     rdx,    [rdx+2*rcx]
212
213     paddd   xmm1,   xmm2
214     paddd   xmm3,   xmm4
215     paddd   xmm0,   xmm1
216     paddd   xmm0,   xmm3
217 %endmacro
218
219 %macro SSD_INC_8x16P_SSE2 0
220     SSD_INC_2x16P_SSE2
221     SSD_INC_2x16P_SSE2
222     SSD_INC_2x16P_SSE2
223     SSD_INC_2x16P_SSE2
224 %endmacro
225
226 %macro SSD_START_SSE2 0
227 ;   mov     rdi, rdi            ; pix1
228     movsxd  rsi, esi            ; stride1
229 ;   mov     rdx, rdx            ; pix2
230     movsxd  rcx, ecx            ; stride2
231
232     pxor    xmm7,   xmm7        ; zero
233     pxor    xmm0,   xmm0        ; mm0 holds the sum
234 %endmacro
235
236 %macro SSD_END_SSE2 0
237     HADDD   xmm0, xmm1
238     movd    eax,  xmm0
239     ret
240 %endmacro
241
242 ALIGN 16
243 ;-----------------------------------------------------------------------------
244 ;   int x264_pixel_ssd_16x16_sse2 (uint8_t *, int, uint8_t *, int )
245 ;-----------------------------------------------------------------------------
246 x264_pixel_ssd_16x16_sse2:
247     SSD_START_SSE2
248     SSD_INC_8x16P_SSE2
249     SSD_INC_8x16P_SSE2
250     SSD_END_SSE2
251
252 ALIGN 16
253 ;-----------------------------------------------------------------------------
254 ;   int x264_pixel_ssd_16x8_sse2 (uint8_t *, int, uint8_t *, int )
255 ;-----------------------------------------------------------------------------
256 x264_pixel_ssd_16x8_sse2:
257     SSD_START_SSE2
258     SSD_INC_8x16P_SSE2
259     SSD_END_SSE2
260
261 ; %1=(row2, row0) %2=(row3, row1) %3=junk
262 ; output in %1=(row3, row0) and %3=(row2, row1)
263 %macro HADAMARD4x4_SSE2 3
264     movdqa     %3, %1
265     paddw      %1, %2
266     psubw      %3, %2
267     movdqa     %2, %1
268     punpcklqdq %1, %3
269     punpckhqdq %2, %3
270     movdqa     %3, %1
271     paddw      %1, %2
272     psubw      %3, %2
273 %endmacro
274
275 ;;; two HADAMARD4x4_SSE2 running side-by-side
276 %macro HADAMARD4x4_TWO_SSE2 6    ; a02 a13 junk1 b02 b13 junk2 (1=4 2=5 3=6)
277     movdqa     %3, %1
278     movdqa     %6, %4
279     paddw      %1, %2
280     paddw      %4, %5
281     psubw      %3, %2
282     psubw      %6, %5
283     movdqa     %2, %1
284     movdqa     %5, %4
285     punpcklqdq %1, %3
286     punpcklqdq %4, %6
287     punpckhqdq %2, %3
288     punpckhqdq %5, %6
289     movdqa     %3, %1
290     movdqa     %6, %4
291     paddw      %1, %2
292     paddw      %4, %5
293     psubw      %3, %2
294     psubw      %6, %5
295 %endmacro
296
297 %macro TRANSPOSE4x4_TWIST_SSE2 3    ; %1=(row3, row0) %2=(row2, row1) %3=junk, output in %1 and %2
298     movdqa     %3, %1
299     punpcklwd  %1, %2
300     punpckhwd  %2, %3             ; backwards because the high quadwords are already swapped
301
302     movdqa     %3, %1
303     punpckldq  %1, %2
304     punpckhdq  %3, %2
305
306     movdqa     %2, %1
307     punpcklqdq %1, %3
308     punpckhqdq %2, %3
309 %endmacro
310
311 ;;; two TRANSPOSE4x4_TWIST_SSE2 running side-by-side
312 %macro TRANSPOSE4x4_TWIST_TWO_SSE2 6    ; a02 a13 junk1 b02 b13 junk2 (1=4 2=5 3=6)
313     movdqa     %3, %1
314     movdqa     %6, %4
315     punpcklwd  %1, %2
316     punpcklwd  %4, %5
317     punpckhwd  %2, %3
318     punpckhwd  %5, %6
319     movdqa     %3, %1
320     movdqa     %6, %4
321     punpckldq  %1, %2
322     punpckldq  %4, %5
323     punpckhdq  %3, %2
324     punpckhdq  %6, %5
325     movdqa     %2, %1
326     movdqa     %5, %4
327     punpcklqdq %1, %3
328     punpcklqdq %4, %6
329     punpckhqdq %2, %3
330     punpckhqdq %5, %6
331 %endmacro
332
333 ;;; loads the difference of two 4x4 blocks into xmm0,xmm1 and xmm4,xmm5 in interleaved-row order
334 ;;; destroys xmm2, 3
335 ;;; the value in xmm7 doesn't matter: it's only subtracted from itself
336 %macro LOAD4x8_DIFF_SSE2 0
337     movq      xmm0, [rdi]
338     movq      xmm4, [rdx]
339     punpcklbw xmm0, xmm7
340     punpcklbw xmm4, xmm7
341     psubw     xmm0, xmm4
342
343     movq      xmm1, [rdi+rsi]
344     movq      xmm5, [rdx+rcx]
345     lea       rdi,  [rdi+2*rsi]
346     lea       rdx,  [rdx+2*rcx]
347     punpcklbw xmm1, xmm7
348     punpcklbw xmm5, xmm7
349     psubw     xmm1, xmm5
350
351     movq       xmm2, [rdi]
352     movq       xmm4, [rdx]
353     punpcklbw  xmm2, xmm7
354     punpcklbw  xmm4, xmm7
355     psubw      xmm2, xmm4
356     movdqa     xmm4, xmm0
357     punpcklqdq xmm0, xmm2        ; rows 0 and 2
358     punpckhqdq xmm4, xmm2        ; next 4x4 rows 0 and 2
359
360     movq       xmm3, [rdi+rsi]
361     movq       xmm5, [rdx+rcx]
362     lea        rdi,  [rdi+2*rsi]
363     lea        rdx,  [rdx+2*rcx]
364     punpcklbw  xmm3, xmm7
365     punpcklbw  xmm5, xmm7
366     psubw      xmm3, xmm5
367     movdqa     xmm5, xmm1
368     punpcklqdq xmm1, xmm3        ; rows 1 and 3
369     punpckhqdq xmm5, xmm3        ; next 4x4 rows 1 and 3
370 %endmacro
371
372 %macro SUM1x8_SSE2 3    ; 01 junk sum
373     pxor    %2, %2
374     psubw   %2, %1
375     pmaxsw  %1, %2
376     paddusw %3, %1
377 %endmacro
378
379 %macro SUM4x4_SSE2 4    ; 02 13 junk sum
380     pxor    %3, %3
381     psubw   %3, %1
382     pmaxsw  %1, %3
383
384     pxor    %3, %3
385     psubw   %3, %2
386     pmaxsw  %2, %3
387
388     paddusw %4, %1
389     paddusw %4, %2
390 %endmacro
391
392 ;;; two SUM4x4_SSE2 running side-by-side
393 %macro SUM4x4_TWO_SSE2 7    ; a02 a13 junk1 b02 b13 junk2 (1=4 2=5 3=6) sum
394     pxor    %3, %3
395     pxor    %6, %6
396     psubw   %3, %1
397     psubw   %6, %4
398     pmaxsw  %1, %3
399     pmaxsw  %4, %6
400     pxor    %3, %3
401     pxor    %6, %6
402     psubw   %3, %2
403     psubw   %6, %5
404     pmaxsw  %2, %3
405     pmaxsw  %5, %6
406     paddusw %1, %2
407     paddusw %4, %5
408     paddusw %7, %1
409     paddusw %7, %4
410 %endmacro
411
412 %macro SATD_TWO_SSE2 0
413     LOAD4x8_DIFF_SSE2
414     HADAMARD4x4_TWO_SSE2        xmm0, xmm1, xmm2, xmm4, xmm5, xmm3
415     TRANSPOSE4x4_TWIST_TWO_SSE2 xmm0, xmm2, xmm1, xmm4, xmm3, xmm5
416     HADAMARD4x4_TWO_SSE2        xmm0, xmm2, xmm1, xmm4, xmm3, xmm5
417     SUM4x4_TWO_SSE2             xmm0, xmm1, xmm2, xmm4, xmm5, xmm3, xmm6
418 %endmacro
419
420 %macro SATD_START 0
421 ;   mov     rdi, rdi            ; pix1
422     movsxd  rsi, esi            ; stride1
423 ;   mov     rdx, rdx            ; pix2
424     movsxd  rcx, ecx            ; stride2
425     pxor    xmm6, xmm6
426 %endmacro
427
428 %macro SATD_END 0
429     psrlw   xmm6, 1
430     HADDW   xmm6, xmm7
431     movd    eax,  xmm6
432     ret
433 %endmacro
434
435 ALIGN 16
436 ;-----------------------------------------------------------------------------
437 ;   int x264_pixel_satd_16x16_sse2 (uint8_t *, int, uint8_t *, int )
438 ;-----------------------------------------------------------------------------
439 x264_pixel_satd_16x16_sse2:
440     SATD_START
441     mov     r8,  rdi
442     mov     r9,  rdx
443
444     SATD_TWO_SSE2
445     SATD_TWO_SSE2
446     SATD_TWO_SSE2
447     SATD_TWO_SSE2
448
449     lea     rdi, [r8+8]
450     lea     rdx, [r9+8]
451
452     SATD_TWO_SSE2
453     SATD_TWO_SSE2
454     SATD_TWO_SSE2
455     SATD_TWO_SSE2
456
457     SATD_END
458
459 ALIGN 16
460 ;-----------------------------------------------------------------------------
461 ;   int x264_pixel_satd_8x16_sse2 (uint8_t *, int, uint8_t *, int )
462 ;-----------------------------------------------------------------------------
463 x264_pixel_satd_8x16_sse2:
464     SATD_START
465
466     SATD_TWO_SSE2
467     SATD_TWO_SSE2
468     SATD_TWO_SSE2
469     SATD_TWO_SSE2
470
471     SATD_END
472
473 ALIGN 16
474 ;-----------------------------------------------------------------------------
475 ;   int x264_pixel_satd_16x8_sse2 (uint8_t *, int, uint8_t *, int )
476 ;-----------------------------------------------------------------------------
477 x264_pixel_satd_16x8_sse2:
478     SATD_START
479     mov     r8,  rdi
480     mov     r9,  rdx
481
482     SATD_TWO_SSE2
483     SATD_TWO_SSE2
484
485     lea     rdi, [r8+8]
486     lea     rdx, [r9+8]
487
488     SATD_TWO_SSE2
489     SATD_TWO_SSE2
490
491     SATD_END
492
493 ALIGN 16
494 ;-----------------------------------------------------------------------------
495 ;   int x264_pixel_satd_8x8_sse2 (uint8_t *, int, uint8_t *, int )
496 ;-----------------------------------------------------------------------------
497 x264_pixel_satd_8x8_sse2:
498     SATD_START
499
500     SATD_TWO_SSE2
501     SATD_TWO_SSE2
502
503     SATD_END
504
505 ALIGN 16
506 ;-----------------------------------------------------------------------------
507 ;   int x264_pixel_satd_8x4_sse2 (uint8_t *, int, uint8_t *, int )
508 ;-----------------------------------------------------------------------------
509 x264_pixel_satd_8x4_sse2:
510     SATD_START
511
512     SATD_TWO_SSE2
513
514     SATD_END
515
516
517 %macro LOAD_DIFF_8P 4  ; MMP, MMT, [pix1], [pix2]
518     movq        %1, %3
519     movq        %2, %4
520     punpcklbw   %1, %2
521     punpcklbw   %2, %2
522     psubw       %1, %2
523 %endmacro
524
525 %macro SBUTTERFLY 5
526     mov%1       %5, %3
527     punpckl%2   %3, %4
528     punpckh%2   %5, %4
529 %endmacro
530
531 %macro TRANSPOSE4x4D 5   ; abcd-t -> adtc
532     SBUTTERFLY dqa, dq,  %1, %2, %5
533     SBUTTERFLY dqa, dq,  %3, %4, %2
534     SBUTTERFLY dqa, qdq, %1, %3, %4
535     SBUTTERFLY dqa, qdq, %5, %2, %3
536 %endmacro
537
538 ;-----------------------------------------------------------------------------
539 ; input ABCDEFGH output AFHDTECB 
540 ;-----------------------------------------------------------------------------
541 %macro TRANSPOSE8x8 9
542     SBUTTERFLY dqa, wd, %1, %2, %9
543     SBUTTERFLY dqa, wd, %3, %4, %2
544     SBUTTERFLY dqa, wd, %5, %6, %4
545     SBUTTERFLY dqa, wd, %7, %8, %6
546     SBUTTERFLY dqa, dq, %1, %3, %8
547     SBUTTERFLY dqa, dq, %9, %2, %3
548     SBUTTERFLY dqa, dq, %5, %7, %2
549     SBUTTERFLY dqa, dq, %4, %6, %7
550     SBUTTERFLY dqa, qdq, %1, %5, %6
551     SBUTTERFLY dqa, qdq, %9, %4, %5
552     SBUTTERFLY dqa, qdq, %8, %2, %4
553     SBUTTERFLY dqa, qdq, %3, %7, %2
554 %endmacro
555
556 %macro SUMSUB_BADC 4
557     paddw   %1, %2
558     paddw   %3, %4
559     paddw   %2, %2
560     paddw   %4, %4
561     psubw   %2, %1
562     psubw   %4, %3
563 %endmacro
564
565 %macro HADAMARD1x8 8
566     SUMSUB_BADC %1, %5, %2, %6
567     SUMSUB_BADC %3, %7, %4, %8
568     SUMSUB_BADC %1, %3, %2, %4
569     SUMSUB_BADC %5, %7, %6, %8
570     SUMSUB_BADC %1, %2, %3, %4
571     SUMSUB_BADC %5, %6, %7, %8
572 %endmacro
573
574 ALIGN 16
575 ;-----------------------------------------------------------------------------
576 ;   int x264_pixel_sa8d_8x8_sse2( uint8_t *, int, uint8_t *, int )
577 ;-----------------------------------------------------------------------------
578 x264_pixel_sa8d_8x8_sse2:
579     lea  r10, [3*parm2q]
580     lea  r11, [3*parm4q]
581     LOAD_DIFF_8P xmm0, xmm8, [parm1q],          [parm3q]
582     LOAD_DIFF_8P xmm1, xmm9, [parm1q+parm2q],   [parm3q+parm4q]
583     LOAD_DIFF_8P xmm2, xmm8, [parm1q+2*parm2q], [parm3q+2*parm4q]
584     LOAD_DIFF_8P xmm3, xmm9, [parm1q+r10],      [parm3q+r11]
585     lea  parm1q, [parm1q+4*parm2q]
586     lea  parm3q, [parm3q+4*parm4q]
587     LOAD_DIFF_8P xmm4, xmm8, [parm1q],          [parm3q]
588     LOAD_DIFF_8P xmm5, xmm9, [parm1q+parm2q],   [parm3q+parm4q]
589     LOAD_DIFF_8P xmm6, xmm8, [parm1q+2*parm2q], [parm3q+2*parm4q]
590     LOAD_DIFF_8P xmm7, xmm9, [parm1q+r10],      [parm3q+r11]
591     
592     HADAMARD1x8  xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
593     TRANSPOSE8x8 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8
594     HADAMARD1x8  xmm0, xmm5, xmm7, xmm3, xmm8, xmm4, xmm2, xmm1
595
596     pxor            xmm10, xmm10
597     SUM4x4_TWO_SSE2 xmm0, xmm1, xmm6, xmm2, xmm3, xmm9, xmm10
598     SUM4x4_TWO_SSE2 xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10
599     psrlw           xmm10, 1
600     HADDW           xmm10, xmm0
601     movd eax, xmm10
602     add r8d, eax ; preserve rounding for 16x16
603     add eax, 1
604     shr eax, 1
605     ret
606
607 ALIGN 16
608 ;-----------------------------------------------------------------------------
609 ;   int x264_pixel_sa8d_16x16_sse2( uint8_t *, int, uint8_t *, int )
610 ;-----------------------------------------------------------------------------
611 ;; violates calling convention
612 x264_pixel_sa8d_16x16_sse2:
613     xor  r8d, r8d
614     call x264_pixel_sa8d_8x8_sse2 ; pix[0]
615     lea  parm1q, [parm1q+4*parm2q]
616     lea  parm3q, [parm3q+4*parm4q]
617     call x264_pixel_sa8d_8x8_sse2 ; pix[8*stride]
618     lea  r10, [3*parm2q-2]
619     lea  r11, [3*parm4q-2]
620     shl  r10, 2
621     shl  r11, 2
622     sub  parm1q, r10
623     sub  parm3q, r11
624     call x264_pixel_sa8d_8x8_sse2 ; pix[8]
625     lea  parm1q, [parm1q+4*parm2q]
626     lea  parm3q, [parm3q+4*parm4q]
627     call x264_pixel_sa8d_8x8_sse2 ; pix[8*stride+8]
628     mov  eax, r8d
629     add  eax, 1
630     shr  eax, 1
631     ret
632
633
634
635 ALIGN 16
636 ;-----------------------------------------------------------------------------
637 ;  void x264_intra_sa8d_x3_8x8_core_sse2( uint8_t *fenc, int16_t edges[2][8], int *res )
638 ;-----------------------------------------------------------------------------
639 x264_intra_sa8d_x3_8x8_core_sse2:
640     ; 8x8 hadamard
641     pxor        xmm4, xmm4
642     movq        xmm0, [parm1q+0*FENC_STRIDE]
643     movq        xmm7, [parm1q+1*FENC_STRIDE]
644     movq        xmm6, [parm1q+2*FENC_STRIDE]
645     movq        xmm3, [parm1q+3*FENC_STRIDE]
646     movq        xmm5, [parm1q+4*FENC_STRIDE]
647     movq        xmm1, [parm1q+5*FENC_STRIDE]
648     movq        xmm8, [parm1q+6*FENC_STRIDE]
649     movq        xmm2, [parm1q+7*FENC_STRIDE]
650     punpcklbw   xmm0, xmm4
651     punpcklbw   xmm7, xmm4
652     punpcklbw   xmm6, xmm4
653     punpcklbw   xmm3, xmm4
654     punpcklbw   xmm5, xmm4
655     punpcklbw   xmm1, xmm4
656     punpcklbw   xmm8, xmm4
657     punpcklbw   xmm2, xmm4
658     HADAMARD1x8 xmm0, xmm7, xmm6, xmm3, xmm5, xmm1, xmm8, xmm2
659     TRANSPOSE8x8 xmm0, xmm7, xmm6, xmm3, xmm5, xmm1, xmm8, xmm2, xmm4
660     HADAMARD1x8 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
661
662     ; dc
663     movzx       edi, word [parm2q+0]
664     add          di, word [parm2q+16]
665     add         edi, 8
666     and         edi, -16
667     shl         edi, 2
668
669     pxor        xmm15, xmm15
670     movdqa      xmm8, xmm2
671     movdqa      xmm9, xmm3
672     movdqa      xmm10, xmm4
673     movdqa      xmm11, xmm5
674     SUM4x4_TWO_SSE2 xmm8, xmm9, xmm12, xmm10, xmm11, xmm13, xmm15
675     movdqa      xmm8, xmm6
676     movdqa      xmm9, xmm7
677     SUM4x4_SSE2 xmm8, xmm9, xmm10, xmm15
678     movdqa      xmm8, xmm1
679     SUM1x8_SSE2 xmm8, xmm10, xmm15
680     movdqa      xmm14, xmm15 ; 7x8 sum
681
682     movdqa      xmm8, [parm2q+0] ; left edge
683     movd        xmm9, edi
684     psllw       xmm8, 3
685     psubw       xmm8, xmm0
686     psubw       xmm9, xmm0
687     SUM1x8_SSE2 xmm8, xmm10, xmm14
688     SUM1x8_SSE2 xmm9, xmm11, xmm15 ; 1x8 sum
689     punpcklwd   xmm0, xmm1
690     punpcklwd   xmm2, xmm3
691     punpcklwd   xmm4, xmm5
692     punpcklwd   xmm6, xmm7
693     punpckldq   xmm0, xmm2
694     punpckldq   xmm4, xmm6
695     punpcklqdq  xmm0, xmm4 ; transpose
696     movdqa      xmm1, [parm2q+16] ; top edge
697     movdqa      xmm2, xmm15
698     psllw       xmm1, 3
699     psrldq      xmm2, 2     ; 8x7 sum
700     psubw       xmm0, xmm1  ; 8x1 sum
701     SUM1x8_SSE2 xmm0, xmm1, xmm2
702
703     HADDW       xmm14, xmm3
704     movd        eax, xmm14
705     add         eax, 2
706     shr         eax, 2
707     mov         [parm3q+4], eax ; i8x8_h sa8d
708     HADDW       xmm15, xmm4
709     movd        eax, xmm15
710     add         eax, 2
711     shr         eax, 2
712     mov         [parm3q+8], eax ; i8x8_dc sa8d
713     HADDW       xmm2, xmm5
714     movd        eax, xmm2
715     add         eax, 2
716     shr         eax, 2
717     mov         [parm3q+0], eax ; i8x8_v sa8d
718
719     ret
720
721
722
723 ;-----------------------------------------------------------------------------
724 ; void x264_pixel_ssim_4x4x2_core_sse2( const uint8_t *pix1, int stride1,
725 ;                                       const uint8_t *pix2, int stride2, int sums[2][4] )
726 ;-----------------------------------------------------------------------------
727 ALIGN 16
728 x264_pixel_ssim_4x4x2_core_sse2:
729     pxor      xmm0, xmm0
730     pxor      xmm1, xmm1
731     pxor      xmm2, xmm2
732     pxor      xmm3, xmm3
733     pxor      xmm4, xmm4
734     movdqa    xmm8, [pw_1 GLOBAL]
735 %rep 4
736     movq      xmm5, [parm1q]
737     movq      xmm6, [parm3q]
738     punpcklbw xmm5, xmm0
739     punpcklbw xmm6, xmm0
740     paddw     xmm1, xmm5
741     paddw     xmm2, xmm6
742     movdqa    xmm7, xmm5
743     pmaddwd   xmm5, xmm5
744     pmaddwd   xmm7, xmm6
745     pmaddwd   xmm6, xmm6
746     paddd     xmm3, xmm5
747     paddd     xmm4, xmm7
748     paddd     xmm3, xmm6
749     add       parm1q, parm2q
750     add       parm3q, parm4q
751 %endrep
752     ; PHADDW xmm1, xmm2
753     ; PHADDD xmm3, xmm4
754     pshufd    xmm5, xmm3, 0xB1
755     pmaddwd   xmm1, xmm8
756     pmaddwd   xmm2, xmm8
757     pshufd    xmm6, xmm4, 0xB1
758     packssdw  xmm1, xmm2
759     paddd     xmm3, xmm5
760     pmaddwd   xmm1, xmm8
761     paddd     xmm4, xmm6
762     pshufd    xmm1, xmm1, 0xD8
763     movdqa    xmm5, xmm3
764     punpckldq xmm3, xmm4
765     punpckhdq xmm5, xmm4
766     movq      [parm5q+ 0], xmm1
767     movq      [parm5q+ 8], xmm3
768     psrldq    xmm1, 8
769     movq      [parm5q+16], xmm1
770     movq      [parm5q+24], xmm5
771     ret
772
773 ;-----------------------------------------------------------------------------
774 ; float x264_pixel_ssim_end_sse2( int sum0[5][4], int sum1[5][4], int width )
775 ;-----------------------------------------------------------------------------
776 ALIGN 16
777 x264_pixel_ssim_end4_sse2:
778     movdqa   xmm0, [parm1q+ 0]
779     movdqa   xmm1, [parm1q+16]
780     movdqa   xmm2, [parm1q+32]
781     movdqa   xmm3, [parm1q+48]
782     movdqa   xmm4, [parm1q+64]
783     paddd    xmm0, [parm2q+ 0]
784     paddd    xmm1, [parm2q+16]
785     paddd    xmm2, [parm2q+32]
786     paddd    xmm3, [parm2q+48]
787     paddd    xmm4, [parm2q+64]
788     paddd    xmm0, xmm1
789     paddd    xmm1, xmm2
790     paddd    xmm2, xmm3
791     paddd    xmm3, xmm4
792     movdqa   xmm5, [ssim_c1 GLOBAL]
793     movdqa   xmm6, [ssim_c2 GLOBAL]
794     TRANSPOSE4x4D  xmm0, xmm1, xmm2, xmm3, xmm4
795
796 ;   s1=mm0, s2=mm3, ss=mm4, s12=mm2
797     movdqa   xmm1, xmm3
798     pslld    xmm3, 16
799     pmaddwd  xmm1, xmm0  ; s1*s2
800     por      xmm0, xmm3
801     pmaddwd  xmm0, xmm0  ; s1*s1 + s2*s2
802     pslld    xmm1, 1
803     pslld    xmm2, 7
804     pslld    xmm4, 6
805     psubd    xmm2, xmm1  ; covar*2
806     psubd    xmm4, xmm0  ; vars
807     paddd    xmm0, xmm5
808     paddd    xmm1, xmm5
809     paddd    xmm2, xmm6
810     paddd    xmm4, xmm6
811     cvtdq2ps xmm0, xmm0  ; (float)(s1*s1 + s2*s2 + ssim_c1)
812     cvtdq2ps xmm1, xmm1  ; (float)(s1*s2*2 + ssim_c1)
813     cvtdq2ps xmm2, xmm2  ; (float)(covar*2 + ssim_c2)
814     cvtdq2ps xmm4, xmm4  ; (float)(vars + ssim_c2)
815     mulps    xmm1, xmm2
816     mulps    xmm0, xmm4
817     divps    xmm1, xmm0  ; ssim
818
819     neg      parm3d
820     movdqu   xmm3, [mask_ff + parm3d*4 + 16 GLOBAL]
821     pand     xmm1, xmm3
822     movhlps  xmm0, xmm1
823     addps    xmm0, xmm1
824     pshuflw  xmm1, xmm0, 0xE
825     addss    xmm0, xmm1
826     ret
827