;****************************************************************************** ;* Copyright (c) Lynne ;* ;* 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 one_tab: times 4 dq 1.0 seq_tab_avx2: dq 3.0, 2.0, 1.0, 0.0 sub_tab: dq -1.0, -2.0, -3.0, -4.0 add_tab_avx2: times 4 dq 4.0 dec_tab_avx2: times 4 dq -4.0 add_tab_sse2: times 2 dq 2.0 dec_tab_sse2: times 2 dq -2.0 dec_tab_scalar: times 2 dq -1.0 seq_tab_sse2: dq 1.0, 0.0 SECTION .text %macro APPLY_WELCH_FN 0 cglobal lpc_apply_welch_window, 3, 5, 8, data, len, out, off1, off2 cmp lenq, 0 je .end_e cmp lenq, 2 je .two cmp lenq, 1 je .one movapd m6, [one_tab] movd xm1, lend cvtdq2pd xm1, xm1 ; len %if cpuflag(avx2) vbroadcastsd m1, xm1 %else shufpd m1, m1, 00b %endif addpd m0, m6, m6 ; 2.0 subpd m1, m6 ; len - 1 divpd m0, m1 ; 2.0 / (len - 1) mov off1q, lenq and off1q, 1 je .even movapd m5, m0 addpd m0, [sub_tab] lea off2q, [lenq*4 - mmsize/2] sub lenq, mmsize/4 ; avoid overwriting xor off1q, off1q cmp lenq, mmsize/4 jl .scalar_o %if cpuflag(avx2) movapd m7, [dec_tab_avx2] %else movapd m7, [dec_tab_sse2] %endif .loop_o: movapd m1, m6 %if cpuflag(avx2) fnmaddpd m1, m0, m0, m1 vpermpd m2, m1, q0123 %else mulpd m2, m0, m0 subpd m1, m2 shufpd m2, m1, m1, 01b %endif cvtdq2pd m3, [dataq + off1q] cvtdq2pd m4, [dataq + off2q] mulpd m1, m3 mulpd m2, m4 movupd [outq + off1q*2], m1 movupd [outq + off2q*2], m2 addpd m0, m7 add off1q, mmsize/2 sub off2q, mmsize/2 sub lenq, mmsize/4 jg .loop_o add lend, (mmsize/4 - 1) cmp lend, 0 je .end_o sub lenq, (mmsize/4 - 1) .scalar_o: movapd xm7, [dec_tab_scalar] ; Set offsets add off2q, (mmsize/4) + 4*cpuflag(avx2) add lenq, mmsize/4 - 2 .loop_o_scalar: movapd xm1, xm6 %if cpuflag(avx2) fnmaddpd xm1, xm0, xm0, xm1 %else mulpd xm2, xm0, xm0 subpd xm1, xm2 %endif cvtdq2pd xm3, [dataq + off1q] cvtdq2pd xm4, [dataq + off2q] mulpd xm3, xm1 mulpd xm4, xm1 movlpd [outq + off1q*2], xm3 movlpd [outq + off2q*2], xm4 addpd xm0, xm7 add off1q, 4 sub off2q, 4 sub lenq, 2 jg .loop_o_scalar .end_o: xorpd xm3, xm3 movlpd [outq + off1q*2], xm3 RET .even: %if cpuflag(avx2) addpd m0, [seq_tab_avx2] %else addpd m0, [seq_tab_sse2] %endif mov off1d, lend shr off1d, 1 movd xm1, off1d cvtdq2pd xm1, xm1 ; len/2 %if cpuflag(avx2) vbroadcastsd m1, xm1 %else shufpd m1, m1, 00b %endif subpd m0, m1 %if cpuflag(avx2) movapd m7, [add_tab_avx2] %else movapd m7, [add_tab_sse2] %endif lea off2q, [lenq*2] lea off1q, [lenq*2 - mmsize/2] sub lenq, mmsize/4 cmp lenq, mmsize/4 jl .scalar_e .loop_e: movapd m1, m6 %if cpuflag(avx2) fnmaddpd m1, m0, m0, m1 %else mulpd m2, m0, m0 subpd m1, m2 %endif %if cpuflag(avx2) vpermpd m2, m1, q0123 %else shufpd m2, m1, m1, 01b %endif cvtdq2pd m3, [dataq + off1q] cvtdq2pd m4, [dataq + off2q] mulpd m1, m3 mulpd m2, m4 movupd [outq + off1q*2], m1 movupd [outq + off2q*2], m2 addpd m0, m7 add off2q, mmsize/2 sub off1q, mmsize/2 sub lenq, mmsize/4 jge .loop_e .scalar_e: subpd xm0, xm7 movapd xm7, [dec_tab_scalar] subpd xm0, xm7 add off1q, (mmsize/2) sub off2q, (mmsize/2) - 8*cpuflag(avx2) add lenq, 6 + 4*cpuflag(avx2) addpd xm0, [sub_tab] .loop_e_scalar: movapd xm1, xm6 %if cpuflag(avx2) fnmaddpd xm1, xm0, xm0, xm1 %else mulpd xm2, xm0, xm0 subpd xm1, xm2 %endif cvtdq2pd xm3, [dataq + off1q] cvtdq2pd xm4, [dataq + off2q] mulpd xm3, xm1 shufpd xm1, xm1, 00b mulpd xm4, xm1 movlpd [outq + off1q*2], xm3 movhpd [outq + off2q*2 + 8], xm4 subpd xm0, xm7 add off2q, 4 sub off1q, 4 sub lenq, 2 jg .loop_e_scalar RET .two: xorpd xm0, xm0 movhpd [outq + 8], xm0 .one: xorpd xm0, xm0 movhpd [outq], xm0 .end_e: RET %endmacro INIT_XMM sse2 APPLY_WELCH_FN %if HAVE_AVX2_EXTERNAL INIT_YMM avx2 APPLY_WELCH_FN %endif