Merge commit 'ae81576414f2d2083d3118fb4abe1ebc5a7a4c54'
[ffmpeg.git] / libavcodec / arm / fft_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 FFmpeg.
6  *
7  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 @ The fftx_internal_vfp versions of the functions obey a modified AAPCS:
25 @ VFP is in RunFast mode, vector length 4, stride 1 thoroughout, and
26 @ all single-precision VFP registers may be corrupted on exit. The a2
27 @ register may not be clobbered in these functions, as it holds the
28 @ stored original FPSCR.
29
30 function ff_fft_calc_vfp, export=1
31         ldr     ip, [a1, #0]    @ nbits
32         mov     a1, a2
33 A       ldr     pc, [pc, ip, lsl #2]
34 A       .word   0
35 A       .word   0
36 A       .word   0
37 T       movrel  a2, (fft_tab_vfp - 8)
38 T       ldr     pc, [a2, ip, lsl #2]
39 T endfunc
40 T const fft_tab_vfp
41         .word   fft4_vfp
42         .word   fft8_vfp
43         .word   X(ff_fft16_vfp)     @ this one alone is exported
44         .word   fft32_vfp
45         .word   fft64_vfp
46         .word   fft128_vfp
47         .word   fft256_vfp
48         .word   fft512_vfp
49         .word   fft1024_vfp
50         .word   fft2048_vfp
51         .word   fft4096_vfp
52         .word   fft8192_vfp
53         .word   fft16384_vfp
54         .word   fft32768_vfp
55         .word   fft65536_vfp
56 A endfunc
57 T endconst
58
59 function fft4_vfp
60         vldr    d0, [a1, #0*2*4]   @ s0,s1   = z[0]
61         vldr    d4, [a1, #1*2*4]   @ s8,s9   = z[1]
62         vldr    d1, [a1, #2*2*4]   @ s2,s3   = z[2]
63         vldr    d5, [a1, #3*2*4]   @ s10,s11 = z[3]
64         @ stall
65         vadd.f  s12, s0, s8        @ i0
66         vadd.f  s13, s1, s9        @ i1
67         vadd.f  s14, s2, s10       @ i2
68         vadd.f  s15, s3, s11       @ i3
69         vsub.f  s8, s0, s8         @ i4
70         vsub.f  s9, s1, s9         @ i5
71         vsub.f  s10, s2, s10       @ i6
72         vsub.f  s11, s3, s11       @ i7
73         @ stall
74         @ stall
75         vadd.f  s0, s12, s14       @ z[0].re
76         vsub.f  s4, s12, s14       @ z[2].re
77         vadd.f  s1, s13, s15       @ z[0].im
78         vsub.f  s5, s13, s15       @ z[2].im
79         vadd.f  s7, s9, s10        @ z[3].im
80         vsub.f  s3, s9, s10        @ z[1].im
81         vadd.f  s2, s8, s11        @ z[1].re
82         vsub.f  s6, s8, s11        @ z[3].re
83         @ stall
84         @ stall
85         vstr    d0, [a1, #0*2*4]
86         vstr    d2, [a1, #2*2*4]
87         @ stall
88         @ stall
89         vstr    d1, [a1, #1*2*4]
90         vstr    d3, [a1, #3*2*4]
91
92         bx      lr
93 endfunc
94
95 .macro macro_fft8_head
96         @ FFT4
97         vldr    d4, [a1, #0 * 2*4]
98         vldr    d6, [a1, #1 * 2*4]
99         vldr    d5, [a1, #2 * 2*4]
100         vldr    d7, [a1, #3 * 2*4]
101             @ BF
102             vldr    d12, [a1, #4 * 2*4]
103         vadd.f  s16, s8, s12    @ vector op
104             vldr    d14, [a1, #5 * 2*4]
105             vldr    d13, [a1, #6 * 2*4]
106             vldr    d15, [a1, #7 * 2*4]
107         vsub.f  s20, s8, s12    @ vector op
108         vadd.f  s0, s16, s18
109         vsub.f  s2, s16, s18
110         vadd.f  s1, s17, s19
111         vsub.f  s3, s17, s19
112         vadd.f  s7, s21, s22
113         vsub.f  s5, s21, s22
114         vadd.f  s4, s20, s23
115         vsub.f  s6, s20, s23
116             vsub.f  s20, s24, s28   @ vector op
117         vstr    d0, [a1, #0 * 2*4]  @ transfer s0-s7 to s24-s31 via memory
118         vstr    d1, [a1, #1 * 2*4]
119         vldr    s0, cos1pi4
120             vadd.f  s16, s24, s28   @ vector op
121         vstr    d2, [a1, #2 * 2*4]
122         vstr    d3, [a1, #3 * 2*4]
123         vldr    d12, [a1, #0 * 2*4]
124             @ TRANSFORM
125             vmul.f  s20, s20, s0    @ vector x scalar op
126         vldr    d13, [a1, #1 * 2*4]
127         vldr    d14, [a1, #2 * 2*4]
128         vldr    d15, [a1, #3 * 2*4]
129         @ BUTTERFLIES
130         vadd.f  s0, s18, s16
131         vadd.f  s1, s17, s19
132         vsub.f  s2, s17, s19
133         vsub.f  s3, s18, s16
134             vadd.f  s4, s21, s20
135             vsub.f  s5, s21, s20
136             vadd.f  s6, s22, s23
137             vsub.f  s7, s22, s23
138         vadd.f  s8, s0, s24         @ vector op
139         vstr    d0, [a1, #0 * 2*4]  @ transfer s0-s3 to s12-s15 via memory
140         vstr    d1, [a1, #1 * 2*4]
141         vldr    d6, [a1, #0 * 2*4]
142         vldr    d7, [a1, #1 * 2*4]
143             vadd.f  s1, s5, s6
144             vadd.f  s0, s7, s4
145             vsub.f  s2, s5, s6
146             vsub.f  s3, s7, s4
147         vsub.f  s12, s24, s12       @ vector op
148             vsub.f  s5, s29, s1
149             vsub.f  s4, s28, s0
150             vsub.f  s6, s30, s2
151             vsub.f  s7, s31, s3
152             vadd.f  s16, s0, s28    @ vector op
153         vstr    d6, [a1, #4 * 2*4]
154         vstr    d7, [a1, #6 * 2*4]
155         vstr    d4, [a1, #0 * 2*4]
156         vstr    d5, [a1, #2 * 2*4]
157              vstr    d2, [a1, #5 * 2*4]
158              vstr    d3, [a1, #7 * 2*4]
159 .endm
160
161 .macro macro_fft8_tail
162              vstr    d8, [a1, #1 * 2*4]
163              vstr    d9, [a1, #3 * 2*4]
164 .endm
165
166 function .Lfft8_internal_vfp
167         macro_fft8_head
168         macro_fft8_tail
169         bx      lr
170 endfunc
171
172 function fft8_vfp
173         ldr     a3, =0x03030000     @ RunFast mode, vector length 4, stride 1
174         fmrx    a2, FPSCR
175         fmxr    FPSCR, a3
176         vpush   {s16-s31}
177         mov     ip, lr
178         bl      .Lfft8_internal_vfp
179         vpop    {s16-s31}
180         fmxr    FPSCR, a2
181         bx      ip
182 endfunc
183
184 .align 3
185 cos1pi4:    @ cos(1*pi/4) = sqrt(2)
186         .float  0.707106769084930419921875
187 cos1pi8:    @ cos(1*pi/8) = sqrt(2+sqrt(2))/2
188         .float  0.92387950420379638671875
189 cos3pi8:    @ cos(2*pi/8) = sqrt(2-sqrt(2))/2
190         .float  0.3826834261417388916015625
191
192 function .Lfft16_internal_vfp
193         macro_fft8_head
194         @ FFT4(z+8)
195         vldr    d10, [a1, #8 * 2*4]
196         vldr    d12, [a1, #9 * 2*4]
197         vldr    d11, [a1, #10 * 2*4]
198         vldr    d13, [a1, #11 * 2*4]
199         macro_fft8_tail
200         vadd.f  s16, s20, s24   @ vector op
201             @ FFT4(z+12)
202             vldr    d4, [a1, #12 * 2*4]
203             vldr    d6, [a1, #13 * 2*4]
204             vldr    d5, [a1, #14 * 2*4]
205         vsub.f  s20, s20, s24   @ vector op
206             vldr    d7, [a1, #15 * 2*4]
207         vadd.f  s0, s16, s18
208         vsub.f  s4, s16, s18
209         vadd.f  s1, s17, s19
210         vsub.f  s5, s17, s19
211         vadd.f  s7, s21, s22
212         vsub.f  s3, s21, s22
213         vadd.f  s2, s20, s23
214         vsub.f  s6, s20, s23
215             vadd.f  s16, s8, s12    @ vector op
216         vstr    d0, [a1, #8 * 2*4]
217         vstr    d2, [a1, #10 * 2*4]
218         vstr    d1, [a1, #9 * 2*4]
219             vsub.f  s20, s8, s12
220         vstr    d3, [a1, #11 * 2*4]
221         @ TRANSFORM(z[2],z[6],z[10],z[14],cos1pi4,cos1pi4)
222         vldr    d12, [a1, #10 * 2*4]
223             vadd.f  s0, s16, s18
224             vadd.f  s1, s17, s19
225             vsub.f  s6, s16, s18
226             vsub.f  s7, s17, s19
227             vsub.f  s3, s21, s22
228             vadd.f  s2, s20, s23
229             vadd.f  s5, s21, s22
230             vsub.f  s4, s20, s23
231             vstr    d0, [a1, #12 * 2*4]
232         vmov    s0, s6
233           @ TRANSFORM(z[1],z[5],z[9],z[13],cos1pi8,cos3pi8)
234           vldr    d6, [a1, #9 * 2*4]
235             vstr    d1, [a1, #13 * 2*4]
236         vldr    d1, cos1pi4 @ s2 = cos1pi4, s3 = cos1pi8
237             vstr    d2, [a1, #15 * 2*4]
238           vldr    d7, [a1, #13 * 2*4]
239         vadd.f  s4, s25, s24
240         vsub.f  s5, s25, s24
241         vsub.f  s6, s0, s7
242         vadd.f  s7, s0, s7
243           vmul.f  s20, s12, s3  @ vector op
244             @ TRANSFORM(z[3],z[7],z[11],z[15],cos3pi8,cos1pi8)
245             vldr    d4, [a1, #11 * 2*4]
246             vldr    d5, [a1, #15 * 2*4]
247             vldr    s1, cos3pi8
248         vmul.f  s24, s4, s2     @ vector * scalar op
249           vmul.f  s28, s12, s1  @ vector * scalar op
250             vmul.f  s12, s8, s1 @ vector * scalar op
251           vadd.f  s4, s20, s29
252           vsub.f  s5, s21, s28
253           vsub.f  s6, s22, s31
254           vadd.f  s7, s23, s30
255             vmul.f  s8, s8, s3  @ vector * scalar op
256           vldr    d8, [a1, #1 * 2*4]
257           vldr    d9, [a1, #5 * 2*4]
258             vldr    d10, [a1, #3 * 2*4]
259             vldr    d11, [a1, #7 * 2*4]
260         vldr    d14, [a1, #2 * 2*4]
261           vadd.f  s0, s6, s4
262           vadd.f  s1, s5, s7
263           vsub.f  s2, s5, s7
264           vsub.f  s3, s6, s4
265             vadd.f  s4, s12, s9
266             vsub.f  s5, s13, s8
267             vsub.f  s6, s14, s11
268             vadd.f  s7, s15, s10
269           vadd.f  s12, s0, s16  @ vector op
270           vstr    d0, [a1, #1 * 2*4]
271           vstr    d1, [a1, #5 * 2*4]
272           vldr    d4, [a1, #1 * 2*4]
273           vldr    d5, [a1, #5 * 2*4]
274             vadd.f  s0, s6, s4
275             vadd.f  s1, s5, s7
276             vsub.f  s2, s5, s7
277             vsub.f  s3, s6, s4
278           vsub.f  s8, s16, s8   @ vector op
279           vstr    d6, [a1, #1 * 2*4]
280           vstr    d7, [a1, #5 * 2*4]
281         vldr    d15, [a1, #6 * 2*4]
282             vsub.f  s4, s20, s0
283             vsub.f  s5, s21, s1
284             vsub.f  s6, s22, s2
285             vsub.f  s7, s23, s3
286             vadd.f  s20, s0, s20    @ vector op
287           vstr    d4, [a1, #9 * 2*4]
288               @ TRANSFORM_ZERO(z[0],z[4],z[8],z[12])
289               vldr    d6, [a1, #8 * 2*4]
290           vstr    d5, [a1, #13 * 2*4]
291               vldr    d7, [a1, #12 * 2*4]
292           vstr    d2, [a1, #11 * 2*4]
293               vldr    d8, [a1, #0 * 2*4]
294           vstr    d3, [a1, #15 * 2*4]
295               vldr    d9, [a1, #4 * 2*4]
296         vadd.f  s0, s26, s24
297         vadd.f  s1, s25, s27
298         vsub.f  s2, s25, s27
299         vsub.f  s3, s26, s24
300               vadd.f  s4, s14, s12
301               vadd.f  s5, s13, s15
302               vsub.f  s6, s13, s15
303               vsub.f  s7, s14, s12
304         vadd.f  s8, s0, s28 @ vector op
305         vstr    d0, [a1, #3 * 2*4]
306         vstr    d1, [a1, #7 * 2*4]
307         vldr    d6, [a1, #3 * 2*4]
308         vldr    d7, [a1, #7 * 2*4]
309               vsub.f  s0, s16, s4
310               vsub.f  s1, s17, s5
311               vsub.f  s2, s18, s6
312               vsub.f  s3, s19, s7
313         vsub.f  s12, s28, s12       @ vector op
314               vadd.f  s16, s4, s16  @ vector op
315             vstr    d10, [a1, #3 * 2*4]
316             vstr    d11, [a1, #7 * 2*4]
317         vstr    d4, [a1, #2 * 2*4]
318         vstr    d5, [a1, #6 * 2*4]
319               vstr    d0, [a1, #8 * 2*4]
320               vstr    d1, [a1, #12 * 2*4]
321         vstr    d6, [a1, #10 * 2*4]
322         vstr    d7, [a1, #14 * 2*4]
323               vstr    d8, [a1, #0 * 2*4]
324               vstr    d9, [a1, #4 * 2*4]
325
326         bx      lr
327 endfunc
328
329 function ff_fft16_vfp, export=1
330         ldr     a3, =0x03030000     @ RunFast mode, vector length 4, stride 1
331         fmrx    a2, FPSCR
332         fmxr    FPSCR, a3
333         vpush   {s16-s31}
334         mov     ip, lr
335         bl      .Lfft16_internal_vfp
336         vpop    {s16-s31}
337         fmxr    FPSCR, a2
338         bx      ip
339 endfunc
340
341 .macro pass n, z0, z1, z2, z3
342         add     v6, v5, #4*2*\n
343         @ TRANSFORM_ZERO(z[0],z[o1],z[o2],z[o3])
344             @ TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1])
345                 @ TRANSFORM(z[0],z[o1],z[o2],z[o3],wre[0],wim[0])
346                     @ TRANSFORM(z[1],z[o1+1],z[o2+1],z[o3+1],wre[1],wim[-1])
347             vldr    d8, [\z2, #8*(o2+1)]        @ s16,s17
348             vldmdb  v6!, {s2}
349             vldr    d9, [\z3, #8*(o3+1)]        @ s18,s19
350             vldmia  v5!, {s0,s1}                @ s0 is unused
351         vldr    s7, [\z2, #8*o2]            @ t1
352             vmul.f  s20, s16, s2                @ vector * scalar
353         vldr    s0, [\z3, #8*o3]            @ t5
354         vldr    s6, [\z2, #8*o2+4]          @ t2
355         vldr    s3, [\z3, #8*o3+4]          @ t6
356             vmul.f  s16, s16, s1                @ vector * scalar
357         ldr     a4, =\n-1
358 1:      add     \z0, \z0, #8*2
359  .if \n*4*2 >= 512
360         add     \z1, \z1, #8*2
361  .endif
362  .if \n*4*2 >= 256
363         add     \z2, \z2, #8*2
364  .endif
365  .if \n*4*2 >= 512
366         add     \z3, \z3, #8*2
367  .endif
368         @ up to 2 stalls (VFP vector issuing / waiting for s0)
369         @ depending upon whether this is the first iteration and
370         @ how many add instructions are inserted above
371         vadd.f  s4, s0, s7                  @ t5
372         vadd.f  s5, s6, s3                  @ t6
373         vsub.f  s6, s6, s3                  @ t4
374         vsub.f  s7, s0, s7                  @ t3
375         vldr    d6, [\z0, #8*0-8*2]         @ s12,s13
376             vadd.f  s0, s16, s21                @ t1
377         vldr    d7, [\z1, #8*o1-8*2]        @ s14,s15
378             vsub.f  s1, s18, s23                @ t5
379         vadd.f  s8, s4, s12                 @ vector + vector
380         @ stall (VFP vector issuing)
381         @ stall (VFP vector issuing)
382         @ stall (VFP vector issuing)
383         vsub.f  s4, s12, s4
384         vsub.f  s5, s13, s5
385         vsub.f  s6, s14, s6
386         vsub.f  s7, s15, s7
387             vsub.f  s2, s17, s20                @ t2
388             vadd.f  s3, s19, s22                @ t6
389         vstr    d4, [\z0, #8*0-8*2]         @ s8,s9
390         vstr    d5, [\z1, #8*o1-8*2]        @ s10,s11
391         @ stall (waiting for s5)
392         vstr    d2, [\z2, #8*o2-8*2]        @ s4,s5
393             vadd.f  s4, s1, s0                  @ t5
394         vstr    d3, [\z3, #8*o3-8*2]        @ s6,s7
395             vsub.f  s7, s1, s0                  @ t3
396             vadd.f  s5, s2, s3                  @ t6
397             vsub.f  s6, s2, s3                  @ t4
398             vldr    d6, [\z0, #8*1-8*2]         @ s12,s13
399             vldr    d7, [\z1, #8*(o1+1)-8*2]    @ s14,s15
400                 vldr    d4, [\z2, #8*o2]            @ s8,s9
401                 vldmdb  v6!, {s2,s3}
402                 vldr    d5, [\z3, #8*o3]            @ s10,s11
403             vadd.f  s20, s4, s12                @ vector + vector
404                 vldmia  v5!, {s0,s1}
405                     vldr    d8, [\z2, #8*(o2+1)]        @ s16,s17
406             @ stall (VFP vector issuing)
407             vsub.f  s4, s12, s4
408             vsub.f  s5, s13, s5
409             vsub.f  s6, s14, s6
410             vsub.f  s7, s15, s7
411                 vmul.f  s12, s8, s3                 @ vector * scalar
412             vstr    d10, [\z0, #8*1-8*2]        @ s20,s21
413                     vldr    d9, [\z3, #8*(o3+1)]        @ s18,s19
414             vstr    d11, [\z1, #8*(o1+1)-8*2]   @ s22,s23
415                 vmul.f  s8, s8, s0                  @ vector * scalar
416             vstr    d2, [\z2, #8*(o2+1)-8*2]    @ s4,s5
417             @ stall (waiting for s7)
418             vstr    d3, [\z3, #8*(o3+1)-8*2]    @ s6,s7
419                     vmul.f  s20, s16, s2                @ vector * scalar
420                 @ stall (VFP vector issuing)
421                 @ stall (VFP vector issuing)
422                 @ stall (VFP vector issuing)
423                 vadd.f  s7, s8, s13                 @ t1
424                 vsub.f  s6, s9, s12                 @ t2
425                 vsub.f  s0, s10, s15                @ t5
426                 vadd.f  s3, s11, s14                @ t6
427                     vmul.f  s16, s16, s1                @ vector * scalar
428         subs    a4, a4, #1
429         bne     1b
430         @ What remains is identical to the first two indentations of
431         @ the above, but without the increment of z
432         vadd.f  s4, s0, s7                  @ t5
433         vadd.f  s5, s6, s3                  @ t6
434         vsub.f  s6, s6, s3                  @ t4
435         vsub.f  s7, s0, s7                  @ t3
436         vldr    d6, [\z0, #8*0]             @ s12,s13
437             vadd.f  s0, s16, s21                @ t1
438         vldr    d7, [\z1, #8*o1]            @ s14,s15
439             vsub.f  s1, s18, s23                @ t5
440         vadd.f  s8, s4, s12                 @ vector + vector
441         vsub.f  s4, s12, s4
442         vsub.f  s5, s13, s5
443         vsub.f  s6, s14, s6
444         vsub.f  s7, s15, s7
445             vsub.f  s2, s17, s20                @ t2
446             vadd.f  s3, s19, s22                @ t6
447         vstr    d4, [\z0, #8*0]             @ s8,s9
448         vstr    d5, [\z1, #8*o1]            @ s10,s11
449         vstr    d2, [\z2, #8*o2]            @ s4,s5
450             vadd.f  s4, s1, s0                  @ t5
451         vstr    d3, [\z3, #8*o3]            @ s6,s7
452             vsub.f  s7, s1, s0                  @ t3
453             vadd.f  s5, s2, s3                  @ t6
454             vsub.f  s6, s2, s3                  @ t4
455             vldr    d6, [\z0, #8*1]             @ s12,s13
456             vldr    d7, [\z1, #8*(o1+1)]        @ s14,s15
457             vadd.f  s20, s4, s12                @ vector + vector
458             vsub.f  s4, s12, s4
459             vsub.f  s5, s13, s5
460             vsub.f  s6, s14, s6
461             vsub.f  s7, s15, s7
462             vstr    d10, [\z0, #8*1]            @ s20,s21
463             vstr    d11, [\z1, #8*(o1+1)]       @ s22,s23
464             vstr    d2, [\z2, #8*(o2+1)]        @ s4,s5
465             vstr    d3, [\z3, #8*(o3+1)]        @ s6,s7
466 .endm
467
468 .macro  def_fft n, n2, n4
469 function .Lfft\n\()_internal_vfp
470  .if \n >= 512
471         push    {v1-v6,lr}
472  .elseif \n >= 256
473         push    {v1-v2,v5-v6,lr}
474  .else
475         push    {v1,v5-v6,lr}
476  .endif
477         mov     v1, a1
478         bl      .Lfft\n2\()_internal_vfp
479         add     a1, v1, #8*(\n/4)*2
480         bl      .Lfft\n4\()_internal_vfp
481         movrelx v5, X(ff_cos_\n), a1
482         add     a1, v1, #8*(\n/4)*3
483         bl      .Lfft\n4\()_internal_vfp
484  .if \n >= 512
485   .set o1, 0*(\n/4/2)
486   .set o2, 0*(\n/4/2)
487   .set o3, 0*(\n/4/2)
488         add     v2, v1, #8*2*(\n/4/2)
489         add     v3, v1, #8*4*(\n/4/2)
490         add     v4, v1, #8*6*(\n/4/2)
491         pass    (\n/4/2), v1, v2, v3, v4
492         pop     {v1-v6,pc}
493  .elseif \n >= 256
494   .set o1, 2*(\n/4/2)
495   .set o2, 0*(\n/4/2)
496   .set o3, 2*(\n/4/2)
497         add     v2, v1, #8*4*(\n/4/2)
498         pass    (\n/4/2), v1, v1, v2, v2
499         pop     {v1-v2,v5-v6,pc}
500  .else
501   .set o1, 2*(\n/4/2)
502   .set o2, 4*(\n/4/2)
503   .set o3, 6*(\n/4/2)
504         pass    (\n/4/2), v1, v1, v1, v1
505         pop     {v1,v5-v6,pc}
506  .endif
507 endfunc
508
509 function fft\n\()_vfp
510         ldr     a3, =0x03030000 /* RunFast mode, vector length 4, stride 1 */
511         fmrx    a2, FPSCR
512         fmxr    FPSCR, a3
513         vpush   {s16-s31}
514         mov     ip, lr
515         bl      .Lfft\n\()_internal_vfp
516         vpop    {s16-s31}
517         fmxr    FPSCR, a2
518         bx      ip
519 endfunc
520
521 .ltorg
522 .endm
523
524         def_fft    32,    16,     8
525         def_fft    64,    32,    16
526         def_fft   128,    64,    32
527         def_fft   256,   128,    64
528         def_fft   512,   256,   128
529         def_fft  1024,   512,   256
530         def_fft  2048,  1024,   512
531         def_fft  4096,  2048,  1024
532         def_fft  8192,  4096,  2048
533         def_fft 16384,  8192,  4096
534         def_fft 32768, 16384,  8192
535         def_fft 65536, 32768, 16384