more credits to D. J. Bernstein for fft
[ffmpeg.git] / libavcodec / arm / fft_neon.S
1 /*
2  * ARM NEON optimised FFT
3  *
4  * Copyright (c) 2009 Mans Rullgard <mans@mansr.com>
5  * Copyright (c) 2009 Naotoshi Nojiri
6  *
7  * This algorithm (though not any of the implementation details) is
8  * based on libdjbfft by D. J. Bernstein.
9  *
10  * This file is part of FFmpeg.
11  *
12  * FFmpeg is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * FFmpeg is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with FFmpeg; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25  */
26
27 #include "asm.S"
28
29 #define M_SQRT1_2 0.70710678118654752440
30
31         .text
32
33 function fft4_neon
34         vld1.32         {d0-d3}, [r0,:128]
35
36         vext.32         q8,  q1,  q1,  #1       @ i2,r3 d3=i3,r2
37         vsub.f32        d6,  d0,  d1            @ r0-r1,i0-i1
38         vsub.f32        d7,  d16, d17           @ r3-r2,i2-i3
39         vadd.f32        d4,  d0,  d1            @ r0+r1,i0+i1
40         vadd.f32        d5,  d2,  d3            @ i2+i3,r2+r3
41         vadd.f32        d1,  d6,  d7
42         vsub.f32        d3,  d6,  d7
43         vadd.f32        d0,  d4,  d5
44         vsub.f32        d2,  d4,  d5
45
46         vst1.32         {d0-d3}, [r0,:128]
47
48         bx              lr
49 endfunc
50
51 function fft8_neon
52         mov             r1,  r0
53         vld1.32         {d0-d3},   [r1,:128]!
54         vld1.32         {d16-d19}, [r1,:128]
55
56         movw            r2,  #0x04f3            @ sqrt(1/2)
57         movt            r2,  #0x3f35
58         eor             r3,  r2,  #1<<31
59         vdup.32         d31, r2
60
61         vext.32         q11, q1,  q1,  #1       @ i2,r3,i3,r2
62         vadd.f32        d4,  d16, d17           @ r4+r5,i4+i5
63         vmov            d28, r3,  r2
64         vadd.f32        d5,  d18, d19           @ r6+r7,i6+i7
65         vsub.f32        d17, d16, d17           @ r4-r5,i4-i5
66         vsub.f32        d19, d18, d19           @ r6-r7,i6-i7
67         vrev64.32       d29, d28
68         vadd.f32        d20, d0,  d1            @ r0+r1,i0+i1
69         vadd.f32        d21, d2,  d3            @ r2+r3,i2+i3
70         vmul.f32        d26, d17, d28           @ -a2r*w,a2i*w
71         vext.32         q3,  q2,  q2,  #1
72         vmul.f32        d27, d19, d29           @ a3r*w,-a3i*w
73         vsub.f32        d23, d22, d23           @ i2-i3,r3-r2
74         vsub.f32        d22, d0,  d1            @ r0-r1,i0-i1
75         vmul.f32        d24, d17, d31           @ a2r*w,a2i*w
76         vmul.f32        d25, d19, d31           @ a3r*w,a3i*w
77         vadd.f32        d0,  d20, d21
78         vsub.f32        d2,  d20, d21
79         vadd.f32        d1,  d22, d23
80         vrev64.32       q13, q13
81         vsub.f32        d3,  d22, d23
82         vsub.f32        d6,  d6,  d7
83         vadd.f32        d24, d24, d26           @ a2r+a2i,a2i-a2r   t1,t2
84         vadd.f32        d25, d25, d27           @ a3r-a3i,a3i+a3r   t5,t6
85         vadd.f32        d7,  d4,  d5
86         vsub.f32        d18, d2,  d6
87         vext.32         q13, q12, q12, #1
88         vadd.f32        d2,  d2,  d6
89         vsub.f32        d16, d0,  d7
90         vadd.f32        d5,  d25, d24
91         vsub.f32        d4,  d26, d27
92         vadd.f32        d0,  d0,  d7
93         vsub.f32        d17, d1,  d5
94         vsub.f32        d19, d3,  d4
95         vadd.f32        d3,  d3,  d4
96         vadd.f32        d1,  d1,  d5
97
98         vst1.32         {d16-d19}, [r1,:128]
99         vst1.32         {d0-d3},   [r0,:128]
100
101         bx              lr
102 endfunc
103
104 function fft16_neon
105         movrel          r1, mppm
106         vld1.32         {d16-d19}, [r0,:128]!   @ q8{r0,i0,r1,i1} q9{r2,i2,r3,i3}
107         pld             [r0, #32]
108         vld1.32         {d2-d3}, [r1,:128]
109         vext.32         q13, q9,  q9,  #1
110         vld1.32         {d22-d25}, [r0,:128]!   @ q11{r4,i4,r5,i5} q12{r6,i5,r7,i7}
111         vadd.f32        d4,  d16, d17
112         vsub.f32        d5,  d16, d17
113         vadd.f32        d18, d18, d19
114         vsub.f32        d19, d26, d27
115
116         vadd.f32        d20, d22, d23
117         vsub.f32        d22, d22, d23
118         vsub.f32        d23, d24, d25
119         vadd.f32        q8,  q2,  q9            @ {r0,i0,r1,i1}
120         vadd.f32        d21, d24, d25
121         vmul.f32        d24, d22, d2
122         vsub.f32        q9,  q2,  q9            @ {r2,i2,r3,i3}
123         vmul.f32        d25, d23, d3
124         vuzp.32         d16, d17                @ {r0,r1,i0,i1}
125         vmul.f32        q1,  q11, d2[1]
126         vuzp.32         d18, d19                @ {r2,r3,i2,i3}
127         vrev64.32       q12, q12
128         vadd.f32        q11, q12, q1            @ {t1a,t2a,t5,t6}
129         vld1.32         {d24-d27}, [r0,:128]!   @ q12{r8,i8,r9,i9} q13{r10,i10,r11,i11}
130         vzip.32         q10, q11
131         vld1.32         {d28-d31}, [r0,:128]    @ q14{r12,i12,r13,i13} q15{r14,i14,r15,i15}
132         vadd.f32        d0,  d22, d20
133         vadd.f32        d1,  d21, d23
134         vsub.f32        d2,  d21, d23
135         vsub.f32        d3,  d22, d20
136         sub             r0,  r0,  #96
137         vext.32         q13, q13, q13, #1
138         vsub.f32        q10, q8,  q0            @ {r4,r5,i4,i5}
139         vadd.f32        q8,  q8,  q0            @ {r0,r1,i0,i1}
140         vext.32         q15, q15, q15, #1
141         vsub.f32        q11, q9,  q1            @ {r6,r7,i6,i7}
142         vswp            d25, d26                @ q12{r8,i8,i10,r11} q13{r9,i9,i11,r10}
143         vadd.f32        q9,  q9,  q1            @ {r2,r3,i2,i3}
144         vswp            d29, d30                @ q14{r12,i12,i14,r15} q15{r13,i13,i15,r14}
145         vadd.f32        q0,  q12, q13           @ {t1,t2,t5,t6}
146         vadd.f32        q1,  q14, q15           @ {t1a,t2a,t5a,t6a}
147         movrel          r2,  X(ff_cos_16)
148         vsub.f32        q13, q12, q13           @ {t3,t4,t7,t8}
149         vrev64.32       d1,  d1
150         vsub.f32        q15, q14, q15           @ {t3a,t4a,t7a,t8a}
151         vrev64.32       d3,  d3
152         movrel          r3,  pmmp
153         vswp            d1,  d26                @ q0{t1,t2,t3,t4} q13{t6,t5,t7,t8}
154         vswp            d3,  d30                @ q1{t1a,t2a,t3a,t4a} q15{t6a,t5a,t7a,t8a}
155         vadd.f32        q12, q0,  q13           @ {r8,i8,r9,i9}
156         vadd.f32        q14, q1,  q15           @ {r12,i12,r13,i13}
157         vld1.32         {d4-d5},  [r2,:64]
158         vsub.f32        q13, q0,  q13           @ {r10,i10,r11,i11}
159         vsub.f32        q15, q1,  q15           @ {r14,i14,r15,i15}
160         vswp            d25, d28                @ q12{r8,i8,r12,i12} q14{r9,i9,r13,i13}
161         vld1.32         {d6-d7},  [r3,:128]
162         vrev64.32       q1,  q14
163         vmul.f32        q14, q14, d4[1]
164         vmul.f32        q1,  q1,  q3
165         vmla.f32        q14, q1,  d5[1]         @ {t1a,t2a,t5a,t6a}
166         vswp            d27, d30                @ q13{r10,i10,r14,i14} q15{r11,i11,r15,i15}
167         vzip.32         q12, q14
168         vadd.f32        d0,  d28, d24
169         vadd.f32        d1,  d25, d29
170         vsub.f32        d2,  d25, d29
171         vsub.f32        d3,  d28, d24
172         vsub.f32        q12, q8,  q0            @ {r8,r9,i8,i9}
173         vadd.f32        q8,  q8,  q0            @ {r0,r1,i0,i1}
174         vsub.f32        q14, q10, q1            @ {r12,r13,i12,i13}
175         mov             r1,  #32
176         vadd.f32        q10, q10, q1            @ {r4,r5,i4,i5}
177         vrev64.32       q0,  q13
178         vmul.f32        q13, q13, d5[0]
179         vrev64.32       q1,  q15
180         vmul.f32        q15, q15, d5[1]
181         vst2.32         {d16-d17},[r0,:128], r1
182         vmul.f32        q0,  q0,  q3
183         vst2.32         {d20-d21},[r0,:128], r1
184         vmul.f32        q1,  q1,  q3
185         vmla.f32        q13, q0,  d5[0]         @ {t1,t2,t5,t6}
186         vmla.f32        q15, q1,  d4[1]         @ {t1a,t2a,t5a,t6a}
187         vst2.32         {d24-d25},[r0,:128], r1
188         vst2.32         {d28-d29},[r0,:128]
189         vzip.32         q13, q15
190         sub             r0, r0, #80
191         vadd.f32        d0,  d30, d26
192         vadd.f32        d1,  d27, d31
193         vsub.f32        d2,  d27, d31
194         vsub.f32        d3,  d30, d26
195         vsub.f32        q13, q9,  q0            @ {r10,r11,i10,i11}
196         vadd.f32        q9,  q9,  q0            @ {r2,r3,i2,i3}
197         vsub.f32        q15, q11, q1            @ {r14,r15,i14,i15}
198         vadd.f32        q11, q11, q1            @ {r6,r7,i6,i7}
199         vst2.32         {d18-d19},[r0,:128], r1
200         vst2.32         {d22-d23},[r0,:128], r1
201         vst2.32         {d26-d27},[r0,:128], r1
202         vst2.32         {d30-d31},[r0,:128]
203         bx              lr
204 endfunc
205
206 function fft_pass_neon
207         push            {r4-r6,lr}
208         mov             r6,  r2                 @ n
209         lsl             r5,  r2,  #3            @ 2 * n * sizeof FFTSample
210         lsl             r4,  r2,  #4            @ 2 * n * sizeof FFTComplex
211         lsl             r2,  r2,  #5            @ 4 * n * sizeof FFTComplex
212         add             r3,  r2,  r4
213         add             r4,  r4,  r0            @ &z[o1]
214         add             r2,  r2,  r0            @ &z[o2]
215         add             r3,  r3,  r0            @ &z[o3]
216         vld1.32         {d20-d21},[r2,:128]     @ {z[o2],z[o2+1]}
217         movrel          r12, pmmp
218         vld1.32         {d22-d23},[r3,:128]     @ {z[o3],z[o3+1]}
219         add             r5,  r5,  r1            @ wim
220         vld1.32         {d6-d7},  [r12,:128]    @ pmmp
221         vswp            d21, d22
222         vld1.32         {d4},     [r1,:64]!     @ {wre[0],wre[1]}
223         sub             r5,  r5,  #4            @ wim--
224         vrev64.32       q1,  q11
225         vmul.f32        q11, q11, d4[1]
226         vmul.f32        q1,  q1,  q3
227         vld1.32         {d5[0]},  [r5,:32]      @ d5[0] = wim[-1]
228         vmla.f32        q11, q1,  d5[0]         @ {t1a,t2a,t5a,t6a}
229         vld2.32         {d16-d17},[r0,:128]     @ {z[0],z[1]}
230         sub             r6, r6, #1              @ n--
231         vld2.32         {d18-d19},[r4,:128]     @ {z[o1],z[o1+1]}
232         vzip.32         q10, q11
233         vadd.f32        d0,  d22, d20
234         vadd.f32        d1,  d21, d23
235         vsub.f32        d2,  d21, d23
236         vsub.f32        d3,  d22, d20
237         vsub.f32        q10, q8,  q0
238         vadd.f32        q8,  q8,  q0
239         vsub.f32        q11, q9,  q1
240         vadd.f32        q9,  q9,  q1
241         vst2.32         {d20-d21},[r2,:128]!    @ {z[o2],z[o2+1]}
242         vst2.32         {d16-d17},[r0,:128]!    @ {z[0],z[1]}
243         vst2.32         {d22-d23},[r3,:128]!    @ {z[o3],z[o3+1]}
244         vst2.32         {d18-d19},[r4,:128]!    @ {z[o1],z[o1+1]}
245         sub             r5,  r5,  #8            @ wim -= 2
246 1:
247         vld1.32         {d20-d21},[r2,:128]     @ {z[o2],z[o2+1]}
248         vld1.32         {d22-d23},[r3,:128]     @ {z[o3],z[o3+1]}
249         vswp            d21, d22
250         vld1.32         {d4}, [r1]!             @ {wre[0],wre[1]}
251         vrev64.32       q0,  q10
252         vmul.f32        q10, q10, d4[0]
253         vrev64.32       q1,  q11
254         vmul.f32        q11, q11, d4[1]
255         vld1.32         {d5}, [r5]              @ {wim[-1],wim[0]}
256         vmul.f32        q0,  q0,  q3
257         sub             r5,  r5,  #8            @ wim -= 2
258         vmul.f32        q1,  q1,  q3
259         vmla.f32        q10, q0,  d5[1]         @ {t1,t2,t5,t6}
260         vmla.f32        q11, q1,  d5[0]         @ {t1a,t2a,t5a,t6a}
261         vld2.32         {d16-d17},[r0,:128]     @ {z[0],z[1]}
262         subs            r6,  r6,  #1            @ n--
263         vld2.32         {d18-d19},[r4,:128]     @ {z[o1],z[o1+1]}
264         vzip.32         q10, q11
265         vadd.f32        d0,  d22, d20
266         vadd.f32        d1,  d21, d23
267         vsub.f32        d2,  d21, d23
268         vsub.f32        d3,  d22, d20
269         vsub.f32        q10, q8,  q0
270         vadd.f32        q8,  q8,  q0
271         vsub.f32        q11, q9,  q1
272         vadd.f32        q9,  q9,  q1
273         vst2.32         {d20-d21}, [r2,:128]!   @ {z[o2],z[o2+1]}
274         vst2.32         {d16-d17}, [r0,:128]!   @ {z[0],z[1]}
275         vst2.32         {d22-d23}, [r3,:128]!   @ {z[o3],z[o3+1]}
276         vst2.32         {d18-d19}, [r4,:128]!   @ {z[o1],z[o1+1]}
277         bne             1b
278
279         pop             {r4-r6,pc}
280 endfunc
281
282 .macro  def_fft n, n2, n4
283         .align 6
284 function fft\n\()_neon
285         push            {r4, lr}
286         mov             r4,  r0
287         bl              fft\n2\()_neon
288         add             r0,  r4,  #\n4*2*8
289         bl              fft\n4\()_neon
290         add             r0,  r4,  #\n4*3*8
291         bl              fft\n4\()_neon
292         mov             r0,  r4
293         pop             {r4, lr}
294         movrel          r1,  X(ff_cos_\n)
295         mov             r2,  #\n4/2
296         b               fft_pass_neon
297 endfunc
298 .endm
299
300         def_fft    32,    16,     8
301         def_fft    64,    32,    16
302         def_fft   128,    64,    32
303         def_fft   256,   128,    64
304         def_fft   512,   256,   128
305         def_fft  1024,   512,   256
306         def_fft  2048,  1024,   512
307         def_fft  4096,  2048,  1024
308         def_fft  8192,  4096,  2048
309         def_fft 16384,  8192,  4096
310         def_fft 32768, 16384,  8192
311         def_fft 65536, 32768, 16384
312
313 function ff_fft_calc_neon, export=1
314         ldr             r2,  [r0]
315         sub             r2,  r2,  #2
316         movrel          r3,  fft_tab_neon
317         ldr             r3,  [r3, r2, lsl #2]
318         mov             r0,  r1
319         bx              r3
320 endfunc
321
322 function ff_fft_permute_neon, export=1
323         push            {r4,lr}
324         mov             r12, #1
325         ldr             r2,  [r0]       @ nbits
326         ldr             r3,  [r0, #12]  @ tmp_buf
327         ldr             r0,  [r0, #8]   @ revtab
328         lsl             r12, r12, r2
329         mov             r2,  r12
330 1:
331         vld1.32         {d0-d1}, [r1,:128]!
332         ldr             r4,  [r0], #4
333         uxth            lr,  r4
334         uxth            r4,  r4,  ror #16
335         add             lr,  r3,  lr,  lsl #3
336         add             r4,  r3,  r4,  lsl #3
337         vst1.32         {d0}, [lr,:64]
338         vst1.32         {d1}, [r4,:64]
339         subs            r12, r12, #2
340         bgt             1b
341
342         sub             r1,  r1,  r2,  lsl #3
343 1:
344         vld1.32         {d0-d3}, [r3,:128]!
345         vst1.32         {d0-d3}, [r1,:128]!
346         subs            r2,  r2,  #4
347         bgt             1b
348
349         pop             {r4,pc}
350 endfunc
351
352         .section .rodata
353         .align 4
354 fft_tab_neon:
355         .word fft4_neon
356         .word fft8_neon
357         .word fft16_neon
358         .word fft32_neon
359         .word fft64_neon
360         .word fft128_neon
361         .word fft256_neon
362         .word fft512_neon
363         .word fft1024_neon
364         .word fft2048_neon
365         .word fft4096_neon
366         .word fft8192_neon
367         .word fft16384_neon
368         .word fft32768_neon
369         .word fft65536_neon
370 ELF     .size fft_tab_neon, . - fft_tab_neon
371
372         .align 4
373 pmmp:   .float  +1.0, -1.0, -1.0, +1.0
374 mppm:   .float  -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2