1 ;*****************************************************************************
2 ;* x86util.asm: x86 utility macros
3 ;*****************************************************************************
4 ;* Copyright (C) 2008-2015 x264 project
6 ;* Authors: Holger Lubitz <holger@lubitz.org>
7 ;* Loren Merritt <lorenm@u.washington.edu>
9 ;* This program is free software; you can redistribute it and/or modify
10 ;* it under the terms of the GNU General Public License as published by
11 ;* the Free Software Foundation; either version 2 of the License, or
12 ;* (at your option) any later version.
14 ;* This program is distributed in the hope that it will be useful,
15 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;* GNU General Public License for more details.
19 ;* You should have received a copy of the GNU General Public License
20 ;* along with this program; if not, write to the Free Software
21 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
23 ;* This program is also available under a commercial proprietary license.
24 ;* For more information, contact us at licensing@x264.com.
25 ;*****************************************************************************
27 %assign FENC_STRIDE 16
28 %assign FDEC_STRIDE 32
30 %assign SIZEOF_PIXEL 1
31 %assign SIZEOF_DCTCOEF 2
33 %define vpbroadcastdct vpbroadcastw
34 %define vpbroadcastpix vpbroadcastb
36 %assign SIZEOF_PIXEL 2
37 %assign SIZEOF_DCTCOEF 4
39 %define vpbroadcastdct vpbroadcastd
40 %define vpbroadcastpix vpbroadcastw
43 %assign FENC_STRIDEB SIZEOF_PIXEL*FENC_STRIDE
44 %assign FDEC_STRIDEB SIZEOF_PIXEL*FDEC_STRIDE
46 %assign PIXEL_MAX ((1 << BIT_DEPTH)-1)
48 %macro FIX_STRIDES 1-*
60 vperm2i128 m%4, m%2, m%3, q0301 ; punpckh
61 vinserti128 m%2, m%2, xm%3, 1 ; punpckl
62 %elif avx_enabled && mmsize >= 16
63 punpckh%1 m%4, m%2, m%3
74 punpckl%1 m%4, m%2, m%3
75 punpckh%1 m%2, m%2, m%3
79 %macro TRANSPOSE4x4W 5
80 SBUTTERFLY wd, %1, %2, %5
81 SBUTTERFLY wd, %3, %4, %5
82 SBUTTERFLY dq, %1, %3, %5
83 SBUTTERFLY dq, %2, %4, %5
87 %macro TRANSPOSE2x4x4W 5
88 SBUTTERFLY wd, %1, %2, %5
89 SBUTTERFLY wd, %3, %4, %5
90 SBUTTERFLY dq, %1, %3, %5
91 SBUTTERFLY dq, %2, %4, %5
92 SBUTTERFLY qdq, %1, %2, %5
93 SBUTTERFLY qdq, %3, %4, %5
96 %macro TRANSPOSE4x4D 5
97 SBUTTERFLY dq, %1, %2, %5
98 SBUTTERFLY dq, %3, %4, %5
99 SBUTTERFLY qdq, %1, %3, %5
100 SBUTTERFLY qdq, %2, %4, %5
104 %macro TRANSPOSE8x8W 9-11
106 SBUTTERFLY wd, %1, %2, %9
107 SBUTTERFLY wd, %3, %4, %9
108 SBUTTERFLY wd, %5, %6, %9
109 SBUTTERFLY wd, %7, %8, %9
110 SBUTTERFLY dq, %1, %3, %9
111 SBUTTERFLY dq, %2, %4, %9
112 SBUTTERFLY dq, %5, %7, %9
113 SBUTTERFLY dq, %6, %8, %9
114 SBUTTERFLY qdq, %1, %5, %9
115 SBUTTERFLY qdq, %2, %6, %9
116 SBUTTERFLY qdq, %3, %7, %9
117 SBUTTERFLY qdq, %4, %8, %9
121 ; in: m0..m7, unless %11 in which case m6 is in %9
122 ; out: m0..m7, unless %11 in which case m4 is in %10
123 ; spills into %9 and %10
127 SBUTTERFLY wd, %1, %2, %7
130 SBUTTERFLY wd, %3, %4, %2
131 SBUTTERFLY wd, %5, %6, %2
132 SBUTTERFLY wd, %7, %8, %2
133 SBUTTERFLY dq, %1, %3, %2
136 SBUTTERFLY dq, %2, %4, %3
137 SBUTTERFLY dq, %5, %7, %3
138 SBUTTERFLY dq, %6, %8, %3
139 SBUTTERFLY qdq, %1, %5, %3
140 SBUTTERFLY qdq, %2, %6, %3
143 SBUTTERFLY qdq, %3, %7, %2
144 SBUTTERFLY qdq, %4, %8, %2
164 %macro ABSW 2-3 ; dst, src, tmp (tmp used only if dst==src)
167 %elifidn %3, sign ; version for pairing with PSIGNW: modifies src
193 %macro ABSW2 6 ; dst1, dst2, src1, src2, tmp, tmp
242 %if cpuflag(ssse3) && %0 == 4
255 %define PSIGNW PSIGN w,
256 %define PSIGND PSIGN d,
263 movd %1, [%2-3] ;to avoid crossing a cacheline
270 %if cpuflag(avx2) && %3 == 0
273 PSHUFLW %1, %2, (%3)*q1111
282 pshufd %1, %2, (%3)*q1111
284 pshufw %1, %2, (%3)*q0101 + ((%3)+1)*q1010
288 %macro CLIPW 3 ;(dst, min, max)
293 %macro MOVHL 2 ; dst, src
297 punpckhqdq %1, %2, %2
299 pshufd %1, %2, q3232 ; pshufd is slow on some older CPUs, so only use it on more modern ones
301 movhlps %1, %2 ; may cause an int/float domain transition and has a dependency on dst
305 %macro HADDD 2 ; sum junk
308 vextracti128 %2, %1, 1
316 %if cpuflag(xop) && sizeof%1 == 16
319 PSHUFLW %2, %1, q0032
326 %macro HADDW 2 ; reg, tmp
327 %if cpuflag(xop) && sizeof%1 == 16
338 %if cpuflag(xop) && sizeof%1 == 16
349 %if cpuflag(xop) && sizeof%1 == 16
359 %macro PALIGNR 4-5 ; [dst,] src1, src2, imm, tmp
360 ; AVX2 version uses a precalculated extra input that
361 ; can be re-used across calls
363 ; %3 = abcdefgh ijklmnop (lower address)
364 ; %2 = ABCDEFGH IJKLMNOP (higher address)
365 ; vperm2i128 %5, %2, %3, q0003 ; %5 = ijklmnop ABCDEFGH
367 palignr %1, %5, %3, %4 ; %1 = bcdefghi jklmnopA
369 palignr %1, %2, %5, %4-16 ; %1 = pABCDEFG HIJKLMNO
373 palignr %1, %2, %3, %4
389 psllq %%dst, (8-%3)*8
407 ; shift a mmxreg by n bytes, or a xmmreg by 2*n bytes
408 ; values shifted in are undefined
410 %define PSLLPIX PSXLPIX l, -1, ;dst, src, shift
411 %define PSRLPIX PSXLPIX r, 1, ;dst, src, shift
417 pshufw %3, %4, (q3210<<8>>(8+%2*%5))&0xff
424 %macro DEINTB 5 ; mask, reg1, mask, reg2, optional src to fill masks from
426 pand m%3, m%5, m%4 ; src .. y6 .. y4
427 pand m%1, m%5, m%2 ; dst .. y6 .. y4
430 pand m%3, m%1, m%4 ; src .. y6 .. y4
431 pand m%1, m%1, m%2 ; dst .. y6 .. y4
433 psrlw m%2, 8 ; dst .. y7 .. y5
434 psrlw m%4, 8 ; src .. y7 .. y5
453 %macro SUMSUB_BADC 5-6
455 SUMSUB_BA %1, %2, %3, %6
456 SUMSUB_BA %1, %4, %5, %6
467 %macro HADAMARD4_V 4+
468 SUMSUB_BADC w, %1, %2, %3, %4
469 SUMSUB_BADC w, %1, %3, %2, %4
472 %macro HADAMARD8_V 8+
473 SUMSUB_BADC w, %1, %2, %3, %4
474 SUMSUB_BADC w, %5, %6, %7, %8
475 SUMSUB_BADC w, %1, %3, %2, %4
476 SUMSUB_BADC w, %5, %7, %6, %8
477 SUMSUB_BADC w, %1, %5, %2, %6
478 SUMSUB_BADC w, %3, %7, %4, %8
481 %macro TRANS_SSE2 5-6
483 ; %1: transpose width (d/q) - use SBUTTERFLY qdq for dq
484 ; %2: ord/unord (for compat with sse4, unused)
488 %define mask [mask_10]
491 %define mask [mask_1100]
494 %if %0==6 ; less dependency if we have two tmp
495 mova m%5, mask ; ff00
497 psll%1 m%4, shift ; x4..
499 pandn m%5, m%3 ; ..x0
500 psrl%1 m%3, shift ; ..x1
503 %else ; more dependency, one insn less. sometimes faster, sometimes not
505 psll%1 m%4, shift ; x4..
506 pxor m%4, m%3 ; (x4^x1)x0
507 pand m%4, mask ; (x4^x1)..
509 psrl%1 m%4, shift ; ..(x1^x4)
515 %macro TRANS_SSE4 5-6 ; see above
519 pblendw m%5, m%4, q2222
521 pblendw m%4, m%3, q1111
525 pblendw m%5, m%3, m%4, q2222
529 pblendw m%3, m%4, q2222
536 shufps m%5, m%3, m%4, q3131
537 shufps m%3, m%3, m%4, q2020
544 vpperm m%5, m%3, m%4, [transd_shuf1]
545 vpperm m%3, m%3, m%4, [transd_shuf2]
547 shufps m%5, m%3, m%4, q3131
548 shufps m%3, m%4, q2020
554 ; %1=distance in words (0 for vertical pass, 1/2/4 for horizontal passes)
555 ; %2=sumsub/max/amax (sum and diff / maximum / maximum of absolutes)
558 %if %1!=0 ; have to reorder stuff for horizontal op
561 ; sumsub needs order because a-b != b-a unless a=b
564 ; if we just max, order doesn't matter (allows pblendw+or in sse4)
567 TRANS d, ORDER, %3, %4, %5, %6
570 SBUTTERFLY dq, %3, %4, %5
572 TRANS q, ORDER, %3, %4, %5, %6
575 SBUTTERFLY qdq, %3, %4, %5
577 SBUTTERFLY dqqq, %3, %4, %5
581 SUMSUB_BA w, %3, %4, %5
585 ABSW2 m%3, m%4, m%3, m%4, m%5, m%6
596 %macro HADAMARD2_2D 6-7 sumsub
597 HADAMARD 0, sumsub, %1, %2, %5
598 HADAMARD 0, sumsub, %3, %4, %5
599 SBUTTERFLY %6, %1, %2, %5
601 HADAMARD 0, amax, %1, %2, %5, %7
603 HADAMARD 0, %7, %1, %2, %5
605 SBUTTERFLY %6, %3, %4, %5
607 HADAMARD 0, amax, %3, %4, %5, %7
609 HADAMARD 0, %7, %3, %4, %5
613 %macro HADAMARD4_2D 5-6 sumsub
614 HADAMARD2_2D %1, %2, %3, %4, %5, wd
615 HADAMARD2_2D %1, %3, %2, %4, %5, dq, %6
619 %macro HADAMARD4_2D_SSE 5-6 sumsub
620 HADAMARD 0, sumsub, %1, %2, %5 ; 1st V row 0 + 1
621 HADAMARD 0, sumsub, %3, %4, %5 ; 1st V row 2 + 3
622 SBUTTERFLY wd, %1, %2, %5 ; %1: m0 1+0 %2: m1 1+0
623 SBUTTERFLY wd, %3, %4, %5 ; %3: m0 3+2 %4: m1 3+2
624 HADAMARD2_2D %1, %3, %2, %4, %5, dq
625 SBUTTERFLY qdq, %1, %2, %5
626 HADAMARD 0, %6, %1, %2, %5 ; 2nd H m1/m0 row 0+1
627 SBUTTERFLY qdq, %3, %4, %5
628 HADAMARD 0, %6, %3, %4, %5 ; 2nd H m1/m0 row 2+3
631 %macro HADAMARD8_2D 9-10 sumsub
632 HADAMARD2_2D %1, %2, %3, %4, %9, wd
633 HADAMARD2_2D %5, %6, %7, %8, %9, wd
634 HADAMARD2_2D %1, %3, %2, %4, %9, dq
635 HADAMARD2_2D %5, %7, %6, %8, %9, dq
636 HADAMARD2_2D %1, %5, %3, %7, %9, qdq, %10
637 HADAMARD2_2D %2, %6, %4, %8, %9, qdq, %10
644 ; doesn't include the "pmaddubsw hmul_8p" pass
645 %macro HADAMARD8_2D_HMUL 10
646 HADAMARD4_V %1, %2, %3, %4, %9
647 HADAMARD4_V %5, %6, %7, %8, %9
648 SUMSUB_BADC w, %1, %5, %2, %6, %9
649 HADAMARD 2, sumsub, %1, %5, %9, %10
650 HADAMARD 2, sumsub, %2, %6, %9, %10
651 SUMSUB_BADC w, %3, %7, %4, %8, %9
652 HADAMARD 2, sumsub, %3, %7, %9, %10
653 HADAMARD 2, sumsub, %4, %8, %9, %10
654 HADAMARD 1, amax, %1, %5, %9, %10
655 HADAMARD 1, amax, %2, %6, %9, %5
656 HADAMARD 1, amax, %3, %7, %9, %5
657 HADAMARD 1, amax, %4, %8, %9, %5
662 pmacs%1%1 m%4, m%3, [p%1_m2], m%2
663 pmacs%1%1 m%2, m%2, [p%1_2], m%3
680 psra%1 m%5, m%2, 1 ; %3: %3>>1
681 psra%1 m%4, m%3, 1 ; %2: %2>>1
682 padd%1 m%4, m%2 ; %3: %3>>1+%2
683 psub%1 m%5, m%3 ; %2: %2>>1-%3
689 psra%1 m%3, 1 ; %3: %3>>1
690 psra%1 m%2, 1 ; %2: %2>>1
691 padd%1 m%3, %5 ; %3: %3>>1+%2
692 psub%1 m%2, %4 ; %2: %2>>1-%3
698 SUMSUB_BADC w, %4, %1, %3, %2, %5
699 SUMSUB_BA w, %3, %4, %5
700 SUMSUB2_AB w, %1, %2, %5
701 SWAP %1, %3, %4, %5, %2
703 SUMSUB_BADC w, %4, %1, %3, %2
706 SUMSUB2_AB w, %1, [%5], %2
713 SUMSUBD2_AB %1, %3, %5, %7, %6
714 ; %3: %3>>1-%5 %5: %3+%5>>1
715 SUMSUB_BA %1, %4, %2, %7
716 ; %4: %2+%4 %2: %2-%4
717 SUMSUB_BADC %1, %5, %4, %3, %2, %7
718 ; %5: %2+%4 + (%3+%5>>1)
719 ; %4: %2+%4 - (%3+%5>>1)
720 ; %3: %2-%4 + (%3>>1-%5)
721 ; %2: %2-%4 - (%3>>1-%5)
724 SUMSUBD2_AB %1, %3, %5, [%6], [%6+16]
726 SUMSUBD2_AB %1, %3, %5, [%6], [%6+32]
729 SUMSUB_BADC %1, %5, %4, %3, %2
732 ; %2: %2+%4 + (%3+%5>>1) row0
733 ; %3: %2-%4 + (%3>>1-%5) row1
734 ; %4: %2-%4 - (%3>>1-%5) row2
735 ; %5: %2+%4 - (%3+%5>>1) row3
739 %macro LOAD_DIFF 5-6 1
749 %else ; !HIGH_BIT_DEPTH
763 %endif ; HIGH_BIT_DEPTH
766 %macro LOAD_DIFF8x4 8 ; 4x dst, 1x tmp, 1x mul, 2x ptr
767 %if BIT_DEPTH == 8 && cpuflag(ssse3)
768 movh m%2, [%8+%1*FDEC_STRIDE]
769 movh m%1, [%7+%1*FENC_STRIDE]
771 movh m%3, [%8+%2*FDEC_STRIDE]
772 movh m%2, [%7+%2*FENC_STRIDE]
774 movh m%4, [%8+%3*FDEC_STRIDE]
775 movh m%3, [%7+%3*FENC_STRIDE]
777 movh m%5, [%8+%4*FDEC_STRIDE]
778 movh m%4, [%7+%4*FENC_STRIDE]
785 LOAD_DIFF m%1, m%5, m%6, [%7+%1*FENC_STRIDEB], [%8+%1*FDEC_STRIDEB]
786 LOAD_DIFF m%2, m%5, m%6, [%7+%2*FENC_STRIDEB], [%8+%2*FDEC_STRIDEB]
787 LOAD_DIFF m%3, m%5, m%6, [%7+%3*FENC_STRIDEB], [%8+%3*FDEC_STRIDEB]
788 LOAD_DIFF m%4, m%5, m%6, [%7+%4*FENC_STRIDEB], [%8+%4*FDEC_STRIDEB]
797 movhps [%5+%6+32], m%1
798 movhps [%5+%6+40], m%2
799 movhps [%5+%6+48], m%3
800 movhps [%5+%6+56], m%4
804 movhps [r0-4*FDEC_STRIDE], %1
805 movh [r0-3*FDEC_STRIDE], %1
806 movhps [r0-2*FDEC_STRIDE], %2
807 movh [r0-1*FDEC_STRIDE], %2
808 movhps [r0+0*FDEC_STRIDE], %3
809 movh [r0+1*FDEC_STRIDE], %3
810 movhps [r0+2*FDEC_STRIDE], %4
811 movh [r0+3*FDEC_STRIDE], %4
814 %macro LOAD_DIFF_8x4P 7-11 r0,r2,0,1 ; 4x dest, 2x temp, 2x pointer, increment, aligned?
815 LOAD_DIFF m%1, m%5, m%7, [%8], [%9], %11
816 LOAD_DIFF m%2, m%6, m%7, [%8+r1], [%9+r3], %11
817 LOAD_DIFF m%3, m%5, m%7, [%8+2*r1], [%9+2*r3], %11
818 LOAD_DIFF m%4, m%6, m%7, [%8+r4], [%9+r5], %11
825 ; 2xdst, 2xtmp, 2xsrcrow
826 %macro LOAD_DIFF16x2_AVX2 6
827 pmovzxbw m%1, [r1+%5*FENC_STRIDE]
828 pmovzxbw m%2, [r1+%6*FENC_STRIDE]
829 pmovzxbw m%3, [r2+(%5-4)*FDEC_STRIDE]
830 pmovzxbw m%4, [r2+(%6-4)*FDEC_STRIDE]
847 ; (high depth) in: %1, %2, min to clip, max to clip, mem128
848 ; in: %1, tmp, %3, mem64
849 %macro STORE_DIFF 4-5
867 %macro SHUFFLE_MASK_W 8
879 ; instruction, accum, input, iteration (zero to swap, nonzero to add)