]> git.sesse.net Git - x264/blobdiff - common/x86/x86util.asm
Bump dates to 2016
[x264] / common / x86 / x86util.asm
index d4eec429d31b8670255994d156344e737ab3afc0..57d4356e23b92c06ebd968711d8755e27b54199e 100644 (file)
@@ -1,7 +1,10 @@
 ;*****************************************************************************
-;* x86inc.asm
+;* x86util.asm: x86 utility macros
 ;*****************************************************************************
-;* Copyright (C) 2008 Loren Merritt <lorenm@u.washington.edu>
+;* Copyright (C) 2008-2016 x264 project
+;*
+;* Authors: Holger Lubitz <holger@lubitz.org>
+;*          Loren Merritt <lorenm@u.washington.edu>
 ;*
 ;* This program is free software; you can redistribute it and/or modify
 ;* it under the terms of the GNU General Public License as published by
 ;* You should have received a copy of the GNU General Public License
 ;* along with this program; if not, write to the Free Software
 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
+;*
+;* This program is also available under a commercial proprietary license.
+;* For more information, contact us at licensing@x264.com.
 ;*****************************************************************************
 
+%assign FENC_STRIDE 16
+%assign FDEC_STRIDE 32
+
+%assign SIZEOF_PIXEL 1
+%assign SIZEOF_DCTCOEF 2
+%define pixel byte
+%define vpbroadcastdct vpbroadcastw
+%define vpbroadcastpix vpbroadcastb
+%if HIGH_BIT_DEPTH
+    %assign SIZEOF_PIXEL 2
+    %assign SIZEOF_DCTCOEF 4
+    %define pixel word
+    %define vpbroadcastdct vpbroadcastd
+    %define vpbroadcastpix vpbroadcastw
+%endif
+
+%assign FENC_STRIDEB SIZEOF_PIXEL*FENC_STRIDE
+%assign FDEC_STRIDEB SIZEOF_PIXEL*FDEC_STRIDE
+
+%assign PIXEL_MAX ((1 << BIT_DEPTH)-1)
+
+%macro FIX_STRIDES 1-*
+%if HIGH_BIT_DEPTH
+%rep %0
+    add %1, %1
+    %rotate 1
+%endrep
+%endif
+%endmacro
+
+
 %macro SBUTTERFLY 4
+%ifidn %1, dqqq
+    vperm2i128  m%4, m%2, m%3, q0301 ; punpckh
+    vinserti128 m%2, m%2, xm%3, 1    ; punpckl
+%elif avx_enabled && mmsize >= 16
+    punpckh%1 m%4, m%2, m%3
+    punpckl%1 m%2, m%3
+%else
     mova      m%4, m%2
     punpckl%1 m%2, m%3
     punpckh%1 m%4, m%3
+%endif
     SWAP %3, %4
 %endmacro
 
+%macro SBUTTERFLY2 4
+    punpckl%1 m%4, m%2, m%3
+    punpckh%1 m%2, m%2, m%3
+    SWAP %2, %4, %3
+%endmacro
+
 %macro TRANSPOSE4x4W 5
     SBUTTERFLY wd, %1, %2, %5
     SBUTTERFLY wd, %3, %4, %5
 %endmacro
 
 %macro TRANSPOSE8x8W 9-11
-%ifdef ARCH_X86_64
+%if ARCH_X86_64
     SBUTTERFLY wd,  %1, %2, %9
     SBUTTERFLY wd,  %3, %4, %9
     SBUTTERFLY wd,  %5, %6, %9
     SBUTTERFLY qdq, %4, %8, %2
     SWAP %2, %5
     SWAP %4, %7
-%if 0<11
+%if %0<11
     movdqa m%5, %10
 %endif
 %endif
 %endmacro
 
-%macro ABS1_MMX 2    ; a, tmp
-    pxor    %2, %2
-    psubw   %2, %1
-    pmaxsw  %1, %2
+%macro WIDEN_SXWD 2
+    punpckhwd m%2, m%1
+    psrad     m%2, 16
+%if cpuflag(sse4)
+    pmovsxwd  m%1, m%1
+%else
+    punpcklwd m%1, m%1
+    psrad     m%1, 16
+%endif
 %endmacro
 
