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