;****************************************************************************** ;* VP9 MC SIMD optimizations ;* ;* Copyright (c) 2015 Ronald S. Bultje <rsbultje gmail com> ;* ;* This file is part of FFmpeg. ;* ;* FFmpeg is free software; you can redistribute it and/or ;* modify it under the terms of the GNU Lesser General Public ;* License as published by the Free Software Foundation; either ;* version 2.1 of the License, or (at your option) any later version. ;* ;* FFmpeg is distributed in the hope that it will be useful, ;* but WITHOUT ANY WARRANTY; without even the implied warranty of ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;* Lesser General Public License for more details. ;* ;* You should have received a copy of the GNU Lesser General Public ;* License along with FFmpeg; if not, write to the Free Software ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** %include "libavutil/x86/x86util.asm" SECTION_RODATA 32 pd_64: times 8 dd 64 cextern pw_1023 cextern pw_4095 SECTION .text %macro filter_h4_fn 1-2 12 cglobal vp9_%1_8tap_1d_h_4_10, 6, 6, %2, dst, dstride, src, sstride, h, filtery mova m5, [pw_1023] .body: %if notcpuflag(sse4) && ARCH_X86_64 pxor m11, m11 %endif mova m6, [pd_64] mova m7, [filteryq+ 0] %if ARCH_X86_64 && mmsize > 8 mova m8, [filteryq+32] mova m9, [filteryq+64] mova m10, [filteryq+96] %endif .loop: movh m0, [srcq-6] movh m1, [srcq-4] movh m2, [srcq-2] movh m3, [srcq+0] movh m4, [srcq+2] punpcklwd m0, m1 punpcklwd m2, m3 pmaddwd m0, m7 %if ARCH_X86_64 && mmsize > 8 pmaddwd m2, m8 %else pmaddwd m2, [filteryq+32] %endif movu m1, [srcq+4] movu m3, [srcq+6] paddd m0, m2 movu m2, [srcq+8] add srcq, sstrideq punpcklwd m4, m1 punpcklwd m3, m2 %if ARCH_X86_64 && mmsize > 8 pmaddwd m4, m9 pmaddwd m3, m10 %else pmaddwd m4, [filteryq+64] pmaddwd m3, [filteryq+96] %endif paddd m0, m4 paddd m0, m3 paddd m0, m6 psrad m0, 7 %if cpuflag(sse4) packusdw m0, m0 %else packssdw m0, m0 %endif %ifidn %1, avg movh m1, [dstq] %endif pminsw m0, m5 %if notcpuflag(sse4) %if ARCH_X86_64 pmaxsw m0, m11 %else pxor m2, m2 pmaxsw m0, m2 %endif %endif %ifidn %1, avg pavgw m0, m1 %endif movh [dstq], m0 add dstq, dstrideq dec hd jg .loop RET cglobal vp9_%1_8tap_1d_h_4_12, 6, 6, %2, dst, dstride, src, sstride, h, filtery mova m5, [pw_4095] jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_h_4_10 %+ SUFFIX).body %endmacro INIT_XMM sse2 filter_h4_fn put filter_h4_fn avg %macro filter_h_fn 1-2 12 %assign %%px mmsize/2 cglobal vp9_%1_8tap_1d_h_ %+ %%px %+ _10, 6, 6, %2, dst, dstride, src, sstride, h, filtery mova m5, [pw_1023] .body: %if notcpuflag(sse4) && ARCH_X86_64 pxor m11, m11 %endif mova m6, [pd_64] mova m7, [filteryq+ 0] %if ARCH_X86_64 && mmsize > 8 mova m8, [filteryq+32] mova m9, [filteryq+64] mova m10, [filteryq+96] %endif .loop: movu m0, [srcq-6] movu m1, [srcq-4] movu m2, [srcq-2] movu m3, [srcq+0] movu m4, [srcq+2] pmaddwd m0, m7 pmaddwd m1, m7 %if ARCH_X86_64 && mmsize > 8 pmaddwd m2, m8 pmaddwd m3, m8 pmaddwd m4, m9 %else pmaddwd m2, [filteryq+32] pmaddwd m3, [filteryq+32] pmaddwd m4, [filteryq+64] %endif paddd m0, m2 paddd m1, m3 paddd m0, m4 movu m2, [srcq+4] movu m3, [srcq+6] movu m4, [srcq+8] add srcq, sstrideq %if ARCH_X86_64 && mmsize > 8 pmaddwd m2, m9 pmaddwd m3, m10 pmaddwd m4, m10 %else pmaddwd m2, [filteryq+64] pmaddwd m3, [filteryq+96] pmaddwd m4, [filteryq+96] %endif paddd m1, m2 paddd m0, m3 paddd m1, m4 paddd m0, m6 paddd m1, m6 psrad m0, 7 psrad m1, 7 %if cpuflag(sse4) packusdw m0, m0 packusdw m1, m1 %else packssdw m0, m0 packssdw m1, m1 %endif punpcklwd m0, m1 pminsw m0, m5 %if notcpuflag(sse4) %if ARCH_X86_64 pmaxsw m0, m11 %else pxor m2, m2 pmaxsw m0, m2 %endif %endif %ifidn %1, avg pavgw m0, [dstq] %endif mova [dstq], m0 add dstq, dstrideq dec hd jg .loop RET cglobal vp9_%1_8tap_1d_h_ %+ %%px %+ _12, 6, 6, %2, dst, dstride, src, sstride, h, filtery mova m5, [pw_4095] jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_h_ %+ %%px %+ _10 %+ SUFFIX).body %endmacro INIT_XMM sse2 filter_h_fn put filter_h_fn avg %if HAVE_AVX2_EXTERNAL INIT_YMM avx2 filter_h_fn put filter_h_fn avg %endif %macro filter_v4_fn 1-2 12 %if ARCH_X86_64 cglobal vp9_%1_8tap_1d_v_4_10, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3 %else cglobal vp9_%1_8tap_1d_v_4_10, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3 mov filteryq, r5mp %define hd r4mp %endif mova m5, [pw_1023] .body: %if notcpuflag(sse4) && ARCH_X86_64 pxor m11, m11 %endif mova m6, [pd_64] lea sstride3q, [sstrideq*3] lea src4q, [srcq+sstrideq] sub srcq, sstride3q mova m7, [filteryq+ 0] %if ARCH_X86_64 && mmsize > 8 mova m8, [filteryq+ 32] mova m9, [filteryq+ 64] mova m10, [filteryq+ 96] %endif .loop: ; FIXME maybe reuse loads from previous rows, or just ; more generally unroll this to prevent multiple loads of ; the same data? movh m0, [srcq] movh m1, [srcq+sstrideq] movh m2, [srcq+sstrideq*2] movh m3, [srcq+sstride3q] add srcq, sstrideq movh m4, [src4q] punpcklwd m0, m1 punpcklwd m2, m3 pmaddwd m0, m7 %if ARCH_X86_64 && mmsize > 8 pmaddwd m2, m8 %else pmaddwd m2, [filteryq+ 32] %endif movh m1, [src4q+sstrideq] movh m3, [src4q+sstrideq*2] paddd m0, m2 movh m2, [src4q+sstride3q] add src4q, sstrideq punpcklwd m4, m1 punpcklwd m3, m2 %if ARCH_X86_64 && mmsize > 8 pmaddwd m4, m9 pmaddwd m3, m10 %else pmaddwd m4, [filteryq+ 64] pmaddwd m3, [filteryq+ 96] %endif paddd m0, m4 paddd m0, m3 paddd m0, m6 psrad m0, 7 %if cpuflag(sse4) packusdw m0, m0 %else packssdw m0, m0 %endif %ifidn %1, avg movh m1, [dstq] %endif pminsw m0, m5 %if notcpuflag(sse4) %if ARCH_X86_64 pmaxsw m0, m11 %else pxor m2, m2 pmaxsw m0, m2 %endif %endif %ifidn %1, avg pavgw m0, m1 %endif movh [dstq], m0 add dstq, dstrideq dec hd jg .loop RET %if ARCH_X86_64 cglobal vp9_%1_8tap_1d_v_4_12, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3 %else cglobal vp9_%1_8tap_1d_v_4_12, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3 mov filteryq, r5mp %endif mova m5, [pw_4095] jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_v_4_10 %+ SUFFIX).body %endmacro INIT_XMM sse2 filter_v4_fn put filter_v4_fn avg %macro filter_v_fn 1-2 13 %assign %%px mmsize/2 %if ARCH_X86_64 cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _10, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3 %else cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _10, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3 mov filteryq, r5mp %define hd r4mp %endif mova m5, [pw_1023] .body: %if notcpuflag(sse4) && ARCH_X86_64 pxor m12, m12 %endif %if ARCH_X86_64 mova m11, [pd_64] %endif lea sstride3q, [sstrideq*3] lea src4q, [srcq+sstrideq] sub srcq, sstride3q mova m7, [filteryq+ 0] %if ARCH_X86_64 && mmsize > 8 mova m8, [filteryq+ 32] mova m9, [filteryq+ 64] mova m10, [filteryq+ 96] %endif .loop: ; FIXME maybe reuse loads from previous rows, or just ; more generally unroll this to prevent multiple loads of ; the same data? movu m0, [srcq] movu m1, [srcq+sstrideq] movu m2, [srcq+sstrideq*2] movu m3, [srcq+sstride3q] add srcq, sstrideq movu m4, [src4q] SBUTTERFLY wd, 0, 1, 6 SBUTTERFLY wd, 2, 3, 6 pmaddwd m0, m7 pmaddwd m1, m7 %if ARCH_X86_64 && mmsize > 8 pmaddwd m2, m8 pmaddwd m3, m8 %else pmaddwd m2, [filteryq+ 32] pmaddwd m3, [filteryq+ 32] %endif paddd m0, m2 paddd m1, m3 movu m2, [src4q+sstrideq] movu m3, [src4q+sstrideq*2] SBUTTERFLY wd, 4, 2, 6 %if ARCH_X86_64 && mmsize > 8 pmaddwd m4, m9 pmaddwd m2, m9 %else pmaddwd m4, [filteryq+ 64] pmaddwd m2, [filteryq+ 64] %endif paddd m0, m4 paddd m1, m2 movu m4, [src4q+sstride3q] add src4q, sstrideq SBUTTERFLY wd, 3, 4, 6 %if ARCH_X86_64 && mmsize > 8 pmaddwd m3, m10 pmaddwd m4, m10 %else pmaddwd m3, [filteryq+ 96] pmaddwd m4, [filteryq+ 96] %endif paddd m0, m3 paddd m1, m4 %if ARCH_X86_64 paddd m0, m11 paddd m1, m11 %else paddd m0, [pd_64] paddd m1, [pd_64] %endif psrad m0, 7 psrad m1, 7 %if cpuflag(sse4) packusdw m0, m1 %else packssdw m0, m1 %endif pminsw m0, m5 %if notcpuflag(sse4) %if ARCH_X86_64 pmaxsw m0, m12 %else pxor m2, m2 pmaxsw m0, m2 %endif %endif %ifidn %1, avg pavgw m0, [dstq] %endif mova [dstq], m0 add dstq, dstrideq dec hd jg .loop RET %if ARCH_X86_64 cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _12, 6, 8, %2, dst, dstride, src, sstride, h, filtery, src4, sstride3 %else cglobal vp9_%1_8tap_1d_v_ %+ %%px %+ _12, 4, 7, %2, dst, dstride, src, sstride, filtery, src4, sstride3 mov filteryq, r5mp %endif mova m5, [pw_4095] jmp mangle(private_prefix %+ _ %+ vp9_%1_8tap_1d_v_ %+ %%px %+ _10 %+ SUFFIX).body %endmacro INIT_XMM sse2 filter_v_fn put filter_v_fn avg %if HAVE_AVX2_EXTERNAL INIT_YMM avx2 filter_v_fn put filter_v_fn avg %endif