-%macro ABS2_MMX 4    ; a, b, tmp0, tmp1
+%macro ABSW 2-3 ; dst, src, tmp (tmp used only if dst==src)
+%if cpuflag(ssse3)
+    pabsw   %1, %2
+%elifidn %3, sign ; version for pairing with PSIGNW: modifies src
+    pxor    %1, %1
+    pcmpgtw %1, %2
+    pxor    %2, %1
+    psubw   %2, %1
+    SWAP    %1, %2
+%elifidn %1, %2
+    pxor    %3, %3
+    psubw   %3, %1
+    pmaxsw  %1, %3
+%elifid %2
+    pxor    %1, %1
+    psubw   %1, %2
+    pmaxsw  %1, %2
+%elif %0 == 2
+    pxor    %1, %1
+    psubw   %1, %2
+    pmaxsw  %1, %2
+%else
+    mova    %1, %2
     pxor    %3, %3
-    pxor    %4, %4
     psubw   %3, %1
-    psubw   %4, %2
+    pmaxsw  %1, %3
+%endif
+%endmacro
+
+%macro ABSW2 6 ; dst1, dst2, src1, src2, tmp, tmp
+%if cpuflag(ssse3)
+    pabsw   %1, %3
+    pabsw   %2, %4
+%elifidn %1, %3
+    pxor    %5, %5
+    pxor    %6, %6
+    psubw   %5, %1
+    psubw   %6, %2
+    pmaxsw  %1, %5
+    pmaxsw  %2, %6
+%else
+    pxor    %1, %1
+    pxor    %2, %2
+    psubw   %1, %3
+    psubw   %2, %4
     pmaxsw  %1, %3
     pmaxsw  %2, %4
+%endif
+%endmacro
+
+%macro ABSB 2
+%if cpuflag(ssse3)
+    pabsb   %1, %1
+%else
+    pxor    %2, %2
+    psubb   %2, %1
+    pminub  %1, %2
+%endif
+%endmacro
+
+%macro ABSD 2-3
+%if cpuflag(ssse3)
+    pabsd   %1, %2
+%else
+    %define %%s %2
+%if %0 == 3
+    mova    %3, %2
+    %define %%s %3
+%endif
+    pxor     %1, %1
+    pcmpgtd  %1, %%s
+    pxor    %%s, %1
+    psubd   %%s, %1
+    SWAP     %1, %%s
+%endif
+%endmacro
+
+%macro PSIGN 3-4
+%if cpuflag(ssse3) && %0 == 4
+    psign%1 %2, %3, %4
+%elif cpuflag(ssse3)
+    psign%1 %2, %3
+%elif %0 == 4
+    pxor    %2, %3, %4
+    psub%1  %2, %4
+%else
+    pxor    %2, %3
+    psub%1  %2, %3
+%endif
+%endmacro
+
+%define PSIGNW PSIGN w,
+%define PSIGND PSIGN d,
+
+%macro SPLATB_LOAD 3
+%if cpuflag(ssse3)
+    movd      %1, [%2-3]
+    pshufb    %1, %3
+%else
+    movd      %1, [%2-3] ;to avoid crossing a cacheline
+    punpcklbw %1, %1
+    SPLATW    %1, %1, 3
+%endif
+%endmacro
+
+%imacro SPLATW 2-3 0
+%if cpuflag(avx2) && %3 == 0
+    vpbroadcastw %1, %2
+%else
+    PSHUFLW      %1, %2, (%3)*q1111
+%if mmsize == 16
+    punpcklqdq   %1, %1
+%endif
+%endif
+%endmacro
+
+%imacro SPLATD 2-3 0
+%if mmsize == 16
+    pshufd %1, %2, (%3)*q1111
+%else
+    pshufw %1, %2, (%3)*q0101 + ((%3)+1)*q1010
+%endif
+%endmacro
+
+%macro CLIPW 3 ;(dst, min, max)
+    pmaxsw %1, %2
+    pminsw %1, %3
+%endmacro
+
+%macro MOVHL 2 ; dst, src
+%ifidn %1, %2
+    punpckhqdq %1, %2
+%elif cpuflag(avx)
+    punpckhqdq %1, %2, %2
+%elif cpuflag(sse4)
+    pshufd     %1, %2, q3232 ; pshufd is slow on some older CPUs, so only use it on more modern ones
+%else
+    movhlps    %1, %2        ; may cause an int/float domain transition and has a dependency on dst
+%endif
 %endmacro
 
