dcadsp: split lfe_dir cases
[ffmpeg.git] / libavcodec / arm / dcadsp_vfp.S
1 /*
2  * Copyright (c) 2013 RISC OS Open Ltd
3  * Author: Ben Avison <bavison@riscosopen.org>
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/arm/asm.S"
23
24 POUT          .req    a1
25 PIN           .req    a2
26 PCOEF         .req    a3
27 OLDFPSCR      .req    a4
28 COUNTER       .req    ip
29
30 SCALE32       .req    s28  @ use vector of 4 in place of 9th scalar when decifactor=32 / JMAX=8
31 SCALE64       .req    s0   @ spare register in scalar bank when decifactor=64 / JMAX=4
32 IN0           .req    s4
33 IN1           .req    s5
34 IN2           .req    s6
35 IN3           .req    s7
36 IN4           .req    s0
37 IN5           .req    s1
38 IN6           .req    s2
39 IN7           .req    s3
40 COEF0         .req    s8   @ coefficient elements
41 COEF1         .req    s9
42 COEF2         .req    s10
43 COEF3         .req    s11
44 COEF4         .req    s12
45 COEF5         .req    s13
46 COEF6         .req    s14
47 COEF7         .req    s15
48 ACCUM0        .req    s16  @ double-buffered multiply-accumulate results
49 ACCUM4        .req    s20
50 POST0         .req    s24  @ do long-latency post-multiply in this vector in parallel
51 POST1         .req    s25
52 POST2         .req    s26
53 POST3         .req    s27
54
55
56 .macro inner_loop  decifactor, dir, tail, head
57  .ifc "\dir","up"
58   .set X, 0
59   .set Y, 4
60  .else
61   .set X, 4*JMAX*4 - 4
62   .set Y, -4
63  .endif
64  .ifnc "\head",""
65         vldr    COEF0, [PCOEF, #X + (0*JMAX + 0) * Y]
66         vldr    COEF1, [PCOEF, #X + (1*JMAX + 0) * Y]
67         vldr    COEF2, [PCOEF, #X + (2*JMAX + 0) * Y]
68         vldr    COEF3, [PCOEF, #X + (3*JMAX + 0) * Y]
69  .endif
70  .ifnc "\tail",""
71         vadd.f  POST0, ACCUM0, ACCUM4   @ vector operation
72  .endif
73  .ifnc "\head",""
74         vmul.f  ACCUM0, COEF0, IN0      @ vector = vector * scalar
75         vldr    COEF4, [PCOEF, #X + (0*JMAX + 1) * Y]
76         vldr    COEF5, [PCOEF, #X + (1*JMAX + 1) * Y]
77         vldr    COEF6, [PCOEF, #X + (2*JMAX + 1) * Y]
78  .endif
79  .ifnc "\tail",""
80         vmul.f  POST0, POST0, SCALE\decifactor  @ vector operation (SCALE may be scalar)
81  .endif
82  .ifnc "\head",""
83         vldr    COEF7, [PCOEF, #X + (3*JMAX + 1) * Y]
84    .ifc "\tail",""
85         vmul.f  ACCUM4, COEF4, IN1      @ vector operation
86    .endif
87         vldr    COEF0, [PCOEF, #X + (0*JMAX + 2) * Y]
88         vldr    COEF1, [PCOEF, #X + (1*JMAX + 2) * Y]
89    .ifnc "\tail",""
90         vmul.f  ACCUM4, COEF4, IN1      @ vector operation
91    .endif
92         vldr    COEF2, [PCOEF, #X + (2*JMAX + 2) * Y]
93         vldr    COEF3, [PCOEF, #X + (3*JMAX + 2) * Y]
94  .endif
95  .ifnc "\tail",""
96         vstmia  POUT!, {POST0-POST3}
97  .endif
98  .ifnc "\head",""
99         vmla.f  ACCUM0, COEF0, IN2      @ vector = vector * scalar
100         vldr    COEF4, [PCOEF, #X + (0*JMAX + 3) * Y]
101         vldr    COEF5, [PCOEF, #X + (1*JMAX + 3) * Y]
102         vldr    COEF6, [PCOEF, #X + (2*JMAX + 3) * Y]
103         vldr    COEF7, [PCOEF, #X + (3*JMAX + 3) * Y]
104         vmla.f  ACCUM4, COEF4, IN3      @ vector = vector * scalar
105   .if \decifactor == 32
106         vldr    COEF0, [PCOEF, #X + (0*JMAX + 4) * Y]
107         vldr    COEF1, [PCOEF, #X + (1*JMAX + 4) * Y]
108         vldr    COEF2, [PCOEF, #X + (2*JMAX + 4) * Y]
109         vldr    COEF3, [PCOEF, #X + (3*JMAX + 4) * Y]
110         vmla.f  ACCUM0, COEF0, IN4      @ vector = vector * scalar
111         vldr    COEF4, [PCOEF, #X + (0*JMAX + 5) * Y]
112         vldr    COEF5, [PCOEF, #X + (1*JMAX + 5) * Y]
113         vldr    COEF6, [PCOEF, #X + (2*JMAX + 5) * Y]
114         vldr    COEF7, [PCOEF, #X + (3*JMAX + 5) * Y]
115         vmla.f  ACCUM4, COEF4, IN5      @ vector = vector * scalar
116         vldr    COEF0, [PCOEF, #X + (0*JMAX + 6) * Y]
117         vldr    COEF1, [PCOEF, #X + (1*JMAX + 6) * Y]
118         vldr    COEF2, [PCOEF, #X + (2*JMAX + 6) * Y]
119         vldr    COEF3, [PCOEF, #X + (3*JMAX + 6) * Y]
120         vmla.f  ACCUM0, COEF0, IN6      @ vector = vector * scalar
121         vldr    COEF4, [PCOEF, #X + (0*JMAX + 7) * Y]
122         vldr    COEF5, [PCOEF, #X + (1*JMAX + 7) * Y]
123         vldr    COEF6, [PCOEF, #X + (2*JMAX + 7) * Y]
124         vldr    COEF7, [PCOEF, #X + (3*JMAX + 7) * Y]
125         vmla.f  ACCUM4, COEF4, IN7      @ vector = vector * scalar
126   .endif
127  .endif
128 .endm
129
130 .macro dca_lfe_fir  decifactor
131 function ff_dca_lfe_fir\decifactor\()_vfp, export=1
132 NOVFP   vmov    s0, r3
133         fmrx    OLDFPSCR, FPSCR
134         ldr     ip, =0x03030000         @ RunFast mode, short vectors of length 4, stride 1
135         fmxr    FPSCR, ip
136         vldr    IN0, [PIN, #-0*4]
137         vldr    IN1, [PIN, #-1*4]
138         vldr    IN2, [PIN, #-2*4]
139         vldr    IN3, [PIN, #-3*4]
140  .if \decifactor == 32
141   .set JMAX, 8
142         vpush   {s16-s31}
143         vmov    SCALE32, s0             @ duplicate scalar across vector
144         vldr    IN4, [PIN, #-4*4]
145         vldr    IN5, [PIN, #-5*4]
146         vldr    IN6, [PIN, #-6*4]
147         vldr    IN7, [PIN, #-7*4]
148  .else
149   .set JMAX, 4
150         vpush   {s16-s27}
151  .endif
152
153         mov     COUNTER, #\decifactor/4 - 1
154         inner_loop  \decifactor, up,, head
155 1:      add     PCOEF, PCOEF, #4*JMAX*4
156         subs    COUNTER, COUNTER, #1
157         inner_loop  \decifactor, up, tail, head
158         bne     1b
159         inner_loop  \decifactor, up, tail
160
161         mov     COUNTER, #\decifactor/4 - 1
162         inner_loop  \decifactor, down,, head
163 1:      sub     PCOEF, PCOEF, #4*JMAX*4
164         subs    COUNTER, COUNTER, #1
165         inner_loop  \decifactor, down, tail, head
166         bne     1b
167         inner_loop  \decifactor, down, tail
168
169  .if \decifactor == 32
170         vpop    {s16-s31}
171  .else
172         vpop    {s16-s27}
173  .endif
174         fmxr    FPSCR, OLDFPSCR
175         bx      lr
176 endfunc
177 .endm
178
179         dca_lfe_fir  64
180  .ltorg
181         dca_lfe_fir  32
182
183         .unreq  POUT
184         .unreq  PIN
185         .unreq  PCOEF
186         .unreq  OLDFPSCR
187         .unreq  COUNTER
188
189         .unreq  SCALE32
190         .unreq  SCALE64
191         .unreq  IN0
192         .unreq  IN1
193         .unreq  IN2
194         .unreq  IN3
195         .unreq  IN4
196         .unreq  IN5
197         .unreq  IN6
198         .unreq  IN7
199         .unreq  COEF0
200         .unreq  COEF1
201         .unreq  COEF2
202         .unreq  COEF3
203         .unreq  COEF4
204         .unreq  COEF5
205         .unreq  COEF6
206         .unreq  COEF7
207         .unreq  ACCUM0
208         .unreq  ACCUM4
209         .unreq  POST0
210         .unreq  POST1
211         .unreq  POST2
212         .unreq  POST3
213
214
215 IN      .req    a1
216 SBACT   .req    a2
217 OLDFPSCR .req   a3
218 IMDCT   .req    a4
219 WINDOW  .req    v1
220 OUT     .req    v2
221 BUF     .req    v3
222 SCALEINT .req   v4 @ only used in softfp case
223 COUNT   .req    v5
224
225 SCALE   .req    s0
226
227 /* Stack layout differs in softfp and hardfp cases:
228  *
229  * hardfp
230  *      fp -> 6 arg words saved by caller
231  *            a3,a4,v1-v3,v5,fp,lr on entry (a3 just to pad to 8 bytes)
232  *            s16-s23 on entry
233  *            align 16
234  *     buf -> 8*32*4 bytes buffer
235  *            s0 on entry
236  *      sp -> 3 arg words for callee
237  *
238  * softfp
239  *      fp -> 7 arg words saved by caller
240  *            a4,v1-v5,fp,lr on entry
241  *            s16-s23 on entry
242  *            align 16
243  *     buf -> 8*32*4 bytes buffer
244  *      sp -> 4 arg words for callee
245  */
246
247 /* void ff_dca_qmf_32_subbands_vfp(float samples_in[32][8], int sb_act,
248  *                                 SynthFilterContext *synth, FFTContext *imdct,
249  *                                 float (*synth_buf_ptr)[512],
250  *                                 int *synth_buf_offset, float (*synth_buf2)[32],
251  *                                 const float (*window)[512], float *samples_out,
252  *                                 float (*raXin)[32], float scale);
253  */
254 function ff_dca_qmf_32_subbands_vfp, export=1
255 VFP     push    {a3-a4,v1-v3,v5,fp,lr}
256 NOVFP   push    {a4,v1-v5,fp,lr}
257         add     fp, sp, #8*4
258         vpush   {s16-s23}
259         @ The buffer pointed at by raXin isn't big enough for us to do a
260         @ complete matrix transposition as we want to, so allocate an
261         @ alternative buffer from the stack. Align to 4 words for speed.
262         sub     BUF, sp, #8*32*4
263         bic     BUF, BUF, #15
264         mov     sp, BUF
265         ldr     lr, =0x03330000     @ RunFast mode, short vectors of length 4, stride 2
266         fmrx    OLDFPSCR, FPSCR
267         fmxr    FPSCR, lr
268         @ COUNT is used to count down 2 things at once:
269         @ bits 0-4 are the number of word pairs remaining in the output row
270         @ bits 5-31 are the number of words to copy (with possible negation)
271         @   from the source matrix before we start zeroing the remainder
272         mov     COUNT, #(-4 << 5) + 16
273         adds    COUNT, COUNT, SBACT, lsl #5
274         bmi     2f
275 1:
276         vldr    s8,  [IN, #(0*8+0)*4]
277         vldr    s10, [IN, #(0*8+1)*4]
278         vldr    s12, [IN, #(0*8+2)*4]
279         vldr    s14, [IN, #(0*8+3)*4]
280         vldr    s16, [IN, #(0*8+4)*4]
281         vldr    s18, [IN, #(0*8+5)*4]
282         vldr    s20, [IN, #(0*8+6)*4]
283         vldr    s22, [IN, #(0*8+7)*4]
284         vneg.f  s8, s8
285         vldr    s9,  [IN, #(1*8+0)*4]
286         vldr    s11, [IN, #(1*8+1)*4]
287         vldr    s13, [IN, #(1*8+2)*4]
288         vldr    s15, [IN, #(1*8+3)*4]
289         vneg.f  s16, s16
290         vldr    s17, [IN, #(1*8+4)*4]
291         vldr    s19, [IN, #(1*8+5)*4]
292         vldr    s21, [IN, #(1*8+6)*4]
293         vldr    s23, [IN, #(1*8+7)*4]
294         vstr    d4,  [BUF, #(0*32+0)*4]
295         vstr    d5,  [BUF, #(1*32+0)*4]
296         vstr    d6,  [BUF, #(2*32+0)*4]
297         vstr    d7,  [BUF, #(3*32+0)*4]
298         vstr    d8,  [BUF, #(4*32+0)*4]
299         vstr    d9,  [BUF, #(5*32+0)*4]
300         vstr    d10, [BUF, #(6*32+0)*4]
301         vstr    d11, [BUF, #(7*32+0)*4]
302         vldr    s9,  [IN, #(3*8+0)*4]
303         vldr    s11, [IN, #(3*8+1)*4]
304         vldr    s13, [IN, #(3*8+2)*4]
305         vldr    s15, [IN, #(3*8+3)*4]
306         vldr    s17, [IN, #(3*8+4)*4]
307         vldr    s19, [IN, #(3*8+5)*4]
308         vldr    s21, [IN, #(3*8+6)*4]
309         vldr    s23, [IN, #(3*8+7)*4]
310         vneg.f  s9, s9
311         vldr    s8,  [IN, #(2*8+0)*4]
312         vldr    s10, [IN, #(2*8+1)*4]
313         vldr    s12, [IN, #(2*8+2)*4]
314         vldr    s14, [IN, #(2*8+3)*4]
315         vneg.f  s17, s17
316         vldr    s16, [IN, #(2*8+4)*4]
317         vldr    s18, [IN, #(2*8+5)*4]
318         vldr    s20, [IN, #(2*8+6)*4]
319         vldr    s22, [IN, #(2*8+7)*4]
320         vstr    d4,  [BUF, #(0*32+2)*4]
321         vstr    d5,  [BUF, #(1*32+2)*4]
322         vstr    d6,  [BUF, #(2*32+2)*4]
323         vstr    d7,  [BUF, #(3*32+2)*4]
324         vstr    d8,  [BUF, #(4*32+2)*4]
325         vstr    d9,  [BUF, #(5*32+2)*4]
326         vstr    d10, [BUF, #(6*32+2)*4]
327         vstr    d11, [BUF, #(7*32+2)*4]
328         add     IN, IN, #4*8*4
329         add     BUF, BUF, #4*4
330         subs    COUNT, COUNT, #(4 << 5) + 2
331         bpl     1b
332 2:      @ Now deal with trailing < 4 samples
333         adds    COUNT, COUNT, #3 << 5
334         bmi     4f  @ sb_act was a multiple of 4
335         bics    lr, COUNT, #0x1F
336         bne     3f
337         @ sb_act was n*4+1
338         vldr    s8,  [IN, #(0*8+0)*4]
339         vldr    s10, [IN, #(0*8+1)*4]
340         vldr    s12, [IN, #(0*8+2)*4]
341         vldr    s14, [IN, #(0*8+3)*4]
342         vldr    s16, [IN, #(0*8+4)*4]
343         vldr    s18, [IN, #(0*8+5)*4]
344         vldr    s20, [IN, #(0*8+6)*4]
345         vldr    s22, [IN, #(0*8+7)*4]
346         vneg.f  s8, s8
347         vldr    s9,  zero
348         vldr    s11, zero
349         vldr    s13, zero
350         vldr    s15, zero
351         vneg.f  s16, s16
352         vldr    s17, zero
353         vldr    s19, zero
354         vldr    s21, zero
355         vldr    s23, zero
356         vstr    d4,  [BUF, #(0*32+0)*4]
357         vstr    d5,  [BUF, #(1*32+0)*4]
358         vstr    d6,  [BUF, #(2*32+0)*4]
359         vstr    d7,  [BUF, #(3*32+0)*4]
360         vstr    d8,  [BUF, #(4*32+0)*4]
361         vstr    d9,  [BUF, #(5*32+0)*4]
362         vstr    d10, [BUF, #(6*32+0)*4]
363         vstr    d11, [BUF, #(7*32+0)*4]
364         add     BUF, BUF, #2*4
365         sub     COUNT, COUNT, #1
366         b       4f
367 3:      @ sb_act was n*4+2 or n*4+3, so do the first 2
368         vldr    s8,  [IN, #(0*8+0)*4]
369         vldr    s10, [IN, #(0*8+1)*4]
370         vldr    s12, [IN, #(0*8+2)*4]
371         vldr    s14, [IN, #(0*8+3)*4]
372         vldr    s16, [IN, #(0*8+4)*4]
373         vldr    s18, [IN, #(0*8+5)*4]
374         vldr    s20, [IN, #(0*8+6)*4]
375         vldr    s22, [IN, #(0*8+7)*4]
376         vneg.f  s8, s8
377         vldr    s9,  [IN, #(1*8+0)*4]
378         vldr    s11, [IN, #(1*8+1)*4]
379         vldr    s13, [IN, #(1*8+2)*4]
380         vldr    s15, [IN, #(1*8+3)*4]
381         vneg.f  s16, s16
382         vldr    s17, [IN, #(1*8+4)*4]
383         vldr    s19, [IN, #(1*8+5)*4]
384         vldr    s21, [IN, #(1*8+6)*4]
385         vldr    s23, [IN, #(1*8+7)*4]
386         vstr    d4,  [BUF, #(0*32+0)*4]
387         vstr    d5,  [BUF, #(1*32+0)*4]
388         vstr    d6,  [BUF, #(2*32+0)*4]
389         vstr    d7,  [BUF, #(3*32+0)*4]
390         vstr    d8,  [BUF, #(4*32+0)*4]
391         vstr    d9,  [BUF, #(5*32+0)*4]
392         vstr    d10, [BUF, #(6*32+0)*4]
393         vstr    d11, [BUF, #(7*32+0)*4]
394         add     BUF, BUF, #2*4
395         sub     COUNT, COUNT, #(2 << 5) + 1
396         bics    lr, COUNT, #0x1F
397         bne     4f
398         @ sb_act was n*4+3
399         vldr    s8,  [IN, #(2*8+0)*4]
400         vldr    s10, [IN, #(2*8+1)*4]
401         vldr    s12, [IN, #(2*8+2)*4]
402         vldr    s14, [IN, #(2*8+3)*4]
403         vldr    s16, [IN, #(2*8+4)*4]
404         vldr    s18, [IN, #(2*8+5)*4]
405         vldr    s20, [IN, #(2*8+6)*4]
406         vldr    s22, [IN, #(2*8+7)*4]
407         vldr    s9,  zero
408         vldr    s11, zero
409         vldr    s13, zero
410         vldr    s15, zero
411         vldr    s17, zero
412         vldr    s19, zero
413         vldr    s21, zero
414         vldr    s23, zero
415         vstr    d4,  [BUF, #(0*32+0)*4]
416         vstr    d5,  [BUF, #(1*32+0)*4]
417         vstr    d6,  [BUF, #(2*32+0)*4]
418         vstr    d7,  [BUF, #(3*32+0)*4]
419         vstr    d8,  [BUF, #(4*32+0)*4]
420         vstr    d9,  [BUF, #(5*32+0)*4]
421         vstr    d10, [BUF, #(6*32+0)*4]
422         vstr    d11, [BUF, #(7*32+0)*4]
423         add     BUF, BUF, #2*4
424         sub     COUNT, COUNT, #1
425 4:      @ Now fill the remainder with 0
426         vldr    s8, zero
427         vldr    s9, zero
428         ands    COUNT, COUNT, #0x1F
429         beq     6f
430 5:      vstr    d4, [BUF, #(0*32+0)*4]
431         vstr    d4, [BUF, #(1*32+0)*4]
432         vstr    d4, [BUF, #(2*32+0)*4]
433         vstr    d4, [BUF, #(3*32+0)*4]
434         vstr    d4, [BUF, #(4*32+0)*4]
435         vstr    d4, [BUF, #(5*32+0)*4]
436         vstr    d4, [BUF, #(6*32+0)*4]
437         vstr    d4, [BUF, #(7*32+0)*4]
438         add     BUF, BUF, #2*4
439         subs    COUNT, COUNT, #1
440         bne     5b
441 6:
442         fmxr    FPSCR, OLDFPSCR
443         ldr     WINDOW, [fp, #3*4]
444         ldr     OUT, [fp, #4*4]
445         sub     BUF, BUF, #32*4
446 NOVFP   ldr     SCALEINT, [fp, #6*4]
447         mov     COUNT, #8
448 VFP     vpush   {SCALE}
449 VFP     sub     sp, sp, #3*4
450 NOVFP   sub     sp, sp, #4*4
451 7:
452 VFP     ldr     a1, [fp, #-7*4]     @ imdct
453 NOVFP   ldr     a1, [fp, #-8*4]
454         ldmia   fp, {a2-a4}
455 VFP     stmia   sp, {WINDOW, OUT, BUF}
456 NOVFP   stmia   sp, {WINDOW, OUT, BUF, SCALEINT}
457 VFP     vldr    SCALE, [sp, #3*4]
458         bl      X(ff_synth_filter_float_vfp)
459         add     OUT, OUT, #32*4
460         add     BUF, BUF, #32*4
461         subs    COUNT, COUNT, #1
462         bne     7b
463
464 A       sub     sp, fp, #(8+8)*4
465 T       sub     fp, fp, #(8+8)*4
466 T       mov     sp, fp
467         vpop    {s16-s23}
468 VFP     pop     {a3-a4,v1-v3,v5,fp,pc}
469 NOVFP   pop     {a4,v1-v5,fp,pc}
470 endfunc
471
472         .unreq  IN
473         .unreq  SBACT
474         .unreq  OLDFPSCR
475         .unreq  IMDCT
476         .unreq  WINDOW
477         .unreq  OUT
478         .unreq  BUF
479         .unreq  SCALEINT
480         .unreq  COUNT
481
482         .unreq  SCALE
483
484         .align 2
485 zero:   .word   0