/* * Copyright (c) 2013 RISC OS Open Ltd * Author: Ben Avison * * This file is part of Libav. * * Libav 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. * * Libav 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 Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/arm/asm.S" POUT .req a1 PIN .req a2 PCOEF .req a3 DECIFACTOR .req a4 OLDFPSCR .req a4 COUNTER .req ip SCALE32 .req s28 @ use vector of 4 in place of 9th scalar when decifactor=32 / JMAX=8 SCALE64 .req s0 @ spare register in scalar bank when decifactor=64 / JMAX=4 IN0 .req s4 IN1 .req s5 IN2 .req s6 IN3 .req s7 IN4 .req s0 IN5 .req s1 IN6 .req s2 IN7 .req s3 COEF0 .req s8 @ coefficient elements COEF1 .req s9 COEF2 .req s10 COEF3 .req s11 COEF4 .req s12 COEF5 .req s13 COEF6 .req s14 COEF7 .req s15 ACCUM0 .req s16 @ double-buffered multiply-accumulate results ACCUM4 .req s20 POST0 .req s24 @ do long-latency post-multiply in this vector in parallel POST1 .req s25 POST2 .req s26 POST3 .req s27 .macro inner_loop decifactor, dir, tail, head .ifc "\dir","up" .set X, 0 .set Y, 4 .else .set X, 4*JMAX*4 - 4 .set Y, -4 .endif .ifnc "\head","" vldr COEF0, [PCOEF, #X + (0*JMAX + 0) * Y] vldr COEF1, [PCOEF, #X + (1*JMAX + 0) * Y] vldr COEF2, [PCOEF, #X + (2*JMAX + 0) * Y] vldr COEF3, [PCOEF, #X + (3*JMAX + 0) * Y] .endif .ifnc "\tail","" vadd.f POST0, ACCUM0, ACCUM4 @ vector operation .endif .ifnc "\head","" vmul.f ACCUM0, COEF0, IN0 @ vector = vector * scalar vldr COEF4, [PCOEF, #X + (0*JMAX + 1) * Y] vldr COEF5, [PCOEF, #X + (1*JMAX + 1) * Y] vldr COEF6, [PCOEF, #X + (2*JMAX + 1) * Y] .endif .ifnc "\tail","" vmul.f POST0, POST0, SCALE\decifactor @ vector operation (SCALE may be scalar) .endif .ifnc "\head","" vldr COEF7, [PCOEF, #X + (3*JMAX + 1) * Y] .ifc "\tail","" vmul.f ACCUM4, COEF4, IN1 @ vector operation .endif vldr COEF0, [PCOEF, #X + (0*JMAX + 2) * Y] vldr COEF1, [PCOEF, #X + (1*JMAX + 2) * Y] .ifnc "\tail","" vmul.f ACCUM4, COEF4, IN1 @ vector operation .endif vldr COEF2, [PCOEF, #X + (2*JMAX + 2) * Y] vldr COEF3, [PCOEF, #X + (3*JMAX + 2) * Y] .endif .ifnc "\tail","" vstmia POUT!, {POST0-POST3} .endif .ifnc "\head","" vmla.f ACCUM0, COEF0, IN2 @ vector = vector * scalar vldr COEF4, [PCOEF, #X + (0*JMAX + 3) * Y] vldr COEF5, [PCOEF, #X + (1*JMAX + 3) * Y] vldr COEF6, [PCOEF, #X + (2*JMAX + 3) * Y] vldr COEF7, [PCOEF, #X + (3*JMAX + 3) * Y] vmla.f ACCUM4, COEF4, IN3 @ vector = vector * scalar .if \decifactor == 32 vldr COEF0, [PCOEF, #X + (0*JMAX + 4) * Y] vldr COEF1, [PCOEF, #X + (1*JMAX + 4) * Y] vldr COEF2, [PCOEF, #X + (2*JMAX + 4) * Y] vldr COEF3, [PCOEF, #X + (3*JMAX + 4) * Y] vmla.f ACCUM0, COEF0, IN4 @ vector = vector * scalar vldr COEF4, [PCOEF, #X + (0*JMAX + 5) * Y] vldr COEF5, [PCOEF, #X + (1*JMAX + 5) * Y] vldr COEF6, [PCOEF, #X + (2*JMAX + 5) * Y] vldr COEF7, [PCOEF, #X + (3*JMAX + 5) * Y] vmla.f ACCUM4, COEF4, IN5 @ vector = vector * scalar vldr COEF0, [PCOEF, #X + (0*JMAX + 6) * Y] vldr COEF1, [PCOEF, #X + (1*JMAX + 6) * Y] vldr COEF2, [PCOEF, #X + (2*JMAX + 6) * Y] vldr COEF3, [PCOEF, #X + (3*JMAX + 6) * Y] vmla.f ACCUM0, COEF0, IN6 @ vector = vector * scalar vldr COEF4, [PCOEF, #X + (0*JMAX + 7) * Y] vldr COEF5, [PCOEF, #X + (1*JMAX + 7) * Y] vldr COEF6, [PCOEF, #X + (2*JMAX + 7) * Y] vldr COEF7, [PCOEF, #X + (3*JMAX + 7) * Y] vmla.f ACCUM4, COEF4, IN7 @ vector = vector * scalar .endif .endif .endm .macro dca_lfe_fir decifactor .if \decifactor == 32 .set JMAX, 8 vpush {s16-s31} vmov SCALE32, s0 @ duplicate scalar across vector vldr IN4, [PIN, #-4*4] vldr IN5, [PIN, #-5*4] vldr IN6, [PIN, #-6*4] vldr IN7, [PIN, #-7*4] .else .set JMAX, 4 vpush {s16-s27} .endif mov COUNTER, #\decifactor/4 - 1 inner_loop \decifactor, up,, head 1: add PCOEF, PCOEF, #4*JMAX*4 subs COUNTER, COUNTER, #1 inner_loop \decifactor, up, tail, head bne 1b inner_loop \decifactor, up, tail mov COUNTER, #\decifactor/4 - 1 inner_loop \decifactor, down,, head 1: sub PCOEF, PCOEF, #4*JMAX*4 subs COUNTER, COUNTER, #1 inner_loop \decifactor, down, tail, head bne 1b inner_loop \decifactor, down, tail .if \decifactor == 32 vpop {s16-s31} .else vpop {s16-s27} .endif fmxr FPSCR, OLDFPSCR bx lr .endm /* void ff_dca_lfe_fir_vfp(float *out, const float *in, const float *coefs, * int decifactor, float scale) */ function ff_dca_lfe_fir_vfp, export=1 teq DECIFACTOR, #32 fmrx OLDFPSCR, FPSCR ldr ip, =0x03030000 @ RunFast mode, short vectors of length 4, stride 1 fmxr FPSCR, ip NOVFP vldr s0, [sp] vldr IN0, [PIN, #-0*4] vldr IN1, [PIN, #-1*4] vldr IN2, [PIN, #-2*4] vldr IN3, [PIN, #-3*4] beq 32f 64: dca_lfe_fir 64 .ltorg 32: dca_lfe_fir 32 endfunc .unreq POUT .unreq PIN .unreq PCOEF .unreq DECIFACTOR .unreq OLDFPSCR .unreq COUNTER .unreq SCALE32 .unreq SCALE64 .unreq IN0 .unreq IN1 .unreq IN2 .unreq IN3 .unreq IN4 .unreq IN5 .unreq IN6 .unreq IN7 .unreq COEF0 .unreq COEF1 .unreq COEF2 .unreq COEF3 .unreq COEF4 .unreq COEF5 .unreq COEF6 .unreq COEF7 .unreq ACCUM0 .unreq ACCUM4 .unreq POST0 .unreq POST1 .unreq POST2 .unreq POST3