-%macro ABS1_SSSE3 2
-    pabsw   %1, %1
+%macro HADDD 2 ; sum junk
+%if sizeof%1 == 32
+%define %2 xmm%2
+    vextracti128 %2, %1, 1
+%define %1 xmm%1
+    paddd   %1, %2
+%endif
+%if mmsize >= 16
+    MOVHL   %2, %1
+    paddd   %1, %2
+%endif
+%if cpuflag(xop) && sizeof%1 == 16
+    vphadddq %1, %1
+%else
+    PSHUFLW %2, %1, q0032
+    paddd   %1, %2
+%endif
+%undef %1
+%undef %2
 %endmacro
 
-%macro ABS2_SSSE3 4
-    pabsw   %1, %1
-    pabsw   %2, %2
+%macro HADDW 2 ; reg, tmp
+%if cpuflag(xop) && sizeof%1 == 16
+    vphaddwq  %1, %1
+    MOVHL     %2, %1
+    paddd     %1, %2
+%else
+    pmaddwd   %1, [pw_1]
+    HADDD     %1, %2
+%endif
 %endmacro
 
-%define ABS1 ABS1_MMX
-%define ABS2 ABS2_MMX
+%macro HADDUWD 2
+%if cpuflag(xop) && sizeof%1 == 16
+    vphadduwd %1, %1
+%else
+    psrld %2, %1, 16
+    pslld %1, 16
+    psrld %1, 16
+    paddd %1, %2
+%endif
+%endmacro
 
-%macro ABS4 6
-    ABS2 %1, %2, %5, %6
-    ABS2 %3, %4, %5, %6
+%macro HADDUW 2
+%if cpuflag(xop) && sizeof%1 == 16
+    vphadduwq %1, %1
+    MOVHL     %2, %1
+    paddd     %1, %2
+%else
+    HADDUWD   %1, %2
+    HADDD     %1, %2
+%endif
 %endmacro
 
-%macro PALIGNR_MMX 4
+%macro PALIGNR 4-5 ; [dst,] src1, src2, imm, tmp
+; AVX2 version uses a precalculated extra input that
+; can be re-used across calls
+%if sizeof%1==32
+                                 ; %3 = abcdefgh ijklmnop (lower address)
+                                 ; %2 = ABCDEFGH IJKLMNOP (higher address)
+;   vperm2i128 %5, %2, %3, q0003 ; %5 = ijklmnop ABCDEFGH
+%if %4 < 16
+    palignr    %1, %5, %3, %4    ; %1 = bcdefghi jklmnopA
+%else
+    palignr    %1, %2, %5, %4-16 ; %1 = pABCDEFG HIJKLMNO
+%endif
+%elif cpuflag(ssse3)
+    %if %0==5
+        palignr %1, %2, %3, %4
+    %else
+        palignr %1, %2, %3
+    %endif
+%else
+    %define %%dst %1
+    %if %0==5
+        %ifnidn %1, %2
+            mova %%dst, %2
+        %endif
+        %rotate 1
+    %endif
     %ifnidn %4, %2
-    mova    %4, %2
+        mova %4, %2
+    %endif
+    %if mmsize==8
+        psllq  %%dst, (8-%3)*8
+        psrlq  %4, %3*8
+    %else
+        pslldq %%dst, 16-%3
+        psrldq %4, %3
     %endif
+    por %%dst, %4
+%endif
+%endmacro
+
+%macro PSHUFLW 1+
     %if mmsize == 8
-    psllq   %1, (8-%3)*8
-    psrlq   %4, %3*8
+        pshufw %1
     %else
-    pslldq  %1, 16-%3
-    psrldq  %4, %3
+        pshuflw %1
     %endif
-    por     %1, %4
 %endmacro
 
-%macro PALIGNR_SSSE3 4
-    palignr %1, %2, %3
+; shift a mmxreg by n bytes, or a xmmreg by 2*n bytes
+; values shifted in are undefined
+; faster if dst==src
+%define PSLLPIX PSXLPIX l, -1, ;dst, src, shift
+%define PSRLPIX PSXLPIX r,  1, ;dst, src, shift
+%macro PSXLPIX 5
+    %if mmsize == 8
+        %if %5&1
+            ps%1lq %3, %4, %5*8
+        %else
+            pshufw %3, %4, (q3210<<8>>(8+%2*%5))&0xff
+        %endif
+    %else
+        ps%1ldq %3, %4, %5*2
+    %endif
 %endmacro
 
