1 ;*****************************************************************************
\r
2 ;* deblock-a.asm: h264 encoder library
\r
3 ;*****************************************************************************
\r
4 ;* Copyright (C) 2005-2008 x264 project
\r
6 ;* Authors: Loren Merritt <lorenm@u.washington.edu>
\r
8 ;* This program is free software; you can redistribute it and/or modify
\r
9 ;* it under the terms of the GNU General Public License as published by
\r
10 ;* the Free Software Foundation; either version 2 of the License, or
\r
11 ;* (at your option) any later version.
\r
13 ;* This program is distributed in the hope that it will be useful,
\r
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 ;* GNU General Public License for more details.
\r
18 ;* You should have received a copy of the GNU General Public License
\r
19 ;* along with this program; if not, write to the Free Software
\r
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
\r
21 ;*****************************************************************************
\r
23 %include "x86inc.asm"
\r
26 pb_00: times 16 db 0x00
\r
27 pb_01: times 16 db 0x01
\r
28 pb_03: times 16 db 0x03
\r
29 pb_a1: times 16 db 0xa1
\r
33 ; expands to [base],...,[base+7*stride]
\r
34 %define PASS8ROWS(base, base3, stride, stride3) \
\r
35 [base], [base+stride], [base+stride*2], [base3], \
\r
36 [base3+stride], [base3+stride*2], [base3+stride3], [base3+stride*4]
\r
38 ; in: 8 rows of 4 bytes in %1..%8
\r
39 ; out: 4 rows of 8 bytes in m0..m3
\r
40 %macro TRANSPOSE4x8_LOAD 8
\r
69 ; in: 4 rows of 8 bytes in m0..m3
\r
70 ; out: 8 rows of 4 bytes in %1..%8
\r
71 %macro TRANSPOSE8x4_STORE 8
\r
105 %macro SBUTTERFLY 4
\r
111 ; in: 8 rows of 8 (only the middle 6 pels are used) in %1..%8
\r
112 ; out: 6 rows of 8 in [%9+0*16] .. [%9+5*16]
\r
113 %macro TRANSPOSE6x8_MEM 9
\r
121 SBUTTERFLY bw, m0, m1, m7
\r
122 SBUTTERFLY bw, m2, m3, m1
\r
123 SBUTTERFLY bw, m4, m5, m3
\r
125 SBUTTERFLY bw, m6, %8, m5
\r
126 SBUTTERFLY wd, m0, m2, m1
\r
127 SBUTTERFLY wd, m4, m6, m2
\r
130 SBUTTERFLY wd, m7, [%9+0x10], m6
\r
131 SBUTTERFLY wd, m3, m5, m4
\r
132 SBUTTERFLY dq, m7, m3, m0
\r
133 SBUTTERFLY dq, m1, m2, m5
\r
142 ; in: 8 rows of 8 in %1..%8
\r
143 ; out: 8 rows of 8 in %9..%16
\r
144 %macro TRANSPOSE8x8_MEM 16
\r
152 SBUTTERFLY bw, m0, m1, m7
\r
153 SBUTTERFLY bw, m2, m3, m1
\r
154 SBUTTERFLY bw, m4, m5, m3
\r
155 SBUTTERFLY bw, m6, %8, m5
\r
157 SBUTTERFLY wd, m0, m2, m3
\r
158 SBUTTERFLY wd, m4, m6, m2
\r
159 SBUTTERFLY wd, m7, m1, m6
\r
162 SBUTTERFLY wd, m2, m5, m1
\r
163 SBUTTERFLY dq, m0, m4, m5
\r
164 SBUTTERFLY dq, m7, m2, m4
\r
169 SBUTTERFLY dq, m3, %11, m0
\r
170 SBUTTERFLY dq, m6, m1, m5
\r
177 ; out: %4 = |%1-%2|>%3
\r
188 ; out: %4 = |%1-%2|>%3
\r
209 ; in: m0=p1 m1=p0 m2=q0 m3=q1 %1=alpha-1 %2=beta-1
\r
210 ; out: m5=beta-1, m7=mask, %3=alpha-1
\r
212 %macro LOAD_MASK 2-3
\r
217 packuswb m4, m4 ; 16x alpha-1
\r
218 packuswb m5, m5 ; 16x beta-1
\r
222 DIFF_GT m1, m2, m4, m7, m6 ; |p0-q0| > alpha-1
\r
223 DIFF_GT m0, m1, m5, m4, m6 ; |p1-p0| > beta-1
\r
225 DIFF_GT m3, m2, m5, m4, m6 ; |q1-q0| > beta-1
\r
231 ; in: m0=p1 m1=p0 m2=q0 m3=q1 m7=(tc&mask)
\r
232 ; out: m1=p0' m2=q0'
\r
234 %macro DEBLOCK_P0_Q0 0
\r
236 pxor m5, m2 ; p0^q0
\r
237 pand m5, [pb_01 GLOBAL] ; (p0^q0)&1
\r
240 pavgb m3, m0 ; (p1 - q1 + 256)>>1
\r
241 pavgb m3, [pb_03 GLOBAL] ; (((p1 - q1 + 256)>>1)+4)>>1 = 64+2+(p1-q1)>>2
\r
243 pavgb m4, m2 ; (q0 - p0 + 256)>>1
\r
245 paddusb m3, m4 ; d+128+33
\r
246 mova m6, [pb_a1 GLOBAL]
\r
248 psubusb m3, [pb_a1 GLOBAL]
\r
258 ; %1=p1 %2=q2 %3=[q2] %4=[q1] %5=tc0 %6=tmp
\r
259 ; out: [q1] = clip( (q2+((p0+q0+1)>>1))>>1, q1-tc0, q1+tc0 )
\r
260 ; clobbers: q2, tmp, tc0
\r
264 pavgb %2, %6 ; avg(p2,avg(p0,q0))
\r
266 pand %6, [pb_01 GLOBAL] ; (p2^avg(p0,q0))&1
\r
267 psubusb %2, %6 ; (p2+((p0+q0+1)>>1))>>1
\r
277 ;-----------------------------------------------------------------------------
\r
278 ; void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
\r
279 ;-----------------------------------------------------------------------------
\r
281 cglobal x264_deblock_v_luma_sse2
\r
282 movd m8, [r4] ; tc0
\r
287 add r4, r0 ; pix-3*stride
\r
289 mova m0, [r4+r1] ; p1
\r
290 mova m1, [r4+2*r1] ; p0
\r
292 mova m3, [r0+r1] ; q1
\r
296 punpcklbw m8, m8 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]
\r
302 movdqa m3, [r4] ; p2
\r
303 DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1
\r
308 LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4
\r
310 movdqa m4, [r0+2*r1] ; q2
\r
311 DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1
\r
316 LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m8, m6
\r
323 ;-----------------------------------------------------------------------------
\r
324 ; void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
\r
325 ;-----------------------------------------------------------------------------
\r
327 cglobal x264_deblock_h_luma_sse2
\r
329 lea r11, [r10+r10*2]
\r
333 %define pix_tmp rsp
\r
335 ; transpose 6x16 -> tmp space
\r
336 TRANSPOSE6x8_MEM PASS8ROWS(rax, r9, r10, r11), pix_tmp
\r
337 lea rax, [rax+r10*8]
\r
338 lea r9, [r9 +r10*8]
\r
339 TRANSPOSE6x8_MEM PASS8ROWS(rax, r9, r10, r11), pix_tmp+8
\r
342 ; alpha, beta, tc0 are still in r2d, r3d, r4
\r
343 ; don't backup rax, r9, r10, r11 because x264_deblock_v_luma_sse2 doesn't use them
\r
344 lea r0, [pix_tmp+0x30]
\r
346 call x264_deblock_v_luma_sse2
\r
348 ; transpose 16x4 -> original space (only the middle 4 rows were changed by the filter)
\r
351 movq m0, [pix_tmp+0x18]
\r
352 movq m1, [pix_tmp+0x28]
\r
353 movq m2, [pix_tmp+0x38]
\r
354 movq m3, [pix_tmp+0x48]
\r
355 TRANSPOSE8x4_STORE PASS8ROWS(rax, r9, r10, r11)
\r
361 movq m0, [pix_tmp+0x10]
\r
362 movq m1, [pix_tmp+0x20]
\r
363 movq m2, [pix_tmp+0x30]
\r
364 movq m3, [pix_tmp+0x40]
\r
365 TRANSPOSE8x4_STORE PASS8ROWS(rax, r9, r10, r11)
\r
372 %macro DEBLOCK_LUMA 3
\r
373 ;-----------------------------------------------------------------------------
\r
374 ; void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
\r
375 ;-----------------------------------------------------------------------------
\r
376 cglobal x264_deblock_%2_luma_%1, 5,5
\r
381 add r4, r0 ; pix-3*stride
\r
382 %assign pad 2*%3+12-(stack_offset&15)
\r
385 mova m0, [r4+r1] ; p1
\r
386 mova m1, [r4+2*r1] ; p0
\r
388 mova m3, [r0+r1] ; q1
\r
392 movd m4, [r3] ; tc0
\r
394 punpcklbw m4, m4 ; tc = 4x tc0[3], 4x tc0[2], 4x tc0[1], 4x tc0[0]
\r
395 mova [esp+%3], m4 ; tc
\r
399 mova [esp], m4 ; mask
\r
402 DIFF_GT2 m1, m3, m5, m6, m7 ; |p2-p0| > beta-1
\r
404 pand m4, [esp+%3] ; tc
\r
408 LUMA_Q1 m0, m3, [r4], [r4+r1], m6, m4
\r
410 mova m4, [r0+2*r1] ; q2
\r
411 DIFF_GT2 m2, m4, m5, m6, m3 ; |q2-q0| > beta-1
\r
412 mova m5, [esp] ; mask
\r
414 mova m5, [esp+%3] ; tc
\r
418 LUMA_Q1 m3, m4, [r0+2*r1], [r0+r1], m5, m6
\r
426 ;-----------------------------------------------------------------------------
\r
427 ; void x264_deblock_h_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
\r
428 ;-----------------------------------------------------------------------------
\r
430 cglobal x264_deblock_h_luma_%1, 0,5
\r
436 %assign pad 0x78-(stack_offset&15)
\r
438 %define pix_tmp esp+12
\r
440 ; transpose 6x16 -> tmp space
\r
441 TRANSPOSE6x8_MEM PASS8ROWS(r0, r1, r3, r4), pix_tmp
\r
444 TRANSPOSE6x8_MEM PASS8ROWS(r0, r1, r3, r4), pix_tmp+8
\r
447 lea r0, [pix_tmp+0x30]
\r
453 call x264_deblock_%2_luma_%1
\r
455 add dword [esp ], 8 ; pix_tmp+0x38
\r
456 add dword [esp+16], 2 ; tc0+2
\r
457 call x264_deblock_%2_luma_%1
\r
461 ; transpose 16x4 -> original space (only the middle 4 rows were changed by the filter)
\r
466 movq m0, [pix_tmp+0x10]
\r
467 movq m1, [pix_tmp+0x20]
\r
468 movq m2, [pix_tmp+0x30]
\r
469 movq m3, [pix_tmp+0x40]
\r
470 TRANSPOSE8x4_STORE PASS8ROWS(r0, r1, r3, r4)
\r
474 movq m0, [pix_tmp+0x18]
\r
475 movq m1, [pix_tmp+0x28]
\r
476 movq m2, [pix_tmp+0x38]
\r
477 movq m3, [pix_tmp+0x48]
\r
478 TRANSPOSE8x4_STORE PASS8ROWS(r0, r1, r3, r4)
\r
482 %endmacro ; DEBLOCK_LUMA
\r
485 DEBLOCK_LUMA sse2, v, 16
\r
491 %macro LUMA_INTRA_P012 4 ; p0..p3 in memory
\r
496 pavgb t0, t1 ; ((p2+p1+1)/2 + (p0+q0+1)/2 + 1)/2
\r
509 psubb t0, t2 ; p1' = (p2+p1+p0+q0+2)/4;
\r
516 psubb t3, t2 ; p2+2*p1+2*p0+2*q0+q1
\r
520 pavgb t1, t5 ; (((p2+q1)/2 + p1+1)/2 + (p0+q0+1)/2 + 1)/2
\r
525 psubb t1, t3 ; p0'a = (p2+2*p1+2*p0+2*q0+q1+4)/8
\r
533 pavgb t2, p1 ; p0'b = (2*p1+p0+q0+2)/4
\r
541 mova %1, t1 ; store p0
\r
547 pavgb t1, t0 ; (p3+p2+1)/2 + (p2+p1+p0+q0+2)/4
\r
549 paddb t2, t4 ; 2*p3+3*p2+p1+p0+q0
\r
554 psubb t1, t2 ; p2' = (2*p3+3*p2+p1+p0+q0+4)/8
\r
562 mova %2, t0 ; store p1
\r
563 mova %3, t1 ; store p2
\r
566 %macro LUMA_INTRA_SWAP_PQ 0
\r
572 %define mask1p mask1q
\r
575 %macro DEBLOCK_LUMA_INTRA 2
\r
591 %define mask1q [rsp-24]
\r
595 %define spill(x) [esp+16*x+((stack_offset+4)&15)]
\r
597 %define q2 [r0+2*r1]
\r
598 %define t4 spill(0)
\r
599 %define t5 spill(1)
\r
600 %define mask0 spill(2)
\r
601 %define mask1p spill(3)
\r
602 %define mask1q spill(4)
\r
603 %define mpb_00 [pb_00 GLOBAL]
\r
604 %define mpb_01 [pb_01 GLOBAL]
\r
607 ;-----------------------------------------------------------------------------
\r
608 ; void x264_deblock_v_luma_intra_sse2( uint8_t *pix, int stride, int alpha, int beta )
\r
609 ;-----------------------------------------------------------------------------
\r
610 cglobal x264_deblock_%2_luma_intra_%1, 4,6
\r
611 %ifndef ARCH_X86_64
\r
615 lea r5, [r1*3] ; 3*stride
\r
621 add r4, r0 ; pix-4*stride
\r
627 pxor mpb_00, mpb_00
\r
628 mova mpb_01, [pb_01 GLOBAL]
\r
629 LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0
\r
630 SWAP 7, 12 ; m12=mask0
\r
632 pavgb t5, mpb_01 ; alpha/4+1
\r
634 movdqa q2, [r0+2*r1]
\r
635 DIFF_GT2 p0, q0, t5, t0, t3 ; t0 = |p0-q0| > alpha/4+1
\r
636 DIFF_GT2 p0, p2, m5, t2, t5 ; mask1 = |p2-p0| > beta-1
\r
637 DIFF_GT2 q0, q2, m5, t4, t5 ; t4 = |q2-q0| > beta-1
\r
644 LOAD_MASK r2d, r3d, t5 ; m5=beta-1, t5=alpha-1, m7=mask0
\r
647 pavgb m4, [pb_00 GLOBAL]
\r
648 pavgb m4, [pb_01 GLOBAL] ; alpha/4+1
\r
649 DIFF_GT2 p0, q0, m4, m6, m7 ; m6 = |p0-q0| > alpha/4+1
\r
651 DIFF_GT2 p0, p2, m5, m4, m7 ; m4 = |p2-p0| > beta-1
\r
654 DIFF_GT2 q0, q2, m5, m4, m7 ; m4 = |q2-q0| > beta-1
\r
658 LUMA_INTRA_P012 [r4+r5], [r4+2*r1], [r4+r1], [r4]
\r
660 LUMA_INTRA_P012 [r0], [r0+r1], [r0+2*r1], [r0+r5]
\r
662 %ifndef ARCH_X86_64
\r
669 ;-----------------------------------------------------------------------------
\r
670 ; void x264_deblock_h_luma_intra_sse2( uint8_t *pix, int stride, int alpha, int beta )
\r
671 ;-----------------------------------------------------------------------------
\r
672 cglobal x264_deblock_h_luma_intra_%1
\r
678 %define pix_tmp rsp
\r
680 ; transpose 8x16 -> tmp space
\r
681 TRANSPOSE8x8_MEM PASS8ROWS(rax, r9, r10, r11), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)
\r
682 lea rax, [rax+r10*8]
\r
684 TRANSPOSE8x8_MEM PASS8ROWS(rax, r9, r10, r11), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)
\r
686 lea r0, [pix_tmp+0x40]
\r
688 call x264_deblock_v_luma_intra_%1
\r
690 ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)
\r
692 TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(rax, r9, r10, r11)
\r
697 TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(rax, r9, r10, r11)
\r
701 cglobal x264_deblock_h_luma_intra_%1, 2,4
\r
705 %assign pad 0x8c-(stack_offset&15)
\r
707 %define pix_tmp rsp
\r
709 ; transpose 8x16 -> tmp space
\r
710 TRANSPOSE8x8_MEM PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30)
\r
713 TRANSPOSE8x8_MEM PASS8ROWS(r0, r2, r1, r3), PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30)
\r
715 lea r0, [pix_tmp+0x40]
\r
720 call x264_deblock_%2_luma_intra_%1
\r
722 add dword [rsp], 8 ; pix_tmp+8
\r
723 call x264_deblock_%2_luma_intra_%1
\r
732 ; transpose 16x6 -> original space (but we can't write only 6 pixels, so really 16x8)
\r
733 TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp, pix_tmp+0x30, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)
\r
736 TRANSPOSE8x8_MEM PASS8ROWS(pix_tmp+8, pix_tmp+0x38, 0x10, 0x30), PASS8ROWS(r0, r2, r1, r3)
\r
739 %endif ; ARCH_X86_64
\r
740 %endmacro ; DEBLOCK_LUMA_INTRA
\r
743 DEBLOCK_LUMA_INTRA sse2, v
\r
744 %ifndef ARCH_X86_64
\r
746 DEBLOCK_LUMA_INTRA mmxext, v8
\r