2 * ARM NEON optimised FFT
4 * Copyright (c) 2009 Mans Rullgard <mans@mansr.com>
5 * Copyright (c) 2009 Naotoshi Nojiri
7 * This algorithm (though not any of the implementation details) is
8 * based on libdjbfft by D. J. Bernstein.
10 * This file is part of FFmpeg.
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.
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.
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
29 #define M_SQRT1_2 0.70710678118654752440
34 vld1.32 {d0-d3}, [r0,:128]
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
46 vst1.32 {d0-d3}, [r0,:128]
53 vld1.32 {d0-d3}, [r1,:128]!
54 vld1.32 {d16-d19}, [r1,:128]
56 movw r2, #0x04f3 @ sqrt(1/2)
61 vext.32 q11, q1, q1, #1 @ i2,r3,i3,r2
62 vadd.f32 d4, d16, d17 @ r4+r5,i4+i5
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
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
83 vadd.f32 d24, d24, d26 @ a2r+a2i,a2i-a2r t1,t2
84 vadd.f32 d25, d25, d27 @ a3r-a3i,a3i+a3r t5,t6
87 vext.32 q13, q12, q12, #1
98 vst1.32 {d16-d19}, [r1,:128]
99 vst1.32 {d0-d3}, [r0,:128]
106 vld1.32 {d16-d19}, [r0,:128]! @ q8{r0,i0,r1,i1} q9{r2,i2,r3,i3}
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
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}
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}
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
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}
150 vsub.f32 q15, q14, q15 @ {t3a,t4a,t7a,t8a}
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]
163 vmul.f32 q14, q14, d4[1]
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}
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}
176 vadd.f32 q10, q10, q1 @ {r4,r5,i4,i5}
178 vmul.f32 q13, q13, d5[0]
180 vmul.f32 q15, q15, d5[1]
181 vst2.32 {d16-d17},[r0,:128], r1
183 vst2.32 {d20-d21},[r0,:128], r1
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]
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]
206 function fft_pass_neon
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
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]}
218 vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]}
220 vld1.32 {d6-d7}, [r12,:128] @ pmmp
222 vld1.32 {d4}, [r1,:64]! @ {wre[0],wre[1]}
223 sub r5, r5, #4 @ wim--
225 vmul.f32 q11, q11, d4[1]
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]}
231 vld2.32 {d18-d19},[r4,:128] @ {z[o1],z[o1+1]}
233 vadd.f32 d0, d22, d20
234 vadd.f32 d1, d21, d23
235 vsub.f32 d2, d21, d23
236 vsub.f32 d3, d22, d20
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
247 vld1.32 {d20-d21},[r2,:128] @ {z[o2],z[o2+1]}
248 vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]}
250 vld1.32 {d4}, [r1]! @ {wre[0],wre[1]}
252 vmul.f32 q10, q10, d4[0]
254 vmul.f32 q11, q11, d4[1]
255 vld1.32 {d5}, [r5] @ {wim[-1],wim[0]}
257 sub r5, r5, #8 @ wim -= 2
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]}
265 vadd.f32 d0, d22, d20
266 vadd.f32 d1, d21, d23
267 vsub.f32 d2, d21, d23
268 vsub.f32 d3, d22, d20
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]}
282 .macro def_fft n, n2, n4
284 function fft\n\()_neon
294 movrel r1, X(ff_cos_\n)
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
313 function ff_fft_calc_neon, export=1
316 movrel r3, fft_tab_neon
317 ldr r3, [r3, r2, lsl #2]
322 function ff_fft_permute_neon, export=1
326 ldr r3, [r0, #12] @ tmp_buf
327 ldr r0, [r0, #8] @ revtab
331 vld1.32 {d0-d1}, [r1,:128]!
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]
342 sub r1, r1, r2, lsl #3
344 vld1.32 {d0-d3}, [r3,:128]!
345 vst1.32 {d0-d3}, [r1,:128]!
371 .float +1.0, -1.0, -1.0, +1.0
375 .float -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2