-%macro SUMSUB_BA 2
-    paddw   %1, %2
-    paddw   %2, %2
-    psubw   %2, %1
+%macro DEINTB 5 ; mask, reg1, mask, reg2, optional src to fill masks from
+%ifnum %5
+    pand   m%3, m%5, m%4 ; src .. y6 .. y4
+    pand   m%1, m%5, m%2 ; dst .. y6 .. y4
+%else
+    mova   m%1, %5
+    pand   m%3, m%1, m%4 ; src .. y6 .. y4
+    pand   m%1, m%1, m%2 ; dst .. y6 .. y4
+%endif
+    psrlw  m%2, 8        ; dst .. y7 .. y5
+    psrlw  m%4, 8        ; src .. y7 .. y5
 %endmacro
 
-%macro SUMSUB_BADC 4
-    paddw   %1, %2
-    paddw   %3, %4
-    paddw   %2, %2
-    paddw   %4, %4
-    psubw   %2, %1
-    psubw   %4, %3
+%macro SUMSUB_BA 3-4
+%if %0==3
+    padd%1  m%2, m%3
+    padd%1  m%3, m%3
+    psub%1  m%3, m%2
+%elif avx_enabled
+    padd%1  m%4, m%2, m%3
+    psub%1  m%3, m%2
+    SWAP    %2, %4
+%else
+    mova    m%4, m%2
+    padd%1  m%2, m%3
+    psub%1  m%3, m%4
+%endif
 %endmacro
 
-%macro HADAMARD8_1D 8
-    SUMSUB_BADC %1, %5, %2, %6
-    SUMSUB_BADC %3, %7, %4, %8
-    SUMSUB_BADC %1, %3, %2, %4
-    SUMSUB_BADC %5, %7, %6, %8
-    SUMSUB_BADC %1, %2, %3, %4
-    SUMSUB_BADC %5, %6, %7, %8
+%macro SUMSUB_BADC 5-6
+%if %0==6
+    SUMSUB_BA %1, %2, %3, %6
+    SUMSUB_BA %1, %4, %5, %6
+%else
+    padd%1  m%2, m%3
+    padd%1  m%4, m%5
+    padd%1  m%3, m%3
+    padd%1  m%5, m%5
+    psub%1  m%3, m%2
+    psub%1  m%5, m%4
+%endif
 %endmacro
 
-%macro SUMSUB2_AB 3
-    mova    %3, %1
-    paddw   %1, %1
-    paddw   %1, %2
-    psubw   %3, %2
-    psubw   %3, %2
+%macro HADAMARD4_V 4+
+    SUMSUB_BADC w, %1, %2, %3, %4
+    SUMSUB_BADC w, %1, %3, %2, %4
 %endmacro
 
