2 * ARM NEON optimised FFT
4 * Copyright (c) 2009 Mans Rullgard <mans@mansr.com>
5 * Copyright (c) 2009 Naotoshi Nojiri
7 * This file is part of FFmpeg.
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #define M_SQRT1_2 0.70710678118654752440
31 vld1.32 {d0-d3}, [r0,:128]
33 vext.32 q8, q1, q1, #1 @ i2,r3 d3=i3,r2
34 vsub.f32 d6, d0, d1 @ r0-r1,i0-i1
35 vsub.f32 d7, d16, d17 @ r3-r2,i2-i3
36 vadd.f32 d4, d0, d1 @ r0+r1,i0+i1
37 vadd.f32 d5, d2, d3 @ i2+i3,r2+r3
43 vst1.32 {d0-d3}, [r0,:128]
50 vld1.32 {d0-d3}, [r1,:128]!
51 vld1.32 {d16-d19}, [r1,:128]
53 movw r2, #0x04f3 @ sqrt(1/2)
58 vext.32 q11, q1, q1, #1 @ i2,r3,i3,r2
59 vadd.f32 d4, d16, d17 @ r4+r5,i4+i5
61 vadd.f32 d5, d18, d19 @ r6+r7,i6+i7
62 vsub.f32 d17, d16, d17 @ r4-r5,i4-i5
63 vsub.f32 d19, d18, d19 @ r6-r7,i6-i7
65 vadd.f32 d20, d0, d1 @ r0+r1,i0+i1
66 vadd.f32 d21, d2, d3 @ r2+r3,i2+i3
67 vmul.f32 d26, d17, d28 @ -a2r*w,a2i*w
68 vext.32 q3, q2, q2, #1
69 vmul.f32 d27, d19, d29 @ a3r*w,-a3i*w
70 vsub.f32 d23, d22, d23 @ i2-i3,r3-r2
71 vsub.f32 d22, d0, d1 @ r0-r1,i0-i1
72 vmul.f32 d24, d17, d31 @ a2r*w,a2i*w
73 vmul.f32 d25, d19, d31 @ a3r*w,a3i*w
80 vadd.f32 d24, d24, d26 @ a2r+a2i,a2i-a2r t1,t2
81 vadd.f32 d25, d25, d27 @ a3r-a3i,a3i+a3r t5,t6
84 vext.32 q13, q12, q12, #1
95 vst1.32 {d16-d19}, [r1,:128]
96 vst1.32 {d0-d3}, [r0,:128]
103 vld1.32 {d16-d19}, [r0,:128]! @ q8{r0,i0,r1,i1} q9{r2,i2,r3,i3}
105 vld1.32 {d2-d3}, [r1,:128]
106 vext.32 q13, q9, q9, #1
107 vld1.32 {d22-d25}, [r0,:128]! @ q11{r4,i4,r5,i5} q12{r6,i5,r7,i7}
108 vadd.f32 d4, d16, d17
109 vsub.f32 d5, d16, d17
110 vadd.f32 d18, d18, d19
111 vsub.f32 d19, d26, d27
113 vadd.f32 d20, d22, d23
114 vsub.f32 d22, d22, d23
115 vsub.f32 d23, d24, d25
116 vadd.f32 q8, q2, q9 @ {r0,i0,r1,i1}
117 vadd.f32 d21, d24, d25
118 vmul.f32 d24, d22, d2
119 vsub.f32 q9, q2, q9 @ {r2,i2,r3,i3}
120 vmul.f32 d25, d23, d3
121 vuzp.32 d16, d17 @ {r0,r1,i0,i1}
122 vmul.f32 q1, q11, d2[1]
123 vuzp.32 d18, d19 @ {r2,r3,i2,i3}
125 vadd.f32 q11, q12, q1 @ {t1a,t2a,t5,t6}
126 vld1.32 {d24-d27}, [r0,:128]! @ q12{r8,i8,r9,i9} q13{r10,i10,r11,i11}
128 vld1.32 {d28-d31}, [r0,:128] @ q14{r12,i12,r13,i13} q15{r14,i14,r15,i15}
129 vadd.f32 d0, d22, d20
130 vadd.f32 d1, d21, d23
131 vsub.f32 d2, d21, d23
132 vsub.f32 d3, d22, d20
134 vext.32 q13, q13, q13, #1
135 vsub.f32 q10, q8, q0 @ {r4,r5,i4,i5}
136 vadd.f32 q8, q8, q0 @ {r0,r1,i0,i1}
137 vext.32 q15, q15, q15, #1
138 vsub.f32 q11, q9, q1 @ {r6,r7,i6,i7}
139 vswp d25, d26 @ q12{r8,i8,i10,r11} q13{r9,i9,i11,r10}
140 vadd.f32 q9, q9, q1 @ {r2,r3,i2,i3}
141 vswp d29, d30 @ q14{r12,i12,i14,r15} q15{r13,i13,i15,r14}
142 vadd.f32 q0, q12, q13 @ {t1,t2,t5,t6}
143 vadd.f32 q1, q14, q15 @ {t1a,t2a,t5a,t6a}
145 vsub.f32 q13, q12, q13 @ {t3,t4,t7,t8}
147 vsub.f32 q15, q14, q15 @ {t3a,t4a,t7a,t8a}
150 vswp d1, d26 @ q0{t1,t2,t3,t4} q13{t6,t5,t7,t8}
151 vswp d3, d30 @ q1{t1a,t2a,t3a,t4a} q15{t6a,t5a,t7a,t8a}
152 vadd.f32 q12, q0, q13 @ {r8,i8,r9,i9}
153 vadd.f32 q14, q1, q15 @ {r12,i12,r13,i13}
154 vld1.32 {d4-d5}, [r2,:64]
155 vsub.f32 q13, q0, q13 @ {r10,i10,r11,i11}
156 vsub.f32 q15, q1, q15 @ {r14,i14,r15,i15}
157 vswp d25, d28 @ q12{r8,i8,r12,i12} q14{r9,i9,r13,i13}
158 vld1.32 {d6-d7}, [r3,:128]
160 vmul.f32 q14, q14, d4[1]
162 vmla.f32 q14, q1, d5[1] @ {t1a,t2a,t5a,t6a}
163 vswp d27, d30 @ q13{r10,i10,r14,i14} q15{r11,i11,r15,i15}
165 vadd.f32 d0, d28, d24
166 vadd.f32 d1, d25, d29
167 vsub.f32 d2, d25, d29
168 vsub.f32 d3, d28, d24
169 vsub.f32 q12, q8, q0 @ {r8,r9,i8,i9}
170 vadd.f32 q8, q8, q0 @ {r0,r1,i0,i1}
171 vsub.f32 q14, q10, q1 @ {r12,r13,i12,i13}
173 vadd.f32 q10, q10, q1 @ {r4,r5,i4,i5}
175 vmul.f32 q13, q13, d5[0]
177 vmul.f32 q15, q15, d5[1]
178 vst2.32 {d16-d17},[r0,:128], r1
180 vst2.32 {d20-d21},[r0,:128], r1
182 vmla.f32 q13, q0, d5[0] @ {t1,t2,t5,t6}
183 vmla.f32 q15, q1, d4[1] @ {t1a,t2a,t5a,t6a}
184 vst2.32 {d24-d25},[r0,:128], r1
185 vst2.32 {d28-d29},[r0,:128]
188 vadd.f32 d0, d30, d26
189 vadd.f32 d1, d27, d31
190 vsub.f32 d2, d27, d31
191 vsub.f32 d3, d30, d26
192 vsub.f32 q13, q9, q0 @ {r10,r11,i10,i11}
193 vadd.f32 q9, q9, q0 @ {r2,r3,i2,i3}
194 vsub.f32 q15, q11, q1 @ {r14,r15,i14,i15}
195 vadd.f32 q11, q11, q1 @ {r6,r7,i6,i7}
196 vst2.32 {d18-d19},[r0,:128], r1
197 vst2.32 {d22-d23},[r0,:128], r1
198 vst2.32 {d26-d27},[r0,:128], r1
199 vst2.32 {d30-d31},[r0,:128]
203 function fft_pass_neon
206 lsl r5, r2, #3 @ 2 * n * sizeof FFTSample
207 lsl r4, r2, #4 @ 2 * n * sizeof FFTComplex
208 lsl r2, r2, #5 @ 4 * n * sizeof FFTComplex
210 add r4, r4, r0 @ &z[o1]
211 add r2, r2, r0 @ &z[o2]
212 add r3, r3, r0 @ &z[o3]
213 vld1.32 {d20-d21},[r2,:128] @ {z[o2],z[o2+1]}
215 vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]}
217 vld1.32 {d6-d7}, [r12,:128] @ pmmp
219 vld1.32 {d4}, [r1,:64]! @ {wre[0],wre[1]}
220 sub r5, r5, #4 @ wim--
222 vmul.f32 q11, q11, d4[1]
224 vld1.32 {d5[0]}, [r5,:32] @ d5[0] = wim[-1]
225 vmla.f32 q11, q1, d5[0] @ {t1a,t2a,t5a,t6a}
226 vld2.32 {d16-d17},[r0,:128] @ {z[0],z[1]}
228 vld2.32 {d18-d19},[r4,:128] @ {z[o1],z[o1+1]}
230 vadd.f32 d0, d22, d20
231 vadd.f32 d1, d21, d23
232 vsub.f32 d2, d21, d23
233 vsub.f32 d3, d22, d20
238 vst2.32 {d20-d21},[r2,:128]! @ {z[o2],z[o2+1]}
239 vst2.32 {d16-d17},[r0,:128]! @ {z[0],z[1]}
240 vst2.32 {d22-d23},[r3,:128]! @ {z[o3],z[o3+1]}
241 vst2.32 {d18-d19},[r4,:128]! @ {z[o1],z[o1+1]}
242 sub r5, r5, #8 @ wim -= 2
244 vld1.32 {d20-d21},[r2,:128] @ {z[o2],z[o2+1]}
245 vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]}
247 vld1.32 {d4}, [r1]! @ {wre[0],wre[1]}
249 vmul.f32 q10, q10, d4[0]
251 vmul.f32 q11, q11, d4[1]
252 vld1.32 {d5}, [r5] @ {wim[-1],wim[0]}
254 sub r5, r5, #8 @ wim -= 2
256 vmla.f32 q10, q0, d5[1] @ {t1,t2,t5,t6}
257 vmla.f32 q11, q1, d5[0] @ {t1a,t2a,t5a,t6a}
258 vld2.32 {d16-d17},[r0,:128] @ {z[0],z[1]}
259 subs r6, r6, #1 @ n--
260 vld2.32 {d18-d19},[r4,:128] @ {z[o1],z[o1+1]}
262 vadd.f32 d0, d22, d20
263 vadd.f32 d1, d21, d23
264 vsub.f32 d2, d21, d23
265 vsub.f32 d3, d22, d20
270 vst2.32 {d20-d21}, [r2,:128]! @ {z[o2],z[o2+1]}
271 vst2.32 {d16-d17}, [r0,:128]! @ {z[0],z[1]}
272 vst2.32 {d22-d23}, [r3,:128]! @ {z[o3],z[o3+1]}
273 vst2.32 {d18-d19}, [r4,:128]! @ {z[o1],z[o1+1]}
279 .macro def_fft n, n2, n4
281 function fft\n\()_neon
301 def_fft 512, 256, 128
302 def_fft 1024, 512, 256
303 def_fft 2048, 1024, 512
304 def_fft 4096, 2048, 1024
305 def_fft 8192, 4096, 2048
306 def_fft 16384, 8192, 4096
307 def_fft 32768, 16384, 8192
308 def_fft 65536, 32768, 16384
310 function ff_fft_calc_neon, export=1
313 movrel r3, fft_tab_neon
314 ldr r3, [r3, r2, lsl #2]
319 function ff_fft_permute_neon, export=1
323 ldr r3, [r0, #20] @ tmp_buf
324 ldr r0, [r0, #8] @ revtab
328 vld1.32 {d0-d1}, [r1,:128]!
331 uxtah r4, r3, r4, ror #16
332 vst1.32 {d0}, [lr,:64]
333 vst1.32 {d1}, [r4,:64]
337 sub r1, r1, r2, lsl #3
339 vld1.32 {d0-d3}, [r3,:128]!
340 vst1.32 {d0-d3}, [r1,:128]!
365 .size fft_tab_neon, . - fft_tab_neon
368 pmmp: .float +1.0, -1.0, -1.0, +1.0
369 mppm: .float -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2