mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
parent
4308f238c0
commit
37c84eccc0
28 changed files with 8441 additions and 50 deletions
619
trunk/3rdparty/ffmpeg-4.2-fit/libswresample/x86/resample.asm
vendored
Normal file
619
trunk/3rdparty/ffmpeg-4.2-fit/libswresample/x86/resample.asm
vendored
Normal file
|
@ -0,0 +1,619 @@
|
|||
;******************************************************************************
|
||||
;* Copyright (c) 2012 Michael Niedermayer
|
||||
;* Copyright (c) 2014 James Almer <jamrial <at> gmail.com>
|
||||
;* Copyright (c) 2014 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"
|
||||
|
||||
%if ARCH_X86_64
|
||||
%define pointer resq
|
||||
%else
|
||||
%define pointer resd
|
||||
%endif
|
||||
|
||||
struc ResampleContext
|
||||
.av_class: pointer 1
|
||||
.filter_bank: pointer 1
|
||||
.filter_length: resd 1
|
||||
.filter_alloc: resd 1
|
||||
.ideal_dst_incr: resd 1
|
||||
.dst_incr: resd 1
|
||||
.dst_incr_div: resd 1
|
||||
.dst_incr_mod: resd 1
|
||||
.index: resd 1
|
||||
.frac: resd 1
|
||||
.src_incr: resd 1
|
||||
.compensation_distance: resd 1
|
||||
.phase_count: resd 1
|
||||
|
||||
; there's a few more here but we only care about the first few
|
||||
endstruc
|
||||
|
||||
SECTION_RODATA
|
||||
|
||||
pf_1: dd 1.0
|
||||
pdbl_1: dq 1.0
|
||||
pd_0x4000: dd 0x4000
|
||||
|
||||
SECTION .text
|
||||
|
||||
; FIXME remove unneeded variables (index_incr, phase_mask)
|
||||
%macro RESAMPLE_FNS 3-5 ; format [float or int16], bps, log2_bps, float op suffix [s or d], 1.0 constant
|
||||
; int resample_common_$format(ResampleContext *ctx, $format *dst,
|
||||
; const $format *src, int size, int update_ctx)
|
||||
%if ARCH_X86_64 ; unix64 and win64
|
||||
cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_count, index, frac, \
|
||||
dst_incr_mod, size, min_filter_count_x4, \
|
||||
min_filter_len_x4, dst_incr_div, src_incr, \
|
||||
phase_mask, dst_end, filter_bank
|
||||
|
||||
; use red-zone for variable storage
|
||||
%define ctx_stackq [rsp-0x8]
|
||||
%define src_stackq [rsp-0x10]
|
||||
%if WIN64
|
||||
%define update_context_stackd r4m
|
||||
%else ; unix64
|
||||
%define update_context_stackd [rsp-0x14]
|
||||
%endif
|
||||
|
||||
; load as many variables in registers as possible; for the rest, store
|
||||
; on stack so that we have 'ctx' available as one extra register
|
||||
mov sized, r3d
|
||||
%if UNIX64
|
||||
mov update_context_stackd, r4d
|
||||
%endif
|
||||
mov indexd, [ctxq+ResampleContext.index]
|
||||
mov fracd, [ctxq+ResampleContext.frac]
|
||||
mov dst_incr_modd, [ctxq+ResampleContext.dst_incr_mod]
|
||||
mov filter_bankq, [ctxq+ResampleContext.filter_bank]
|
||||
mov src_incrd, [ctxq+ResampleContext.src_incr]
|
||||
mov ctx_stackq, ctxq
|
||||
mov min_filter_len_x4d, [ctxq+ResampleContext.filter_length]
|
||||
mov dst_incr_divd, [ctxq+ResampleContext.dst_incr_div]
|
||||
shl min_filter_len_x4d, %3
|
||||
lea dst_endq, [dstq+sizeq*%2]
|
||||
|
||||
%if UNIX64
|
||||
mov ecx, [ctxq+ResampleContext.phase_count]
|
||||
mov edi, [ctxq+ResampleContext.filter_alloc]
|
||||
|
||||
DEFINE_ARGS filter_alloc, dst, src, phase_count, index, frac, dst_incr_mod, \
|
||||
filter, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
|
||||
src_incr, phase_mask, dst_end, filter_bank
|
||||
%elif WIN64
|
||||
mov R9d, [ctxq+ResampleContext.filter_alloc]
|
||||
mov ecx, [ctxq+ResampleContext.phase_count]
|
||||
|
||||
DEFINE_ARGS phase_count, dst, src, filter_alloc, index, frac, dst_incr_mod, \
|
||||
filter, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
|
||||
src_incr, phase_mask, dst_end, filter_bank
|
||||
%endif
|
||||
|
||||
neg min_filter_len_x4q
|
||||
sub filter_bankq, min_filter_len_x4q
|
||||
sub srcq, min_filter_len_x4q
|
||||
mov src_stackq, srcq
|
||||
%else ; x86-32
|
||||
cglobal resample_common_%1, 1, 7, 2, ctx, phase_count, dst, frac, \
|
||||
index, min_filter_length_x4, filter_bank
|
||||
|
||||
; push temp variables to stack
|
||||
%define ctx_stackq r0mp
|
||||
%define src_stackq r2mp
|
||||
%define update_context_stackd r4m
|
||||
|
||||
mov dstq, r1mp
|
||||
mov r3, r3mp
|
||||
lea r3, [dstq+r3*%2]
|
||||
PUSH dword [ctxq+ResampleContext.dst_incr_div]
|
||||
PUSH dword [ctxq+ResampleContext.dst_incr_mod]
|
||||
PUSH dword [ctxq+ResampleContext.filter_alloc]
|
||||
PUSH r3
|
||||
PUSH dword [ctxq+ResampleContext.phase_count] ; unneeded replacement for phase_mask
|
||||
PUSH dword [ctxq+ResampleContext.src_incr]
|
||||
mov min_filter_length_x4d, [ctxq+ResampleContext.filter_length]
|
||||
mov indexd, [ctxq+ResampleContext.index]
|
||||
shl min_filter_length_x4d, %3
|
||||
mov fracd, [ctxq+ResampleContext.frac]
|
||||
neg min_filter_length_x4q
|
||||
mov filter_bankq, [ctxq+ResampleContext.filter_bank]
|
||||
sub r2mp, min_filter_length_x4q
|
||||
sub filter_bankq, min_filter_length_x4q
|
||||
PUSH min_filter_length_x4q
|
||||
PUSH filter_bankq
|
||||
mov phase_countd, [ctxq+ResampleContext.phase_count]
|
||||
|
||||
DEFINE_ARGS src, phase_count, dst, frac, index, min_filter_count_x4, filter
|
||||
|
||||
%define filter_bankq dword [rsp+0x0]
|
||||
%define min_filter_length_x4q dword [rsp+0x4]
|
||||
%define src_incrd dword [rsp+0x8]
|
||||
%define phase_maskd dword [rsp+0xc]
|
||||
%define dst_endq dword [rsp+0x10]
|
||||
%define filter_allocd dword [rsp+0x14]
|
||||
%define dst_incr_modd dword [rsp+0x18]
|
||||
%define dst_incr_divd dword [rsp+0x1c]
|
||||
|
||||
mov srcq, r2mp
|
||||
%endif
|
||||
|
||||
.loop:
|
||||
mov filterd, filter_allocd
|
||||
imul filterd, indexd
|
||||
%if ARCH_X86_64
|
||||
mov min_filter_count_x4q, min_filter_len_x4q
|
||||
lea filterq, [filter_bankq+filterq*%2]
|
||||
%else ; x86-32
|
||||
mov min_filter_count_x4q, filter_bankq
|
||||
lea filterq, [min_filter_count_x4q+filterq*%2]
|
||||
mov min_filter_count_x4q, min_filter_length_x4q
|
||||
%endif
|
||||
%ifidn %1, int16
|
||||
movd m0, [pd_0x4000]
|
||||
%else ; float/double
|
||||
xorps m0, m0, m0
|
||||
%endif
|
||||
|
||||
align 16
|
||||
.inner_loop:
|
||||
movu m1, [srcq+min_filter_count_x4q*1]
|
||||
%ifidn %1, int16
|
||||
%if cpuflag(xop)
|
||||
vpmadcswd m0, m1, [filterq+min_filter_count_x4q*1], m0
|
||||
%else
|
||||
pmaddwd m1, [filterq+min_filter_count_x4q*1]
|
||||
paddd m0, m1
|
||||
%endif
|
||||
%else ; float/double
|
||||
%if cpuflag(fma4) || cpuflag(fma3)
|
||||
fmaddp%4 m0, m1, [filterq+min_filter_count_x4q*1], m0
|
||||
%else
|
||||
mulp%4 m1, m1, [filterq+min_filter_count_x4q*1]
|
||||
addp%4 m0, m0, m1
|
||||
%endif ; cpuflag
|
||||
%endif
|
||||
add min_filter_count_x4q, mmsize
|
||||
js .inner_loop
|
||||
|
||||
%ifidn %1, int16
|
||||
HADDD m0, m1
|
||||
psrad m0, 15
|
||||
add fracd, dst_incr_modd
|
||||
packssdw m0, m0
|
||||
add indexd, dst_incr_divd
|
||||
movd [dstq], m0
|
||||
%else ; float/double
|
||||
; horizontal sum & store
|
||||
%if mmsize == 32
|
||||
vextractf128 xm1, m0, 0x1
|
||||
addp%4 xm0, xm1
|
||||
%endif
|
||||
movhlps xm1, xm0
|
||||
%ifidn %1, float
|
||||
addps xm0, xm1
|
||||
shufps xm1, xm0, xm0, q0001
|
||||
%endif
|
||||
add fracd, dst_incr_modd
|
||||
addp%4 xm0, xm1
|
||||
add indexd, dst_incr_divd
|
||||
movs%4 [dstq], xm0
|
||||
%endif
|
||||
cmp fracd, src_incrd
|
||||
jl .skip
|
||||
sub fracd, src_incrd
|
||||
inc indexd
|
||||
|
||||
%if UNIX64
|
||||
DEFINE_ARGS filter_alloc, dst, src, phase_count, index, frac, dst_incr_mod, \
|
||||
index_incr, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
|
||||
src_incr, phase_mask, dst_end, filter_bank
|
||||
%elif WIN64
|
||||
DEFINE_ARGS phase_count, dst, src, filter_alloc, index, frac, dst_incr_mod, \
|
||||
index_incr, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
|
||||
src_incr, phase_mask, dst_end, filter_bank
|
||||
%else ; x86-32
|
||||
DEFINE_ARGS src, phase_count, dst, frac, index, index_incr
|
||||
%endif
|
||||
|
||||
.skip:
|
||||
add dstq, %2
|
||||
cmp indexd, phase_countd
|
||||
jb .index_skip
|
||||
.index_while:
|
||||
sub indexd, phase_countd
|
||||
lea srcq, [srcq+%2]
|
||||
cmp indexd, phase_countd
|
||||
jnb .index_while
|
||||
.index_skip:
|
||||
cmp dstq, dst_endq
|
||||
jne .loop
|
||||
|
||||
%if ARCH_X86_64
|
||||
DEFINE_ARGS ctx, dst, src, phase_count, index, frac
|
||||
%else ; x86-32
|
||||
DEFINE_ARGS src, ctx, update_context, frac, index
|
||||
%endif
|
||||
|
||||
cmp dword update_context_stackd, 0
|
||||
jz .skip_store
|
||||
; strictly speaking, the function should always return the consumed
|
||||
; number of bytes; however, we only use the value if update_context
|
||||
; is true, so let's just leave it uninitialized otherwise
|
||||
mov ctxq, ctx_stackq
|
||||
movifnidn rax, srcq
|
||||
mov [ctxq+ResampleContext.frac ], fracd
|
||||
sub rax, src_stackq
|
||||
mov [ctxq+ResampleContext.index], indexd
|
||||
shr rax, %3
|
||||
|
||||
.skip_store:
|
||||
%if ARCH_X86_32
|
||||
ADD rsp, 0x20
|
||||
%endif
|
||||
RET
|
||||
|
||||
; int resample_linear_$format(ResampleContext *ctx, float *dst,
|
||||
; const float *src, int size, int update_ctx)
|
||||
%if ARCH_X86_64 ; unix64 and win64
|
||||
%if UNIX64
|
||||
cglobal resample_linear_%1, 0, 15, 5, ctx, dst, phase_mask, phase_count, index, frac, \
|
||||
size, dst_incr_mod, min_filter_count_x4, \
|
||||
min_filter_len_x4, dst_incr_div, src_incr, \
|
||||
src, dst_end, filter_bank
|
||||
|
||||
mov srcq, r2mp
|
||||
%else ; win64
|
||||
cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_count, index, frac, \
|
||||
size, dst_incr_mod, min_filter_count_x4, \
|
||||
min_filter_len_x4, dst_incr_div, src_incr, \
|
||||
dst, dst_end, filter_bank
|
||||
|
||||
mov dstq, r1mp
|
||||
%endif
|
||||
|
||||
; use red-zone for variable storage
|
||||
%define ctx_stackq [rsp-0x8]
|
||||
%define src_stackq [rsp-0x10]
|
||||
%define phase_mask_stackd [rsp-0x14]
|
||||
%if WIN64
|
||||
%define update_context_stackd r4m
|
||||
%else ; unix64
|
||||
%define update_context_stackd [rsp-0x18]
|
||||
%endif
|
||||
|
||||
; load as many variables in registers as possible; for the rest, store
|
||||
; on stack so that we have 'ctx' available as one extra register
|
||||
mov sized, r3d
|
||||
%if UNIX64
|
||||
mov update_context_stackd, r4d
|
||||
%endif
|
||||
mov indexd, [ctxq+ResampleContext.index]
|
||||
mov fracd, [ctxq+ResampleContext.frac]
|
||||
mov dst_incr_modd, [ctxq+ResampleContext.dst_incr_mod]
|
||||
mov filter_bankq, [ctxq+ResampleContext.filter_bank]
|
||||
mov src_incrd, [ctxq+ResampleContext.src_incr]
|
||||
mov ctx_stackq, ctxq
|
||||
mov min_filter_len_x4d, [ctxq+ResampleContext.filter_length]
|
||||
%ifidn %1, int16
|
||||
movd m4, [pd_0x4000]
|
||||
%else ; float/double
|
||||
cvtsi2s%4 xm0, src_incrd
|
||||
movs%4 xm4, [%5]
|
||||
divs%4 xm4, xm0
|
||||
%endif
|
||||
mov dst_incr_divd, [ctxq+ResampleContext.dst_incr_div]
|
||||
shl min_filter_len_x4d, %3
|
||||
lea dst_endq, [dstq+sizeq*%2]
|
||||
|
||||
%if UNIX64
|
||||
mov ecx, [ctxq+ResampleContext.phase_count]
|
||||
mov edi, [ctxq+ResampleContext.filter_alloc]
|
||||
|
||||
DEFINE_ARGS filter_alloc, dst, filter2, phase_count, index, frac, filter1, \
|
||||
dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
|
||||
dst_incr_div, src_incr, src, dst_end, filter_bank
|
||||
%elif WIN64
|
||||
mov R9d, [ctxq+ResampleContext.filter_alloc]
|
||||
mov ecx, [ctxq+ResampleContext.phase_count]
|
||||
|
||||
DEFINE_ARGS phase_count, filter2, src, filter_alloc, index, frac, filter1, \
|
||||
dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
|
||||
dst_incr_div, src_incr, dst, dst_end, filter_bank
|
||||
%endif
|
||||
|
||||
neg min_filter_len_x4q
|
||||
sub filter_bankq, min_filter_len_x4q
|
||||
sub srcq, min_filter_len_x4q
|
||||
mov src_stackq, srcq
|
||||
%else ; x86-32
|
||||
cglobal resample_linear_%1, 1, 7, 5, ctx, min_filter_length_x4, filter2, \
|
||||
frac, index, dst, filter_bank
|
||||
|
||||
; push temp variables to stack
|
||||
%define ctx_stackq r0mp
|
||||
%define src_stackq r2mp
|
||||
%define update_context_stackd r4m
|
||||
|
||||
mov dstq, r1mp
|
||||
mov r3, r3mp
|
||||
lea r3, [dstq+r3*%2]
|
||||
PUSH dword [ctxq+ResampleContext.dst_incr_div]
|
||||
PUSH r3
|
||||
mov r3, dword [ctxq+ResampleContext.filter_alloc]
|
||||
PUSH dword [ctxq+ResampleContext.dst_incr_mod]
|
||||
PUSH r3
|
||||
shl r3, %3
|
||||
PUSH r3
|
||||
mov r3, dword [ctxq+ResampleContext.src_incr]
|
||||
PUSH dword [ctxq+ResampleContext.phase_count] ; unneeded replacement of phase_mask
|
||||
PUSH r3d
|
||||
%ifidn %1, int16
|
||||
movd m4, [pd_0x4000]
|
||||
%else ; float/double
|
||||
cvtsi2s%4 xm0, r3d
|
||||
movs%4 xm4, [%5]
|
||||
divs%4 xm4, xm0
|
||||
%endif
|
||||
mov min_filter_length_x4d, [ctxq+ResampleContext.filter_length]
|
||||
mov indexd, [ctxq+ResampleContext.index]
|
||||
shl min_filter_length_x4d, %3
|
||||
mov fracd, [ctxq+ResampleContext.frac]
|
||||
neg min_filter_length_x4q
|
||||
mov filter_bankq, [ctxq+ResampleContext.filter_bank]
|
||||
sub r2mp, min_filter_length_x4q
|
||||
sub filter_bankq, min_filter_length_x4q
|
||||
PUSH min_filter_length_x4q
|
||||
PUSH filter_bankq
|
||||
PUSH dword [ctxq+ResampleContext.phase_count]
|
||||
|
||||
DEFINE_ARGS filter1, min_filter_count_x4, filter2, frac, index, dst, src
|
||||
|
||||
%define phase_count_stackd dword [rsp+0x0]
|
||||
%define filter_bankq dword [rsp+0x4]
|
||||
%define min_filter_length_x4q dword [rsp+0x8]
|
||||
%define src_incrd dword [rsp+0xc]
|
||||
%define phase_mask_stackd dword [rsp+0x10]
|
||||
%define filter_alloc_x4q dword [rsp+0x14]
|
||||
%define filter_allocd dword [rsp+0x18]
|
||||
%define dst_incr_modd dword [rsp+0x1c]
|
||||
%define dst_endq dword [rsp+0x20]
|
||||
%define dst_incr_divd dword [rsp+0x24]
|
||||
|
||||
mov srcq, r2mp
|
||||
%endif
|
||||
|
||||
.loop:
|
||||
mov filter1d, filter_allocd
|
||||
imul filter1d, indexd
|
||||
%if ARCH_X86_64
|
||||
mov min_filter_count_x4q, min_filter_len_x4q
|
||||
lea filter1q, [filter_bankq+filter1q*%2]
|
||||
lea filter2q, [filter1q+filter_allocq*%2]
|
||||
%else ; x86-32
|
||||
mov min_filter_count_x4q, filter_bankq
|
||||
lea filter1q, [min_filter_count_x4q+filter1q*%2]
|
||||
mov min_filter_count_x4q, min_filter_length_x4q
|
||||
mov filter2q, filter1q
|
||||
add filter2q, filter_alloc_x4q
|
||||
%endif
|
||||
%ifidn %1, int16
|
||||
mova m0, m4
|
||||
mova m2, m4
|
||||
%else ; float/double
|
||||
xorps m0, m0, m0
|
||||
xorps m2, m2, m2
|
||||
%endif
|
||||
|
||||
align 16
|
||||
.inner_loop:
|
||||
movu m1, [srcq+min_filter_count_x4q*1]
|
||||
%ifidn %1, int16
|
||||
%if cpuflag(xop)
|
||||
vpmadcswd m2, m1, [filter2q+min_filter_count_x4q*1], m2
|
||||
vpmadcswd m0, m1, [filter1q+min_filter_count_x4q*1], m0
|
||||
%else
|
||||
pmaddwd m3, m1, [filter2q+min_filter_count_x4q*1]
|
||||
pmaddwd m1, [filter1q+min_filter_count_x4q*1]
|
||||
paddd m2, m3
|
||||
paddd m0, m1
|
||||
%endif ; cpuflag
|
||||
%else ; float/double
|
||||
%if cpuflag(fma4) || cpuflag(fma3)
|
||||
fmaddp%4 m2, m1, [filter2q+min_filter_count_x4q*1], m2
|
||||
fmaddp%4 m0, m1, [filter1q+min_filter_count_x4q*1], m0
|
||||
%else
|
||||
mulp%4 m3, m1, [filter2q+min_filter_count_x4q*1]
|
||||
mulp%4 m1, m1, [filter1q+min_filter_count_x4q*1]
|
||||
addp%4 m2, m2, m3
|
||||
addp%4 m0, m0, m1
|
||||
%endif ; cpuflag
|
||||
%endif
|
||||
add min_filter_count_x4q, mmsize
|
||||
js .inner_loop
|
||||
|
||||
%ifidn %1, int16
|
||||
%if mmsize == 16
|
||||
%if cpuflag(xop)
|
||||
vphadddq m2, m2
|
||||
vphadddq m0, m0
|
||||
%endif
|
||||
pshufd m3, m2, q0032
|
||||
pshufd m1, m0, q0032
|
||||
paddd m2, m3
|
||||
paddd m0, m1
|
||||
%endif
|
||||
%if notcpuflag(xop)
|
||||
PSHUFLW m3, m2, q0032
|
||||
PSHUFLW m1, m0, q0032
|
||||
paddd m2, m3
|
||||
paddd m0, m1
|
||||
%endif
|
||||
psubd m2, m0
|
||||
; This is probably a really bad idea on atom and other machines with a
|
||||
; long transfer latency between GPRs and XMMs (atom). However, it does
|
||||
; make the clip a lot simpler...
|
||||
movd eax, m2
|
||||
add indexd, dst_incr_divd
|
||||
imul fracd
|
||||
idiv src_incrd
|
||||
movd m1, eax
|
||||
add fracd, dst_incr_modd
|
||||
paddd m0, m1
|
||||
psrad m0, 15
|
||||
packssdw m0, m0
|
||||
movd [dstq], m0
|
||||
|
||||
; note that for imul/idiv, I need to move filter to edx/eax for each:
|
||||
; - 32bit: eax=r0[filter1], edx=r2[filter2]
|
||||
; - win64: eax=r6[filter1], edx=r1[todo]
|
||||
; - unix64: eax=r6[filter1], edx=r2[todo]
|
||||
%else ; float/double
|
||||
; val += (v2 - val) * (FELEML) frac / c->src_incr;
|
||||
%if mmsize == 32
|
||||
vextractf128 xm1, m0, 0x1
|
||||
vextractf128 xm3, m2, 0x1
|
||||
addp%4 xm0, xm1
|
||||
addp%4 xm2, xm3
|
||||
%endif
|
||||
cvtsi2s%4 xm1, fracd
|
||||
subp%4 xm2, xm0
|
||||
mulp%4 xm1, xm4
|
||||
shufp%4 xm1, xm1, q0000
|
||||
%if cpuflag(fma4) || cpuflag(fma3)
|
||||
fmaddp%4 xm0, xm2, xm1, xm0
|
||||
%else
|
||||
mulp%4 xm2, xm1
|
||||
addp%4 xm0, xm2
|
||||
%endif ; cpuflag
|
||||
|
||||
; horizontal sum & store
|
||||
movhlps xm1, xm0
|
||||
%ifidn %1, float
|
||||
addps xm0, xm1
|
||||
shufps xm1, xm0, xm0, q0001
|
||||
%endif
|
||||
add fracd, dst_incr_modd
|
||||
addp%4 xm0, xm1
|
||||
add indexd, dst_incr_divd
|
||||
movs%4 [dstq], xm0
|
||||
%endif
|
||||
cmp fracd, src_incrd
|
||||
jl .skip
|
||||
sub fracd, src_incrd
|
||||
inc indexd
|
||||
|
||||
%if UNIX64
|
||||
DEFINE_ARGS filter_alloc, dst, filter2, phase_count, index, frac, index_incr, \
|
||||
dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
|
||||
dst_incr_div, src_incr, src, dst_end, filter_bank
|
||||
%elif WIN64
|
||||
DEFINE_ARGS phase_count, filter2, src, filter_alloc, index, frac, index_incr, \
|
||||
dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
|
||||
dst_incr_div, src_incr, dst, dst_end, filter_bank
|
||||
%else ; x86-32
|
||||
DEFINE_ARGS filter1, phase_count, index_incr, frac, index, dst, src
|
||||
%endif
|
||||
|
||||
.skip:
|
||||
%if ARCH_X86_32
|
||||
mov phase_countd, phase_count_stackd
|
||||
%endif
|
||||
add dstq, %2
|
||||
cmp indexd, phase_countd
|
||||
jb .index_skip
|
||||
.index_while:
|
||||
sub indexd, phase_countd
|
||||
lea srcq, [srcq+%2]
|
||||
cmp indexd, phase_countd
|
||||
jnb .index_while
|
||||
.index_skip:
|
||||
cmp dstq, dst_endq
|
||||
jne .loop
|
||||
|
||||
%if UNIX64
|
||||
DEFINE_ARGS ctx, dst, filter2, phase_count, index, frac, index_incr, \
|
||||
dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
|
||||
dst_incr_div, src_incr, src, dst_end, filter_bank
|
||||
%elif WIN64
|
||||
DEFINE_ARGS ctx, filter2, src, phase_count, index, frac, index_incr, \
|
||||
dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
|
||||
dst_incr_div, src_incr, dst, dst_end, filter_bank
|
||||
%else ; x86-32
|
||||
DEFINE_ARGS filter1, ctx, update_context, frac, index, dst, src
|
||||
%endif
|
||||
|
||||
cmp dword update_context_stackd, 0
|
||||
jz .skip_store
|
||||
; strictly speaking, the function should always return the consumed
|
||||
; number of bytes; however, we only use the value if update_context
|
||||
; is true, so let's just leave it uninitialized otherwise
|
||||
mov ctxq, ctx_stackq
|
||||
movifnidn rax, srcq
|
||||
mov [ctxq+ResampleContext.frac ], fracd
|
||||
sub rax, src_stackq
|
||||
mov [ctxq+ResampleContext.index], indexd
|
||||
shr rax, %3
|
||||
|
||||
.skip_store:
|
||||
%if ARCH_X86_32
|
||||
ADD rsp, 0x28
|
||||
%endif
|
||||
RET
|
||||
%endmacro
|
||||
|
||||
INIT_XMM sse
|
||||
RESAMPLE_FNS float, 4, 2, s, pf_1
|
||||
|
||||
%if HAVE_AVX_EXTERNAL
|
||||
INIT_YMM avx
|
||||
RESAMPLE_FNS float, 4, 2, s, pf_1
|
||||
%endif
|
||||
%if HAVE_FMA3_EXTERNAL
|
||||
INIT_YMM fma3
|
||||
RESAMPLE_FNS float, 4, 2, s, pf_1
|
||||
%endif
|
||||
%if HAVE_FMA4_EXTERNAL
|
||||
INIT_XMM fma4
|
||||
RESAMPLE_FNS float, 4, 2, s, pf_1
|
||||
%endif
|
||||
|
||||
%if ARCH_X86_32
|
||||
INIT_MMX mmxext
|
||||
RESAMPLE_FNS int16, 2, 1
|
||||
%endif
|
||||
|
||||
INIT_XMM sse2
|
||||
RESAMPLE_FNS int16, 2, 1
|
||||
%if HAVE_XOP_EXTERNAL
|
||||
INIT_XMM xop
|
||||
RESAMPLE_FNS int16, 2, 1
|
||||
%endif
|
||||
|
||||
INIT_XMM sse2
|
||||
RESAMPLE_FNS double, 8, 3, d, pdbl_1
|
||||
|
||||
%if HAVE_AVX_EXTERNAL
|
||||
INIT_YMM avx
|
||||
RESAMPLE_FNS double, 8, 3, d, pdbl_1
|
||||
%endif
|
||||
%if HAVE_FMA3_EXTERNAL
|
||||
INIT_YMM fma3
|
||||
RESAMPLE_FNS double, 8, 3, d, pdbl_1
|
||||
%endif
|
Loading…
Add table
Add a link
Reference in a new issue