-%macro SUMSUBD2_AB 4
-    mova    %4, %1
-    mova    %3, %2
-    psraw   %2, 1
-    psraw   %4, 1
-    paddw   %1, %2
-    psubw   %4, %3
+%macro HADAMARD8_V 8+
+    SUMSUB_BADC w, %1, %2, %3, %4
+    SUMSUB_BADC w, %5, %6, %7, %8
+    SUMSUB_BADC w, %1, %3, %2, %4
+    SUMSUB_BADC w, %5, %7, %6, %8
+    SUMSUB_BADC w, %1, %5, %2, %6
+    SUMSUB_BADC w, %3, %7, %4, %8
+%endmacro
+
+%macro TRANS_SSE2 5-6
+; TRANSPOSE2x2
+; %1: transpose width (d/q) - use SBUTTERFLY qdq for dq
+; %2: ord/unord (for compat with sse4, unused)
+; %3/%4: source regs
+; %5/%6: tmp regs
+%ifidn %1, d
+%define mask [mask_10]
+%define shift 16
+%elifidn %1, q
+%define mask [mask_1100]
+%define shift 32
+%endif
+%if %0==6 ; less dependency if we have two tmp
+    mova   m%5, mask   ; ff00
+    mova   m%6, m%4    ; x5x4
+    psll%1 m%4, shift  ; x4..
+    pand   m%6, m%5    ; x5..
+    pandn  m%5, m%3    ; ..x0
+    psrl%1 m%3, shift  ; ..x1
+    por    m%4, m%5    ; x4x0
+    por    m%3, m%6    ; x5x1
+%else ; more dependency, one insn less. sometimes faster, sometimes not
+    mova   m%5, m%4    ; x5x4
+    psll%1 m%4, shift  ; x4..
+    pxor   m%4, m%3    ; (x4^x1)x0
+    pand   m%4, mask   ; (x4^x1)..
+    pxor   m%3, m%4    ; x4x0
+    psrl%1 m%4, shift  ; ..(x1^x4)
+    pxor   m%5, m%4    ; x5x1
+    SWAP   %4, %3, %5
+%endif
+%endmacro
+
+%macro TRANS_SSE4 5-6 ; see above
+%ifidn %1, d
+%ifidn %2, ord
+    psrl%1  m%5, m%3, 16
+    pblendw m%5, m%4, q2222
+    psll%1  m%4, 16
+    pblendw m%4, m%3, q1111
+    SWAP     %3, %5
+%else
+%if avx_enabled
+    pblendw m%5, m%3, m%4, q2222
+    SWAP     %3, %5
+%else
+    mova    m%5, m%3
+    pblendw m%3, m%4, q2222
+%endif
+    psll%1  m%4, 16
+    psrl%1  m%5, 16
+    por     m%4, m%5
+%endif
+%elifidn %1, q
+    shufps m%5, m%3, m%4, q3131
+    shufps m%3, m%3, m%4, q2020
+    SWAP    %4, %5
+%endif
+%endmacro
+
+%macro TRANS_XOP 5-6
+%ifidn %1, d
+    vpperm m%5, m%3, m%4, [transd_shuf1]
+    vpperm m%3, m%3, m%4, [transd_shuf2]
+%elifidn %1, q
+    shufps m%5, m%3, m%4, q3131
+    shufps m%3, m%4, q2020
+%endif
+    SWAP    %4, %5
+%endmacro
+
+%macro HADAMARD 5-6
+; %1=distance in words (0 for vertical pass, 1/2/4 for horizontal passes)
+; %2=sumsub/max/amax (sum and diff / maximum / maximum of absolutes)
+; %3/%4: regs
+; %5(%6): tmpregs
+%if %1!=0 ; have to reorder stuff for horizontal op
+    %ifidn %2, sumsub
+        %define ORDER ord
+        ; sumsub needs order because a-b != b-a unless a=b
+    %else
+        %define ORDER unord
+        ; if we just max, order doesn't matter (allows pblendw+or in sse4)
+    %endif
+    %if %1==1
+        TRANS d, ORDER, %3, %4, %5, %6
+    %elif %1==2
+        %if mmsize==8
+            SBUTTERFLY dq, %3, %4, %5
+        %else
+            TRANS q, ORDER, %3, %4, %5, %6
+        %endif
+    %elif %1==4
+        SBUTTERFLY qdq, %3, %4, %5
+    %elif %1==8
+        SBUTTERFLY dqqq, %3, %4, %5
+    %endif
+%endif
+%ifidn %2, sumsub
+    SUMSUB_BA w, %3, %4, %5
+%else
+    %ifidn %2, amax
+        %if %0==6
+            ABSW2 m%3, m%4, m%3, m%4, m%5, m%6
+        %else
+            ABSW m%3, m%3, m%5
+            ABSW m%4, m%4, m%5
+        %endif
+    %endif
+    pmaxsw m%3, m%4
+%endif
+%endmacro
+
+
+%macro HADAMARD2_2D 6-7 sumsub
+    HADAMARD 0, sumsub, %1, %2, %5
+    HADAMARD 0, sumsub, %3, %4, %5
+    SBUTTERFLY %6, %1, %2, %5
+%ifnum %7
+    HADAMARD 0, amax, %1, %2, %5, %7
+%else
+    HADAMARD 0, %7, %1, %2, %5
+%endif
+    SBUTTERFLY %6, %3, %4, %5
+%ifnum %7
+    HADAMARD 0, amax, %3, %4, %5, %7
+%else
+    HADAMARD 0, %7, %3, %4, %5
+%endif
+%endmacro
+
+%macro HADAMARD4_2D 5-6 sumsub
+    HADAMARD2_2D %1, %2, %3, %4, %5, wd
+    HADAMARD2_2D %1, %3, %2, %4, %5, dq, %6
+    SWAP %2, %3
 %endmacro
 
