]> git.sesse.net Git - x264/blob - common/amd64/deblock-a.asm
10% faster deblock mmx functions. ported from ffmpeg.
[x264] / common / amd64 / deblock-a.asm
1 ;*****************************************************************************
2 ;* deblock-a.asm: h264 encoder library
3 ;*****************************************************************************
4 ;* Copyright (C) 2005 x264 project
5 ;*
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
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 %include "amd64inc.asm"
26
27 SECTION .rodata align=16
28 pb_01: times 16 db 0x01
29 pb_03: times 16 db 0x03
30 pb_a1: times 16 db 0xa1
31
32 SECTION .text
33 cglobal x264_deblock_v_luma_sse2
34 cglobal x264_deblock_h_luma_sse2
35 cglobal x264_deblock_v_chroma_mmxext
36 cglobal x264_deblock_h_chroma_mmxext
37 cglobal x264_deblock_v_chroma_intra_mmxext
38 cglobal x264_deblock_h_chroma_intra_mmxext
39
40 ; expands to [base],...,[base+7*stride]
41 %define PASS8ROWS(base, base3, stride, stride3) \
42     [base], [base+stride], [base+stride*2], [base3], \
43     [base3+stride], [base3+stride*2], [base3+stride3], [base3+stride*4]
44
45 ; in: 8 rows of 4 bytes in %1..%8
46 ; out: 4 rows of 8 bytes in mm0..mm3
47 %macro TRANSPOSE4x8_LOAD 8
48     movd       mm0, %1
49     movd       mm2, %2
50     movd       mm1, %3
51     movd       mm3, %4
52     punpcklbw  mm0, mm2
53     punpcklbw  mm1, mm3
54     movq       mm2, mm0
55     punpcklwd  mm0, mm1
56     punpckhwd  mm2, mm1
57
58     movd       mm4, %5
59     movd       mm6, %6
60     movd       mm5, %7
61     movd       mm7, %8
62     punpcklbw  mm4, mm6
63     punpcklbw  mm5, mm7
64     movq       mm6, mm4
65     punpcklwd  mm4, mm5
66     punpckhwd  mm6, mm5
67
68     movq       mm1, mm0
69     movq       mm3, mm2
70     punpckldq  mm0, mm4
71     punpckhdq  mm1, mm4
72     punpckldq  mm2, mm6
73     punpckhdq  mm3, mm6
74 %endmacro
75
76 ; in: 4 rows of 8 bytes in mm0..mm3
77 ; out: 8 rows of 4 bytes in %1..%8
78 %macro TRANSPOSE8x4_STORE 8
79     movq       mm4, mm0
80     movq       mm5, mm1
81     movq       mm6, mm2
82     punpckhdq  mm4, mm4
83     punpckhdq  mm5, mm5
84     punpckhdq  mm6, mm6
85
86     punpcklbw  mm0, mm1
87     punpcklbw  mm2, mm3
88     movq       mm1, mm0
89     punpcklwd  mm0, mm2
90     punpckhwd  mm1, mm2
91     movd       %1,  mm0
92     punpckhdq  mm0, mm0
93     movd       %2,  mm0
94     movd       %3,  mm1
95     punpckhdq  mm1, mm1
96     movd       %4,  mm1
97
98     punpckhdq  mm3, mm3
99     punpcklbw  mm4, mm5
100     punpcklbw  mm6, mm3
101     movq       mm5, mm4
102     punpcklwd  mm4, mm6
103     punpckhwd  mm5, mm6
104     movd       %5,  mm4
105     punpckhdq  mm4, mm4
106     movd       %6,  mm4
107     movd       %7,  mm5
108     punpckhdq  mm5, mm5
109     movd       %8,  mm5
110 %endmacro
111
112 %macro SBUTTERFLY 4
113     movq       %4, %2
114     punpckl%1  %2, %3
115     punpckh%1  %4, %3
116 %endmacro
117
118 ; in: 8 rows of 8 (only the middle 6 pels are used) in %1..%8
119 ; out: 6 rows of 8 in [%9+0*16] .. [%9+5*16]
120 %macro TRANSPOSE6x8_MEM 9
121     movq  mm0, %1
122     movq  mm1, %3
123     movq  mm2, %5
124     movq  mm3, %7
125     SBUTTERFLY bw, mm0, %2, mm4
126     SBUTTERFLY bw, mm1, %4, mm5
127     SBUTTERFLY bw, mm2, %6, mm6
128     movq  [%9+0x10], mm5
129     SBUTTERFLY bw, mm3, %8, mm7
130     SBUTTERFLY wd, mm0, mm1, mm5
131     SBUTTERFLY wd, mm2, mm3, mm1
132     punpckhdq mm0, mm2
133     movq  [%9+0x00], mm0
134     SBUTTERFLY wd, mm4, [%9+0x10], mm3
135     SBUTTERFLY wd, mm6, mm7, mm2
136     SBUTTERFLY dq, mm4, mm6, mm0
137     SBUTTERFLY dq, mm5, mm1, mm7
138     punpckldq mm3, mm2
139     movq  [%9+0x10], mm5
140     movq  [%9+0x20], mm7
141     movq  [%9+0x30], mm4
142     movq  [%9+0x40], mm0
143     movq  [%9+0x50], mm3
144 %endmacro
145
146 ; out: %4 = |%1-%2|>%3
147 ; clobbers: %5
148 %macro DIFF_GT 6
149     mov%1   %6, %3
150     mov%1   %5, %2
151     psubusb %6, %2
152     psubusb %5, %3
153     por     %5, %6
154     psubusb %5, %4
155 %endmacro
156 %macro DIFF_GT_MMX 5
157     DIFF_GT q, %1, %2, %3, %4, %5
158 %endmacro
159 %macro DIFF_GT_SSE2 5
160     DIFF_GT dqa, %1, %2, %3, %4, %5
161 %endmacro
162
163 ; out: %4 = |%1-%2|>%3
164 ; clobbers: %5
165 %macro DIFF_GT2 6
166     mov%1   %6, %3
167     mov%1   %5, %2
168     psubusb %6, %2
169     psubusb %5, %3
170     psubusb %6, %4
171     psubusb %5, %4
172     pcmpeqb %5, %6
173 %endmacro
174 %macro DIFF_GT2_MMX 5
175     DIFF_GT2 q, %1, %2, %3, %4, %5
176 %endmacro
177 %macro DIFF_GT2_SSE2 5
178     DIFF_GT2 dqa, %1, %2, %3, %4, %5
179 %endmacro
180
181 ; in: mm0=p1 mm1=p0 mm2=q0 mm3=q1 %1=alpha-1 %2=beta-1
182 ; out: mm5=beta-1, mm7=mask
183 ; clobbers: mm4,mm6
184 %macro LOAD_MASK_MMX 2
185     movd     mm4, %1
186     movd     mm5, %2
187     pshufw   mm4, mm4, 0
188     pshufw   mm5, mm5, 0
189     packuswb mm4, mm4  ; 8x alpha-1
190     packuswb mm5, mm5  ; 8x beta-1
191     DIFF_GT_MMX  mm1, mm2, mm4, mm7, mm6 ; |p0-q0| > alpha-1
192     DIFF_GT_MMX  mm0, mm1, mm5, mm4, mm6 ; |p1-p0| > beta-1
193     por      mm7, mm4
194     DIFF_GT_MMX  mm3, mm2, mm5, mm4, mm6 ; |q1-q0| > beta-1
195     por      mm7, mm4
196     pxor     mm6, mm6
197     pcmpeqb  mm7, mm6
198 %endmacro
199 %macro LOAD_MASK_SSE2 2
200     movd     xmm4, %1
201     movd     xmm5, %2
202     pshuflw  xmm4, xmm4, 0
203     pshuflw  xmm5, xmm5, 0
204     punpcklqdq xmm4, xmm4
205     punpcklqdq xmm5, xmm5
206     packuswb xmm4, xmm4  ; 16x alpha-1
207     packuswb xmm5, xmm5  ; 16x beta-1
208     DIFF_GT_SSE2  xmm1, xmm2, xmm4, xmm7, xmm6 ; |p0-q0| > alpha-1
209     DIFF_GT_SSE2  xmm0, xmm1, xmm5, xmm4, xmm6 ; |p1-p0| > beta-1
210     por      xmm7, xmm4
211     DIFF_GT_SSE2  xmm3, xmm2, xmm5, xmm4, xmm6 ; |q1-q0| > beta-1
212     por      xmm7, xmm4
213     pxor     xmm6, xmm6
214     pcmpeqb  xmm7, xmm6
215 %endmacro
216
217 ; in: mm0=p1 mm1=p0 mm2=q0 mm3=q1 mm7=(tc&mask)
218 ; out: mm1=p0' mm2=q0'
219 ; clobbers: mm0,3-6
220 %macro DEBLOCK_P0_Q0 2
221     mov%1   %2m5, %2m1
222     pxor    %2m5, %2m2           ; p0^q0
223     pand    %2m5, [pb_01 GLOBAL] ; (p0^q0)&1
224     pcmpeqb %2m4, %2m4
225     pxor    %2m3, %2m4
226     pavgb   %2m3, %2m0           ; (p1 - q1 + 256)>>1
227     pavgb   %2m3, [pb_03 GLOBAL] ; (((p1 - q1 + 256)>>1)+4)>>1 = 64+2+(p1-q1)>>2
228     pxor    %2m4, %2m1
229     pavgb   %2m4, %2m2           ; (q0 - p0 + 256)>>1
230     pavgb   %2m3, %2m5
231     paddusb %2m3, %2m4           ; d+128+33
232     mov%1   %2m6, [pb_a1 GLOBAL]
233     psubusb %2m6, %2m3
234     psubusb %2m3, [pb_a1 GLOBAL]
235     pminub  %2m6, %2m7
236     pminub  %2m3, %2m7
237     psubusb %2m1, %2m6
238     psubusb %2m2, %2m3
239     paddusb %2m1, %2m3
240     paddusb %2m2, %2m6
241 %endmacro
242 %macro DEBLOCK_P0_Q0_MMX 0
243     DEBLOCK_P0_Q0 q, m
244 %endmacro
245 %macro DEBLOCK_P0_Q0_SSE2 0
246     DEBLOCK_P0_Q0 dqa, xm
247 %endmacro
248
249 ; in: mm1=p0 mm2=q0
250 ;     %1=p1 %2=q2 %3=[q2] %4=[q1] %5=tc0 %6=tmp
251 ; out: [q1] = clip( (q2+((p0+q0+1)>>1))>>1, q1-tc0, q1+tc0 )
252 ; clobbers: q2, tmp, tc0
253 %macro LUMA_Q1_SSE2 6
254     movdqa  %6, xmm1
255     pavgb   %6, xmm2
256     pavgb   %2, %6             ; avg(p2,avg(p0,q0))
257     pxor    %6, %3
258     pand    %6, [pb_01 GLOBAL] ; (p2^avg(p0,q0))&1
259     psubusb %2, %6             ; (p2+((p0+q0+1)>>1))>>1
260     movdqa  %6, %1
261     psubusb %6, %5
262     paddusb %5, %1
263     pmaxub  %2, %6
264     pminub  %2, %5
265     movdqa  %4, %2
266 %endmacro
267
268
269 SECTION .text
270 ALIGN 16
271 ;-----------------------------------------------------------------------------
272 ;   void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
273 ;-----------------------------------------------------------------------------
274 x264_deblock_v_luma_sse2:
275     ; rdi = pix
276     movsxd rsi, esi ; stride
277     dec    edx      ; alpha-1
278     dec    ecx      ; beta-1
279     movd   xmm8, [r8] ; tc0
280     mov    r8,  rdi
281     sub    r8,  rsi
282     sub    r8,  rsi
283     sub    r8,  rsi ; pix-3*stride
284
285     movdqa  xmm0, [r8+rsi]    ; p1
286     movdqa  xmm1, [r8+2*rsi]  ; p0
287     movdqa  xmm2, [rdi]       ; q0
288     movdqa  xmm3, [rdi+rsi]   ; q1
289     LOAD_MASK_SSE2  edx, ecx
290
291     punpcklbw xmm8, xmm8
292     punpcklbw xmm8, xmm8 ; xmm8 = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]
293     pcmpeqb xmm9, xmm9
294     pcmpeqb xmm9, xmm8
295     pandn   xmm9, xmm7
296     pand    xmm8, xmm9
297
298     movdqa  xmm3, [r8] ; p2
299     DIFF_GT2_SSE2  xmm1, xmm3, xmm5, xmm6, xmm7 ; |p2-p0| > beta-1
300     pand    xmm6, xmm9
301     movdqa  xmm7, xmm8
302     psubb   xmm7, xmm6
303     pand    xmm6, xmm8
304     LUMA_Q1_SSE2  xmm0, xmm3, [r8], [r8+rsi], xmm6, xmm4
305
306     movdqa  xmm4, [rdi+2*rsi] ; q2
307     DIFF_GT2_SSE2  xmm2, xmm4, xmm5, xmm6, xmm3 ; |q2-q0| > beta-1
308     pand    xmm6, xmm9
309     pand    xmm8, xmm6
310     psubb   xmm7, xmm6
311     movdqa  xmm3, [rdi+rsi]
312     LUMA_Q1_SSE2  xmm3, xmm4, [rdi+2*rsi], [rdi+rsi], xmm8, xmm6
313
314     DEBLOCK_P0_Q0_SSE2
315     movdqa  [r8+2*rsi], xmm1
316     movdqa  [rdi], xmm2
317
318     ret
319
320 ALIGN 16
321 ;-----------------------------------------------------------------------------
322 ;   void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
323 ;-----------------------------------------------------------------------------
324 x264_deblock_h_luma_sse2:
325     movsxd r10, esi
326     lea    r11, [r10+r10*2]
327     lea    rax, [rdi-4]
328     lea    r9,  [rdi-4+r11]
329     %define pix_tmp rsp-104 ; 16x6 for the buffer + 8 for x264_deblock_v_luma_sse2's return address
330
331     ; transpose 6x16 -> tmp space
332     TRANSPOSE6x8_MEM  PASS8ROWS(rax, r9, r10, r11), pix_tmp
333     lea    rax, [rax+r10*8]
334     lea    r9,  [r9 +r10*8]
335     TRANSPOSE6x8_MEM  PASS8ROWS(rax, r9, r10, r11), pix_tmp+8
336
337     ; vertical filter
338     ; alpha, beta, tc0 are still in edx, ecx, r8
339     ; don't backup rax, r9, r10, r11 because x264_deblock_v_luma_sse2 doesn't use them
340     lea    rdi, [pix_tmp+0x30]
341     mov    esi, 0x10
342     call   x264_deblock_v_luma_sse2
343
344     ; transpose 16x4 -> original space  (only the middle 4 rows were changed by the filter)
345     add    rax, 2
346     add    r9,  2
347     movq   mm0, [pix_tmp+0x18]
348     movq   mm1, [pix_tmp+0x28]
349     movq   mm2, [pix_tmp+0x38]
350     movq   mm3, [pix_tmp+0x48]
351     TRANSPOSE8x4_STORE  PASS8ROWS(rax, r9, r10, r11)
352
353     shl    r10, 3
354     sub    rax, r10
355     sub    r9,  r10
356     shr    r10, 3
357     movq   mm0, [pix_tmp+0x10]
358     movq   mm1, [pix_tmp+0x20]
359     movq   mm2, [pix_tmp+0x30]
360     movq   mm3, [pix_tmp+0x40]
361     TRANSPOSE8x4_STORE  PASS8ROWS(rax, r9, r10, r11)
362
363     ret
364
365
366 %macro CHROMA_V_START 0
367     ; rdi = pix
368     movsxd rsi, esi ; stride
369     dec    edx      ; alpha-1
370     dec    ecx      ; beta-1
371     mov    rax, rdi
372     sub    rax, rsi
373     sub    rax, rsi
374 %endmacro
375
376 %macro CHROMA_H_START 0
377     movsxd rsi, esi
378     dec    edx
379     dec    ecx
380     sub    rdi, 2
381     lea    r9, [rsi+rsi*2]
382     mov    rax, rdi
383     add    rdi, r9
384 %endmacro
385
386 ALIGN 16
387 ;-----------------------------------------------------------------------------
388 ;   void x264_deblock_v_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
389 ;-----------------------------------------------------------------------------
390 x264_deblock_v_chroma_mmxext:
391     CHROMA_V_START
392
393     movq  mm0, [rax]
394     movq  mm1, [rax+rsi]
395     movq  mm2, [rdi]
396     movq  mm3, [rdi+rsi]
397
398     LOAD_MASK_MMX  edx, ecx
399     movd       mm6, [r8] ; tc0
400     punpcklbw  mm6, mm6
401     pand       mm7, mm6
402     DEBLOCK_P0_Q0_MMX
403
404     movq  [rax+rsi], mm1
405     movq  [rdi], mm2
406     ret
407
408
409 ALIGN 16
410 ;-----------------------------------------------------------------------------
411 ;   void x264_deblock_h_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
412 ;-----------------------------------------------------------------------------
413 x264_deblock_h_chroma_mmxext:
414     CHROMA_H_START
415
416     TRANSPOSE4x8_LOAD  PASS8ROWS(rax, rdi, rsi, r9)
417     movq  [rsp-8], mm0
418     movq  [rsp-16], mm3
419
420     LOAD_MASK_MMX  edx, ecx
421     movd       mm6, [r8] ; tc0
422     punpcklbw  mm6, mm6
423     pand       mm7, mm6
424     DEBLOCK_P0_Q0_MMX
425
426     movq  mm0, [rsp-8]
427     movq  mm3, [rsp-16]
428     TRANSPOSE8x4_STORE PASS8ROWS(rax, rdi, rsi, r9)
429     ret
430
431
432 ; in: %1=p0 %2=p1 %3=q1
433 ; out: p0 = (p0 + q1 + 2*p1 + 2) >> 2
434 %macro CHROMA_INTRA_P0 3
435     movq    mm4, %1
436     pxor    mm4, %3
437     pand    mm4, [pb_01 GLOBAL] ; mm4 = (p0^q1)&1
438     pavgb   %1,  %3
439     psubusb %1,  mm4
440     pavgb   %1,  %2             ; dst = avg(p1, avg(p0,q1) - ((p0^q1)&1))
441 %endmacro
442
443 %macro CHROMA_INTRA_BODY 0
444     LOAD_MASK_MMX edx, ecx
445     movq   mm5, mm1
446     movq   mm6, mm2
447     CHROMA_INTRA_P0  mm1, mm0, mm3
448     CHROMA_INTRA_P0  mm2, mm3, mm0
449     psubb  mm1, mm5
450     psubb  mm2, mm6
451     pand   mm1, mm7
452     pand   mm2, mm7
453     paddb  mm1, mm5
454     paddb  mm2, mm6
455 %endmacro
456
457 ALIGN 16
458 ;-----------------------------------------------------------------------------
459 ;   void x264_deblock_v_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta )
460 ;-----------------------------------------------------------------------------
461 x264_deblock_v_chroma_intra_mmxext:
462     CHROMA_V_START
463
464     movq  mm0, [rax]
465     movq  mm1, [rax+rsi]
466     movq  mm2, [rdi]
467     movq  mm3, [rdi+rsi]
468
469     CHROMA_INTRA_BODY
470
471     movq  [rax+rsi], mm1
472     movq  [rdi], mm2
473     ret
474
475 ALIGN 16
476 ;-----------------------------------------------------------------------------
477 ;   void x264_deblock_h_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta )
478 ;-----------------------------------------------------------------------------
479 x264_deblock_h_chroma_intra_mmxext:
480     CHROMA_H_START
481     TRANSPOSE4x8_LOAD  PASS8ROWS(rax, rdi, rsi, r9)
482     CHROMA_INTRA_BODY
483     TRANSPOSE8x4_STORE PASS8ROWS(rax, rdi, rsi, r9)
484     ret
485