]> git.sesse.net Git - x264/blob - common/i386/pixel-sse2.asm
SSE2 pixel comparison functions
[x264] / common / i386 / 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 32
24
25 ;=============================================================================
26 ; Macros and other preprocessor constants
27 ;=============================================================================
28
29 %macro cglobal 1
30     %ifdef PREFIX
31         global _%1
32         %define %1 _%1
33     %else
34         global %1
35     %endif
36 %endmacro
37
38
39 %ifdef FORMAT_COFF
40 SECTION .rodata data
41 %else
42 SECTION .rodata data align=16
43 %endif
44
45 pd_0000ffff: times 4 dd 0x0000ffff
46
47
48 SECTION .text
49
50
51 cglobal x264_pixel_sad_16x16_sse2
52 cglobal x264_pixel_sad_16x8_sse2
53 cglobal x264_pixel_ssd_16x16_sse2
54 cglobal x264_pixel_ssd_16x8_sse2
55 cglobal x264_pixel_satd_8x4_sse2
56 cglobal x264_pixel_satd_8x8_sse2
57 cglobal x264_pixel_satd_16x8_sse2
58 cglobal x264_pixel_satd_8x16_sse2
59 cglobal x264_pixel_satd_16x16_sse2
60
61 %macro SAD_INC_4x16P_SSE2 0
62     movdqu  xmm1,   [ecx]
63     movdqu  xmm2,   [ecx+edx]
64     lea     ecx,    [ecx+2*edx]
65     movdqu  xmm3,   [ecx]
66     movdqu  xmm4,   [ecx+edx]
67     psadbw  xmm1,   [eax]
68     psadbw  xmm2,   [eax+ebx]
69     lea     eax,    [eax+2*ebx]
70     psadbw  xmm3,   [eax]
71     psadbw  xmm4,   [eax+ebx]
72     lea     eax,    [eax+2*ebx]
73     lea     ecx,    [ecx+2*edx]
74     paddw   xmm1,   xmm2
75     paddw   xmm3,   xmm4
76     paddw   xmm0,   xmm1
77     paddw   xmm0,   xmm3
78 %endmacro
79
80 %macro SAD_START_SSE2 0
81     push    ebx
82
83     mov     eax,    [esp+ 8]    ; pix1
84     mov     ebx,    [esp+12]    ; stride1
85     mov     ecx,    [esp+16]    ; pix2
86     mov     edx,    [esp+20]    ; stride2
87 %endmacro
88
89 %macro SAD_END_SSE2 0
90     movdqa  xmm1, xmm0
91     psrldq  xmm0,  8
92     paddw   xmm0, xmm1
93     movd    eax,  xmm0
94
95     pop ebx
96     ret
97 %endmacro
98
99 ALIGN 16
100 ;-----------------------------------------------------------------------------
101 ;   int __cdecl x264_pixel_sad_16x16_sse2 (uint8_t *, int, uint8_t *, int )
102 ;-----------------------------------------------------------------------------
103 x264_pixel_sad_16x16_sse2:
104     SAD_START_SSE2
105     movdqu xmm0, [ecx]
106     movdqu xmm1, [ecx+edx]
107     lea    ecx,  [ecx+2*edx]
108     movdqu xmm2, [ecx]
109     movdqu xmm3, [ecx+edx]
110     lea    ecx,  [ecx+2*edx]
111     psadbw xmm0, [eax]
112     psadbw xmm1, [eax+ebx]
113     lea    eax,  [eax+2*ebx]
114     movdqu xmm4, [ecx]
115     paddw  xmm0, xmm1
116     psadbw xmm2, [eax]
117     psadbw xmm3, [eax+ebx]
118     lea    eax,  [eax+2*ebx]
119     movdqu xmm5, [ecx+edx]
120     lea    ecx,  [ecx+2*edx]
121     paddw  xmm2, xmm3
122     movdqu xmm6, [ecx]
123     movdqu xmm7, [ecx+edx]
124     lea    ecx,  [ecx+2*edx]
125     paddw  xmm0, xmm2
126     psadbw xmm4, [eax]
127     psadbw xmm5, [eax+ebx]
128     lea    eax,  [eax+2*ebx]
129     movdqu xmm1, [ecx]
130     paddw  xmm4, xmm5
131     psadbw xmm6, [eax]
132     psadbw xmm7, [eax+ebx]
133     lea    eax,  [eax+2*ebx]
134     movdqu xmm2, [ecx+edx]
135     lea    ecx,  [ecx+2*edx]
136     paddw  xmm6, xmm7
137     movdqu xmm3, [ecx]
138     paddw  xmm0, xmm4
139     movdqu xmm4, [ecx+edx]
140     lea    ecx,  [ecx+2*edx]
141     paddw  xmm0, xmm6
142     psadbw xmm1, [eax]
143     psadbw xmm2, [eax+ebx]
144     lea    eax,  [eax+2*ebx]
145     movdqu xmm5, [ecx]
146     paddw  xmm1, xmm2
147     psadbw xmm3, [eax]
148     psadbw xmm4, [eax+ebx]
149     lea    eax,  [eax+2*ebx]
150     movdqu xmm6, [ecx+edx]
151     lea    ecx,  [ecx+2*edx]
152     paddw  xmm3, xmm4
153     movdqu xmm7, [ecx]
154     paddw  xmm0, xmm1
155     movdqu xmm1, [ecx+edx]
156     paddw  xmm0, xmm3
157     psadbw xmm5, [eax]
158     psadbw xmm6, [eax+ebx]
159     lea    eax,  [eax+2*ebx]
160     paddw  xmm5, xmm6
161     psadbw xmm7, [eax]
162     psadbw xmm1, [eax+ebx]
163     paddw  xmm7, xmm1
164     paddw  xmm0, xmm5
165     paddw  xmm0, xmm7
166     SAD_END_SSE2
167
168 ALIGN 16
169 ;-----------------------------------------------------------------------------
170 ;   int __cdecl x264_pixel_sad_16x8_sse2 (uint8_t *, int, uint8_t *, int )
171 ;-----------------------------------------------------------------------------
172 x264_pixel_sad_16x8_sse2:
173     SAD_START_SSE2
174     pxor    xmm0,   xmm0
175     SAD_INC_4x16P_SSE2
176     SAD_INC_4x16P_SSE2
177     SAD_END_SSE2
178
179 %macro SSD_INC_2x16P_SSE2 0
180     movdqu  xmm1,   [eax]
181     movdqu  xmm2,   [ecx]
182     movdqu  xmm3,   [eax+ebx]
183     movdqu  xmm4,   [ecx+edx]
184
185     movdqa  xmm5,   xmm1
186     movdqa  xmm6,   xmm3
187     psubusb xmm1,   xmm2
188     psubusb xmm3,   xmm4
189     psubusb xmm2,   xmm5
190     psubusb xmm4,   xmm6
191     por     xmm1,   xmm2
192     por     xmm3,   xmm4
193
194     movdqa  xmm2,   xmm1
195     movdqa  xmm4,   xmm3
196     punpcklbw xmm1, xmm7
197     punpckhbw xmm2, xmm7
198     punpcklbw xmm3, xmm7
199     punpckhbw xmm4, xmm7
200     pmaddwd xmm1,   xmm1
201     pmaddwd xmm2,   xmm2
202     pmaddwd xmm3,   xmm3
203     pmaddwd xmm4,   xmm4
204
205     lea     eax,    [eax+2*ebx]
206     lea     ecx,    [ecx+2*edx]
207
208     paddd   xmm1,   xmm2
209     paddd   xmm3,   xmm4
210     paddd   xmm0,   xmm1
211     paddd   xmm0,   xmm3
212 %endmacro
213
214 %macro SSD_INC_8x16P_SSE2 0
215     SSD_INC_2x16P_SSE2
216     SSD_INC_2x16P_SSE2
217     SSD_INC_2x16P_SSE2
218     SSD_INC_2x16P_SSE2
219 %endmacro
220
221 %macro SSD_START_SSE2 0
222     push    ebx
223
224     mov     eax,    [esp+ 8]    ; pix1
225     mov     ebx,    [esp+12]    ; stride1
226     mov     ecx,    [esp+16]    ; pix2
227     mov     edx,    [esp+20]    ; stride2
228
229     pxor    xmm7,   xmm7         ; zero
230     pxor    xmm0,   xmm0         ; mm0 holds the sum
231 %endmacro
232
233 %macro SSD_END_SSE2 0
234     movdqa  xmm1,   xmm0
235     psrldq  xmm1,    8
236     paddd   xmm0,   xmm1
237
238     movdqa  xmm1,   xmm0
239     psrldq  xmm1,    4
240     paddd   xmm0,   xmm1
241
242     movd    eax,    xmm0
243
244     pop ebx
245     ret
246 %endmacro
247
248 ALIGN 16
249 ;-----------------------------------------------------------------------------
250 ;   int __cdecl x264_pixel_ssd_16x16_sse2 (uint8_t *, int, uint8_t *, int )
251 ;-----------------------------------------------------------------------------
252 x264_pixel_ssd_16x16_sse2:
253     SSD_START_SSE2
254     SSD_INC_8x16P_SSE2
255     SSD_INC_8x16P_SSE2
256     SSD_END_SSE2
257
258 ALIGN 16
259 ;-----------------------------------------------------------------------------
260 ;   int __cdecl x264_pixel_ssd_16x8_sse2 (uint8_t *, int, uint8_t *, int )
261 ;-----------------------------------------------------------------------------
262 x264_pixel_ssd_16x8_sse2:
263     SSD_START_SSE2
264     SSD_INC_8x16P_SSE2
265     SSD_END_SSE2
266
267 ; %1=(row2, row0) %2=(row3, row1) %3=junk
268 ; output in %1=(row3, row0) and %3=(row2, row1)
269 %macro HADAMARD4x4_SSE2 3
270     movdqa     %3, %1
271     paddw      %1, %2
272     psubw      %3, %2
273     movdqa     %2, %1
274     punpcklqdq %1, %3
275     punpckhqdq %2, %3
276     movdqa     %3, %1
277     paddw      %1, %2
278     psubw      %3, %2
279 %endmacro
280
281 ;;; two HADAMARD4x4_SSE2 running side-by-side
282 %macro HADAMARD4x4_TWO_SSE2 6    ; a02 a13 junk1 b02 b13 junk2 (1=4 2=5 3=6)
283     movdqa     %3, %1
284     movdqa     %6, %4
285     paddw      %1, %2
286     paddw      %4, %5
287     psubw      %3, %2
288     psubw      %6, %5
289     movdqa     %2, %1
290     movdqa     %5, %4
291     punpcklqdq %1, %3
292     punpcklqdq %4, %6
293     punpckhqdq %2, %3
294     punpckhqdq %5, %6
295     movdqa     %3, %1
296     movdqa     %6, %4
297     paddw      %1, %2
298     paddw      %4, %5
299     psubw      %3, %2
300     psubw      %6, %5
301 %endmacro
302
303 %macro TRANSPOSE4x4_TWIST_SSE2 3    ; %1=(row3, row0) %2=(row2, row1) %3=junk, output in %1 and %2
304     movdqa     %3, %1
305     punpcklwd  %1, %2
306     punpckhwd  %2, %3             ; backwards because the high quadwords are already swapped
307
308     movdqa     %3, %1
309     punpckldq  %1, %2
310     punpckhdq  %3, %2
311
312     movdqa     %2, %1
313     punpcklqdq %1, %3
314     punpckhqdq %2, %3
315 %endmacro
316
317 ;;; two TRANSPOSE4x4_TWIST_SSE2 running side-by-side
318 %macro TRANSPOSE4x4_TWIST_TWO_SSE2 6    ; a02 a13 junk1 b02 b13 junk2 (1=4 2=5 3=6)
319     movdqa     %3, %1
320     movdqa     %6, %4
321     punpcklwd  %1, %2
322     punpcklwd  %4, %5
323     punpckhwd  %2, %3
324     punpckhwd  %5, %6
325     movdqa     %3, %1
326     movdqa     %6, %4
327     punpckldq  %1, %2
328     punpckldq  %4, %5
329     punpckhdq  %3, %2
330     punpckhdq  %6, %5
331     movdqa     %2, %1
332     movdqa     %5, %4
333     punpcklqdq %1, %3
334     punpcklqdq %4, %6
335     punpckhqdq %2, %3
336     punpckhqdq %5, %6
337 %endmacro
338
339 ;;; loads the difference of two 4x4 blocks into xmm0,xmm1 and xmm4,xmm5 in interleaved-row order
340 ;;; destroys xmm2, 3
341 ;;; the value in xmm7 doesn't matter: it's only subtracted from itself
342 %macro LOAD4x8_DIFF_SSE2 0
343     movq      xmm0, [eax]
344     movq      xmm4, [ecx]
345     punpcklbw xmm0, xmm7
346     punpcklbw xmm4, xmm7
347     psubw     xmm0, xmm4
348
349     movq      xmm1, [eax+ebx]
350     movq      xmm5, [ecx+edx]
351     lea       eax,  [eax+2*ebx]
352     lea       ecx,  [ecx+2*edx]
353     punpcklbw xmm1, xmm7
354     punpcklbw xmm5, xmm7
355     psubw     xmm1, xmm5
356
357     movq       xmm2, [eax]
358     movq       xmm4, [ecx]
359     punpcklbw  xmm2, xmm7
360     punpcklbw  xmm4, xmm7
361     psubw      xmm2, xmm4
362     movdqa     xmm4, xmm0
363     punpcklqdq xmm0, xmm2        ; rows 0 and 2
364     punpckhqdq xmm4, xmm2        ; next 4x4 rows 0 and 2
365
366     movq       xmm3, [eax+ebx]
367     movq       xmm5, [ecx+edx]
368     lea        eax,  [eax+2*ebx]
369     lea        ecx,  [ecx+2*edx]
370     punpcklbw  xmm3, xmm7
371     punpcklbw  xmm5, xmm7
372     psubw      xmm3, xmm5
373     movdqa     xmm5, xmm1
374     punpcklqdq xmm1, xmm3        ; rows 1 and 3
375     punpckhqdq xmm5, xmm3        ; next 4x4 rows 1 and 3
376 %endmacro
377
378 %macro SUM4x4_SSE2 4    ; 02 13 junk sum
379     pxor    %3, %3
380     psubw   %3, %1
381     pmaxsw  %1, %3
382
383     pxor    %3, %3
384     psubw   %3, %2
385     pmaxsw  %2, %3
386
387     paddusw %4, %1
388     paddusw %4, %2
389 %endmacro
390
391 ;;; two SUM4x4_SSE2 running side-by-side
392 %macro SUM4x4_TWO_SSE2 7    ; a02 a13 junk1 b02 b13 junk2 (1=4 2=5 3=6) sum
393     pxor    %3, %3
394     pxor    %6, %6
395     psubw   %3, %1
396     psubw   %6, %4
397     pmaxsw  %1, %3
398     pmaxsw  %4, %6
399     pxor    %3, %3
400     pxor    %6, %6
401     psubw   %3, %2
402     psubw   %6, %5
403     pmaxsw  %2, %3
404     pmaxsw  %5, %6
405     paddusw %1, %2
406     paddusw %4, %5
407     paddusw %7, %1
408     paddusw %7, %4
409 %endmacro
410
411 %macro SUM_MM_SSE2 2    ; sum junk
412     ; each column sum of SATD is necessarily even, so we don't lose any precision by shifting first.
413     psrlw   %1, 1
414     movdqa  %2, %1
415     psrldq  %1, 2
416     paddusw %1, %2
417     pand    %1, [pd_0000ffff]
418     movdqa  %2, %1
419     psrldq  %1, 4
420     paddd   %1, %2
421     movdqa  %2, %1
422     psrldq  %1, 8
423     paddd   %1, %2
424     movd    eax,%1
425 %endmacro
426
427 %macro SATD_TWO_SSE2 0
428     LOAD4x8_DIFF_SSE2
429     HADAMARD4x4_TWO_SSE2        xmm0, xmm1, xmm2, xmm4, xmm5, xmm3
430     TRANSPOSE4x4_TWIST_TWO_SSE2 xmm0, xmm2, xmm1, xmm4, xmm3, xmm5
431     HADAMARD4x4_TWO_SSE2        xmm0, xmm2, xmm1, xmm4, xmm3, xmm5
432     SUM4x4_TWO_SSE2             xmm0, xmm1, xmm2, xmm4, xmm5, xmm3, xmm6
433 %endmacro
434
435 %macro SATD_START 0
436     push    ebx
437
438     mov     eax,    [esp+ 8]    ; pix1
439     mov     ebx,    [esp+12]    ; stride1
440     mov     ecx,    [esp+16]    ; pix2
441     mov     edx,    [esp+20]    ; stride2
442
443     pxor    xmm6,    xmm6
444 %endmacro
445
446 %macro SATD_END 0
447     SUM_MM_SSE2  xmm6, xmm7
448
449     pop     ebx
450     ret
451 %endmacro
452
453 ALIGN 16
454 ;-----------------------------------------------------------------------------
455 ;   int __cdecl x264_pixel_satd_16x16_sse2 (uint8_t *, int, uint8_t *, int )
456 ;-----------------------------------------------------------------------------
457 x264_pixel_satd_16x16_sse2:
458     SATD_START
459
460     SATD_TWO_SSE2
461     SATD_TWO_SSE2
462     SATD_TWO_SSE2
463     SATD_TWO_SSE2
464
465     mov     eax,    [esp+ 8]
466     mov     ecx,    [esp+16]
467     lea     eax,    [eax+8]
468     lea     ecx,    [ecx+8]
469
470     SATD_TWO_SSE2
471     SATD_TWO_SSE2
472     SATD_TWO_SSE2
473     SATD_TWO_SSE2
474
475     SATD_END
476
477 ALIGN 16
478 ;-----------------------------------------------------------------------------
479 ;   int __cdecl x264_pixel_satd_8x16_sse2 (uint8_t *, int, uint8_t *, int )
480 ;-----------------------------------------------------------------------------
481 x264_pixel_satd_8x16_sse2:
482     SATD_START
483
484     SATD_TWO_SSE2
485     SATD_TWO_SSE2
486     SATD_TWO_SSE2
487     SATD_TWO_SSE2
488
489     SATD_END
490
491 ALIGN 16
492 ;-----------------------------------------------------------------------------
493 ;   int __cdecl x264_pixel_satd_16x8_sse2 (uint8_t *, int, uint8_t *, int )
494 ;-----------------------------------------------------------------------------
495 x264_pixel_satd_16x8_sse2:
496     SATD_START
497
498     SATD_TWO_SSE2
499     SATD_TWO_SSE2
500
501     mov     eax,    [esp+ 8]
502     mov     ecx,    [esp+16]
503     lea     eax,    [eax+8]
504     lea     ecx,    [ecx+8]
505
506     SATD_TWO_SSE2
507     SATD_TWO_SSE2
508
509     SATD_END
510
511 ALIGN 16
512 ;-----------------------------------------------------------------------------
513 ;   int __cdecl x264_pixel_satd_8x8_sse2 (uint8_t *, int, uint8_t *, int )
514 ;-----------------------------------------------------------------------------
515 x264_pixel_satd_8x8_sse2:
516     SATD_START
517
518     SATD_TWO_SSE2
519     SATD_TWO_SSE2
520
521     SATD_END
522
523 ALIGN 16
524 ;-----------------------------------------------------------------------------
525 ;   int __cdecl x264_pixel_satd_8x4_sse2 (uint8_t *, int, uint8_t *, int )
526 ;-----------------------------------------------------------------------------
527 x264_pixel_satd_8x4_sse2:
528     SATD_START
529
530     SATD_TWO_SSE2
531
532     SATD_END
533