-%macro LOAD_DIFF 5
+%macro HADAMARD4_2D_SSE 5-6 sumsub
+    HADAMARD  0, sumsub, %1, %2, %5 ; 1st V row 0 + 1
+    HADAMARD  0, sumsub, %3, %4, %5 ; 1st V row 2 + 3
+    SBUTTERFLY   wd, %1, %2, %5     ; %1: m0 1+0 %2: m1 1+0
+    SBUTTERFLY   wd, %3, %4, %5     ; %3: m0 3+2 %4: m1 3+2
+    HADAMARD2_2D %1, %3, %2, %4, %5, dq
+    SBUTTERFLY  qdq, %1, %2, %5
+    HADAMARD  0, %6, %1, %2, %5     ; 2nd H m1/m0 row 0+1
+    SBUTTERFLY  qdq, %3, %4, %5
+    HADAMARD  0, %6, %3, %4, %5     ; 2nd H m1/m0 row 2+3
+%endmacro
+
+%macro HADAMARD8_2D 9-10 sumsub
+    HADAMARD2_2D %1, %2, %3, %4, %9, wd
+    HADAMARD2_2D %5, %6, %7, %8, %9, wd
+    HADAMARD2_2D %1, %3, %2, %4, %9, dq
+    HADAMARD2_2D %5, %7, %6, %8, %9, dq
+    HADAMARD2_2D %1, %5, %3, %7, %9, qdq, %10
+    HADAMARD2_2D %2, %6, %4, %8, %9, qdq, %10
+%ifnidn %10, amax
+    SWAP %2, %5
+    SWAP %4, %7
+%endif
+%endmacro
+
+; doesn't include the "pmaddubsw hmul_8p" pass
+%macro HADAMARD8_2D_HMUL 10
+    HADAMARD4_V %1, %2, %3, %4, %9
+    HADAMARD4_V %5, %6, %7, %8, %9
+    SUMSUB_BADC w, %1, %5, %2, %6, %9
+    HADAMARD 2, sumsub, %1, %5, %9, %10
+    HADAMARD 2, sumsub, %2, %6, %9, %10
+    SUMSUB_BADC w, %3, %7, %4, %8, %9
+    HADAMARD 2, sumsub, %3, %7, %9, %10
+    HADAMARD 2, sumsub, %4, %8, %9, %10
+    HADAMARD 1, amax, %1, %5, %9, %10
+    HADAMARD 1, amax, %2, %6, %9, %5
+    HADAMARD 1, amax, %3, %7, %9, %5
+    HADAMARD 1, amax, %4, %8, %9, %5
+%endmacro
+
+%macro SUMSUB2_AB 4
+%if cpuflag(xop)
+    pmacs%1%1 m%4, m%3, [p%1_m2], m%2
+    pmacs%1%1 m%2, m%2, [p%1_2], m%3
+%elifnum %3
+    psub%1  m%4, m%2, m%3
+    psub%1  m%4, m%3
+    padd%1  m%2, m%2
+    padd%1  m%2, m%3
+%else
+    mova    m%4, m%2
+    padd%1  m%2, m%2
+    padd%1  m%2, %3
+    psub%1  m%4, %3
+    psub%1  m%4, %3
+%endif
+%endmacro
+
+%macro SUMSUBD2_AB 5
+%ifnum %4
+    psra%1  m%5, m%2, 1  ; %3: %3>>1
+    psra%1  m%4, m%3, 1  ; %2: %2>>1
+    padd%1  m%4, m%2     ; %3: %3>>1+%2
+    psub%1  m%5, m%3     ; %2: %2>>1-%3
+    SWAP     %2, %5
+    SWAP     %3, %4
+%else
+    mova    %5, m%2
+    mova    %4, m%3
+    psra%1  m%3, 1  ; %3: %3>>1
+    psra%1  m%2, 1  ; %2: %2>>1
+    padd%1  m%3, %5 ; %3: %3>>1+%2
+    psub%1  m%2, %4 ; %2: %2>>1-%3
+%endif
+%endmacro
+
+%macro DCT4_1D 5
+%ifnum %5
+    SUMSUB_BADC w, %4, %1, %3, %2, %5
+    SUMSUB_BA   w, %3, %4, %5
+    SUMSUB2_AB  w, %1, %2, %5
+    SWAP %1, %3, %4, %5, %2
+%else
+    SUMSUB_BADC w, %4, %1, %3, %2
+    SUMSUB_BA   w, %3, %4
+    mova     [%5], m%2
+    SUMSUB2_AB  w, %1, [%5], %2
+    SWAP %1, %3, %4, %2
+%endif
+%endmacro
+
+%macro IDCT4_1D 6-7
+%ifnum %6
+    SUMSUBD2_AB %1, %3, %5, %7, %6
+    ; %3: %3>>1-%5 %5: %3+%5>>1
+    SUMSUB_BA   %1, %4, %2, %7
+    ; %4: %2+%4 %2: %2-%4
+    SUMSUB_BADC %1, %5, %4, %3, %2, %7
+    ; %5: %2+%4 + (%3+%5>>1)
+    ; %4: %2+%4 - (%3+%5>>1)
+    ; %3: %2-%4 + (%3>>1-%5)
+    ; %2: %2-%4 - (%3>>1-%5)
+%else
+%ifidn %1, w
+    SUMSUBD2_AB %1, %3, %5, [%6], [%6+16]
+%else
+    SUMSUBD2_AB %1, %3, %5, [%6], [%6+32]
+%endif
+    SUMSUB_BA   %1, %4, %2
+    SUMSUB_BADC %1, %5, %4, %3, %2
+%endif
+    SWAP %2, %5, %4
+    ; %2: %2+%4 + (%3+%5>>1) row0
+    ; %3: %2-%4 + (%3>>1-%5) row1
+    ; %4: %2-%4 - (%3>>1-%5) row2
+    ; %5: %2+%4 - (%3+%5>>1) row3
+%endmacro
+
+
+%macro LOAD_DIFF 5-6 1
+%if HIGH_BIT_DEPTH
+%if %6 ; %5 aligned?
+    mova       %1, %4
+    psubw      %1, %5
+%else
+    movu       %1, %4
+    movu       %2, %5
+    psubw      %1, %2
+%endif
+%else ; !HIGH_BIT_DEPTH
 %ifidn %3, none
     movh       %1, %4
     movh       %2, %5
     punpcklbw  %2, %3
     psubw      %1, %2
 %endif
