comparison arm/fft_neon.S @ 10153:7a63015e4627 libavcodec

ARM: NEON optimised FFT and MDCT Vorbis and AC3 ~3x faster. Parts by Naotoshi Nojiri, naonoj gmail
author mru
date Thu, 10 Sep 2009 08:50:03 +0000
parents
children eda985c53dba
comparison
equal deleted inserted replaced
10152:ed85bbd5dccb 10153:7a63015e4627
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 file is part of FFmpeg.
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #include "asm.S"
25
26 #define M_SQRT1_2 0.70710678118654752440
27
28 .text
29
30 function fft4_neon
31 vld1.32 {d0-d3}, [r0,:128]
32
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
38 vadd.f32 d1, d6, d7
39 vsub.f32 d3, d6, d7
40 vadd.f32 d0, d4, d5
41 vsub.f32 d2, d4, d5
42
43 vst1.32 {d0-d3}, [r0,:128]
44
45 bx lr
46 .endfunc
47
48 function fft8_neon
49 mov r1, r0
50 vld1.32 {d0-d3}, [r1,:128]!
51 vld1.32 {d16-d19}, [r1,:128]
52
53 movw r2, #0x04f3 @ sqrt(1/2)
54 movt r2, #0x3f35
55 eor r3, r2, #1<<31
56 vdup.32 d31, r2
57
58 vext.32 q11, q1, q1, #1 @ i2,r3,i3,r2
59 vadd.f32 d4, d16, d17 @ r4+r5,i4+i5
60 vmov d28, r3, r2
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
64 vrev64.32 d29, d28
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
74 vadd.f32 d0, d20, d21
75 vsub.f32 d2, d20, d21
76 vadd.f32 d1, d22, d23
77 vrev64.32 q13, q13
78 vsub.f32 d3, d22, d23
79 vsub.f32 d6, d6, d7
80 vadd.f32 d24, d24, d26 @ a2r+a2i,a2i-a2r t1,t2
81 vadd.f32 d25, d25, d27 @ a3r-a3i,a3i+a3r t5,t6
82 vadd.f32 d7, d4, d5
83 vsub.f32 d18, d2, d6
84 vext.32 q13, q12, q12, #1
85 vadd.f32 d2, d2, d6
86 vsub.f32 d16, d0, d7
87 vadd.f32 d5, d25, d24
88 vsub.f32 d4, d26, d27
89 vadd.f32 d0, d0, d7
90 vsub.f32 d17, d1, d5
91 vsub.f32 d19, d3, d4
92 vadd.f32 d3, d3, d4
93 vadd.f32 d1, d1, d5
94
95 vst1.32 {d16-d19}, [r1,:128]
96 vst1.32 {d0-d3}, [r0,:128]
97
98 bx lr
99 .endfunc
100
101 function fft16_neon
102 movrel r1, mppm
103 vld1.32 {d16-d19}, [r0,:128]! @ q8{r0,i0,r1,i1} q9{r2,i2,r3,i3}
104 pld [r0, #32]
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
112
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}
124 vrev64.32 q12, q12
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}
127 vzip.32 q10, q11
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
133 sub r0, r0, #96
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}
144 movrel r2, ff_cos_16
145 vsub.f32 q13, q12, q13 @ {t3,t4,t7,t8}
146 vrev64.32 d1, d1
147 vsub.f32 q15, q14, q15 @ {t3a,t4a,t7a,t8a}
148 vrev64.32 d3, d3
149 movrel r3, pmmp
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]
159 vrev64.32 q1, q14
160 vmul.f32 q14, q14, d4[1]
161 vmul.f32 q1, q1, q3
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}
164 vzip.32 q12, q14
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}
172 mov r1, #32
173 vadd.f32 q10, q10, q1 @ {r4,r5,i4,i5}
174 vrev64.32 q0, q13
175 vmul.f32 q13, q13, d5[0]
176 vrev64.32 q1, q15
177 vmul.f32 q15, q15, d5[1]
178 vst2.32 {d16-d17},[r0,:128], r1
179 vmul.f32 q0, q0, q3
180 vst2.32 {d20-d21},[r0,:128], r1
181 vmul.f32 q1, q1, q3
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]
186 vzip.32 q13, q15
187 sub r0, r0, #80
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]
200 bx lr
201 .endfunc
202
203 function fft_pass_neon
204 push {r4-r6,lr}
205 mov r6, r2 @ n
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
209 add r3, r2, r4
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]}
214 movrel r12, pmmp
215 vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]}
216 add r5, r5, r1 @ wim
217 vld1.32 {d6-d7}, [r12,:128] @ pmmp
218 vswp d21, d22
219 vld1.32 {d4}, [r1,:64]! @ {wre[0],wre[1]}
220 sub r5, r5, #4 @ wim--
221 vrev64.32 q1, q11
222 vmul.f32 q11, q11, d4[1]
223 vmul.f32 q1, q1, q3
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]}
227 sub r6, r6, #1 @ n--
228 vld2.32 {d18-d19},[r4,:128] @ {z[o1],z[o1+1]}
229 vzip.32 q10, q11
230 vadd.f32 d0, d22, d20
231 vadd.f32 d1, d21, d23
232 vsub.f32 d2, d21, d23
233 vsub.f32 d3, d22, d20
234 vsub.f32 q10, q8, q0
235 vadd.f32 q8, q8, q0
236 vsub.f32 q11, q9, q1
237 vadd.f32 q9, q9, q1
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
243 1:
244 vld1.32 {d20-d21},[r2,:128] @ {z[o2],z[o2+1]}
245 vld1.32 {d22-d23},[r3,:128] @ {z[o3],z[o3+1]}
246 vswp d21, d22
247 vld1.32 {d4}, [r1]! @ {wre[0],wre[1]}
248 vrev64.32 q0, q10
249 vmul.f32 q10, q10, d4[0]
250 vrev64.32 q1, q11
251 vmul.f32 q11, q11, d4[1]
252 vld1.32 {d5}, [r5] @ {wim[-1],wim[0]}
253 vmul.f32 q0, q0, q3
254 sub r5, r5, #8 @ wim -= 2
255 vmul.f32 q1, q1, q3
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]}
261 vzip.32 q10, q11
262 vadd.f32 d0, d22, d20
263 vadd.f32 d1, d21, d23
264 vsub.f32 d2, d21, d23
265 vsub.f32 d3, d22, d20
266 vsub.f32 q10, q8, q0
267 vadd.f32 q8, q8, q0
268 vsub.f32 q11, q9, q1
269 vadd.f32 q9, q9, q1
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]}
274 bne 1b
275
276 pop {r4-r6,pc}
277 .endfunc
278
279 .macro def_fft n, n2, n4
280 .align 6
281 function fft\n\()_neon
282 push {r4, lr}
283 mov r4, r0
284 bl fft\n2\()_neon
285 add r0, r4, #\n4*2*8
286 bl fft\n4\()_neon
287 add r0, r4, #\n4*3*8
288 bl fft\n4\()_neon
289 mov r0, r4
290 pop {r4, lr}
291 movrel r1, ff_cos_\n
292 mov r2, #\n4/2
293 b fft_pass_neon
294 .endfunc
295 .endm
296
297 def_fft 32, 16, 8
298 def_fft 64, 32, 16
299 def_fft 128, 64, 32
300 def_fft 256, 128, 64
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
309
310 function ff_fft_calc_neon, export=1
311 ldr r2, [r0]
312 sub r2, r2, #2
313 movrel r3, fft_tab_neon
314 ldr r3, [r3, r2, lsl #2]
315 mov r0, r1
316 bx r3
317 .endfunc
318
319 function ff_fft_permute_neon, export=1
320 push {r4,lr}
321 mov r12, #1
322 ldr r2, [r0] @ nbits
323 ldr r3, [r0, #20] @ tmp_buf
324 ldr r0, [r0, #8] @ revtab
325 lsl r12, r12, r2
326 mov r2, r12
327 1:
328 vld1.32 {d0-d1}, [r1,:128]!
329 ldr r4, [r0], #4
330 uxtah lr, r3, r4
331 uxtah r4, r3, r4, ror #16
332 vst1.32 {d0}, [lr,:64]
333 vst1.32 {d1}, [r4,:64]
334 subs r12, r12, #2
335 bgt 1b
336
337 sub r1, r1, r2, lsl #3
338 1:
339 vld1.32 {d0-d3}, [r3,:128]!
340 vst1.32 {d0-d3}, [r1,:128]!
341 subs r2, r2, #4
342 bgt 1b
343
344 pop {r4,pc}
345 .endfunc
346
347 .section .rodata
348 .align 4
349 fft_tab_neon:
350 .word fft4_neon
351 .word fft8_neon
352 .word fft16_neon
353 .word fft32_neon
354 .word fft64_neon
355 .word fft128_neon
356 .word fft256_neon
357 .word fft512_neon
358 .word fft1024_neon
359 .word fft2048_neon
360 .word fft4096_neon
361 .word fft8192_neon
362 .word fft16384_neon
363 .word fft32768_neon
364 .word fft65536_neon
365 .size fft_tab_neon, . - fft_tab_neon
366
367 .align 4
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