+%endif ; HIGH_BIT_DEPTH
+%endmacro
+
+%macro LOAD_DIFF8x4 8 ; 4x dst, 1x tmp, 1x mul, 2x ptr
+%if BIT_DEPTH == 8 && cpuflag(ssse3)
+    movh       m%2, [%8+%1*FDEC_STRIDE]
+    movh       m%1, [%7+%1*FENC_STRIDE]
+    punpcklbw  m%1, m%2
+    movh       m%3, [%8+%2*FDEC_STRIDE]
+    movh       m%2, [%7+%2*FENC_STRIDE]
+    punpcklbw  m%2, m%3
+    movh       m%4, [%8+%3*FDEC_STRIDE]
+    movh       m%3, [%7+%3*FENC_STRIDE]
+    punpcklbw  m%3, m%4
+    movh       m%5, [%8+%4*FDEC_STRIDE]
+    movh       m%4, [%7+%4*FENC_STRIDE]
+    punpcklbw  m%4, m%5
+    pmaddubsw  m%1, m%6
+    pmaddubsw  m%2, m%6
+    pmaddubsw  m%3, m%6
+    pmaddubsw  m%4, m%6
+%else
+    LOAD_DIFF  m%1, m%5, m%6, [%7+%1*FENC_STRIDEB], [%8+%1*FDEC_STRIDEB]
+    LOAD_DIFF  m%2, m%5, m%6, [%7+%2*FENC_STRIDEB], [%8+%2*FDEC_STRIDEB]
+    LOAD_DIFF  m%3, m%5, m%6, [%7+%3*FENC_STRIDEB], [%8+%3*FDEC_STRIDEB]
+    LOAD_DIFF  m%4, m%5, m%6, [%7+%4*FENC_STRIDEB], [%8+%4*FDEC_STRIDEB]
+%endif
+%endmacro
+
+%macro STORE_DCT 6
+    movq   [%5+%6+ 0], m%1
+    movq   [%5+%6+ 8], m%2
+    movq   [%5+%6+16], m%3
+    movq   [%5+%6+24], m%4
+    movhps [%5+%6+32], m%1
+    movhps [%5+%6+40], m%2
+    movhps [%5+%6+48], m%3
+    movhps [%5+%6+56], m%4
+%endmacro
+
+%macro STORE_IDCT 4
+    movhps [r0-4*FDEC_STRIDE], %1
+    movh   [r0-3*FDEC_STRIDE], %1
+    movhps [r0-2*FDEC_STRIDE], %2
+    movh   [r0-1*FDEC_STRIDE], %2
+    movhps [r0+0*FDEC_STRIDE], %3
+    movh   [r0+1*FDEC_STRIDE], %3
+    movhps [r0+2*FDEC_STRIDE], %4
+    movh   [r0+3*FDEC_STRIDE], %4
+%endmacro
+
+%macro LOAD_DIFF_8x4P 7-11 r0,r2,0,1 ; 4x dest, 2x temp, 2x pointer, increment, aligned?
+    LOAD_DIFF m%1, m%5, m%7, [%8],      [%9],      %11
+    LOAD_DIFF m%2, m%6, m%7, [%8+r1],   [%9+r3],   %11
+    LOAD_DIFF m%3, m%5, m%7, [%8+2*r1], [%9+2*r3], %11
+    LOAD_DIFF m%4, m%6, m%7, [%8+r4],   [%9+r5],   %11
+%if %10
+    lea %8, [%8+4*r1]
+    lea %9, [%9+4*r3]
+%endif
 %endmacro
 
-%macro LOAD_DIFF_8x4P 6 ; 4x dest, 2x temp
-    LOAD_DIFF %1, %5, none, [r0],      [r2]
-    LOAD_DIFF %2, %6, none, [r0+r1],   [r2+r3]
-    LOAD_DIFF %3, %5, none, [r0+2*r1], [r2+2*r3]
-    LOAD_DIFF %4, %6, none, [r0+r4],   [r2+r5]
+; 2xdst, 2xtmp, 2xsrcrow
+%macro LOAD_DIFF16x2_AVX2 6
+    pmovzxbw m%1, [r1+%5*FENC_STRIDE]
+    pmovzxbw m%2, [r1+%6*FENC_STRIDE]
+    pmovzxbw m%3, [r2+(%5-4)*FDEC_STRIDE]
+    pmovzxbw m%4, [r2+(%6-4)*FDEC_STRIDE]
+    psubw    m%1, m%3
+    psubw    m%2, m%4
 %endmacro
 
-%macro STORE_DIFF 4
+%macro DIFFx2 6-7
+    movh       %3, %5
+    punpcklbw  %3, %4
     psraw      %1, 6
+    paddsw     %1, %3
+    movh       %3, %6
+    punpcklbw  %3, %4
+    psraw      %2, 6
+    paddsw     %2, %3
+    packuswb   %2, %1
+%endmacro
+
+; (high depth) in: %1, %2, min to clip, max to clip, mem128
+; in: %1, tmp, %3, mem64
+%macro STORE_DIFF 4-5
+%if HIGH_BIT_DEPTH
+    psrad      %1, 6
+    psrad      %2, 6
+    packssdw   %1, %2
+    paddw      %1, %5
+    CLIPW      %1, %3, %4
+    mova       %5, %1
+%else
     movh       %2, %4
     punpcklbw  %2, %3
+    psraw      %1, 6
     paddsw     %1, %2
     packuswb   %1, %1
     movh       %4, %1
+%endif
+%endmacro
+
+%macro SHUFFLE_MASK_W 8
+    %rep 8
+        %if %1>=0x80
+            db %1, %1
+        %else
+            db %1*2
+            db %1*2+1
+        %endif
+        %rotate 1
+    %endrep
+%endmacro
+
+; instruction, accum, input, iteration (zero to swap, nonzero to add)
+%macro ACCUM 4
+%if %4
+    %1        m%2, m%3
+%else
+    SWAP       %2, %3
+%endif
 %endmacro