Merge commit 'a6a750c7ef240b72ce01e9653343a0ddf247d196'
[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 "libavutil/arm/asm.S"
28
29 #define M_SQRT1_2 0.70710678118654752440
30
31
32 function fft4_neon
33         vld1.32         {d0-d3}, [r0,:128]
34
35         vext.32         q8,  q1,  q1,  #1       @ i2,r3 d3=i3,r2
36         vsub.f32        d6,  d0,  d1            @ r0-r1,i0-i1
37         vsub.f32        d7,  d16, d17           @ r3-r2,i2-i3
38         vadd.f32        d4,  d0,  d1            @ r0+r1,i0+i1
39         vadd.f32        d5,  d2,  d3            @ i2+i3,r2+r3
40         vadd.f32        d1,  d6,  d7
41         vsub.f32        d3,  d6,  d7
42         vadd.f32        d0,  d4,  d5
43         vsub.f32        d2,  d4,  d5
44
45         vst1.32         {d0-d3}, [r0,:128]
46
47         bx              lr
48 endfunc
49
50 function fft8_neon
51         mov             r1,  r0
52         vld1.32         {d0-d3},   [r1,:128]!
53         vld1.32         {d16-d19}, [r1,:128]
54
55         movw            r2,  #0x04f3            @ sqrt(1/2)
56         movt            r2,  #0x3f35
57         eor             r3,  r2,  #1<<31
58         vdup.32         d31, r2
59
60         vext.32         q11, q1,  q1,  #1       @ i2,r3,i3,r2
61         vadd.f32        d4,  d16, d17           @ r4+r5,i4+i5
62         vmov            d28, r3,  r2
63         vadd.f32        d5,  d18, d19           @ r6+r7,i6+i7
64         vsub.f32        d17, d16, d17           @ r4-r5,i4-i5
65         vsub.f32        d19, d18, d19           @ r6-r7,i6-i7
66         vrev64.32       d29, d28
67         vadd.f32        d20, d0,  d1            @ r0+r1,i0+i1
68         vadd.f32        d21, d2,  d3            @ r2+r3,i2+i3
69         vmul.f32        d26, d17, d28           @ -a2r*w,a2i*w
70         vext.32         q3,  q2,  q2,  #1
71         vmul.f32        d27, d19, d29           @ a3r*w,-a3i*w
72         vsub.f32        d23, d22, d23           @ i2-i3,r3-r2
73         vsub.f32        d22, d0,  d1            @ r0-r1,i0-i1
74         vmul.f32        d24, d17, d31           @ a2r*w,a2i*w
75         vmul.f32        d25, d19, d31           @ a3r*w,a3i*w
76         vadd.f32        d0,  d20, d21
77         vsub.f32        d2,  d20, d21
78         vadd.f32        d1,  d22, d23
79         vrev64.32       q13, q13
80         vsub.f32        d3,  d22, d23
81         vsub.f32        d6,  d6,  d7
82         vadd.f32        d24, d24, d26           @ a2r+a2i,a2i-a2r   t1,t2
83         vadd.f32        d25, d25, d27           @ a3r-a3i,a3i+a3r   t5,t6
84         vadd.f32        d7,  d4,  d5
85         vsub.f32        d18, d2,  d6
86         vext.32         q13, q12, q12, #1
87         vadd.f32        d2,  d2,  d6
88         vsub.f32        d16, d0,  d7
89         vadd.f32        d5,  d25, d24
90         vsub.f32        d4,  d26, d27
91         vadd.f32        d0,  d0,  d7
92         vsub.f32        d17, d1,  d5
93         vsub.f32        d19, d3,  d4
94         vadd.f32        d3,  d3,  d4
95         vadd.f32        d1,  d1,  d5
96
97         vst1.32         {d16-d19}, [r1,:128]
98         vst1.32         {d0-d3},   [r0,:128]
99
100         bx              lr
101 endfunc
102
103 function fft16_neon
104         movrel          r1, mppm
105         vld1.32         {d16-d19}, [r0,:128]!   @ q8{r0,i0,r1,i1} q9{r2,i2,r3,i3}
106         pld             [r0, #32]
107         vld1.32         {d2-d3}, [r1,:128]
108         vext.32         q13, q9,  q9,  #1
109         vld1.32         {d22-d25}, [r0,:128]!   @ q11{r4,i4,r5,i5} q12{r6,i5,r7,i7}
110         vadd.f32        d4,  d16, d17
111         vsub.f32        d5,  d16, d17
112         vadd.f32        d18, d18, d19
113         vsub.f32        d19, d26, d27
114
115         vadd.f32        d20, d22, d23
116         vsub.f32        d22, d22, d23
117         vsub.f32        d23, d24, d25
118         vadd.f32        q8,  q2,  q9            @ {r0,i0,r1,i1}
119         vadd.f32        d21, d24, d25
120         vmul.f32        d24, d22, d2
121         vsub.f32        q9,  q2,  q9            @ {r2,i2,r3,i3}
122         vmul.f32        d25, d23, d3
123         vuzp.32         d16, d17                @ {r0,r1,i0,i1}
124         vmul.f32        q1,  q11, d2[1]
125         vuzp.32         d18, d19                @ {r2,r3,i2,i3}
126         vrev64.32       q12, q12
127         vadd.f32        q11, q12, q1            @ {t1a,t2a,t5,t6}
128         vld1.32         {d24-d27}, [r0,:128]!   @ q12{r8,i8,r9,i9} q13{r10,i10,r11,i11}
129         vzip.32         q10, q11
130         vld1.32         {d28-d31}, [r0,:128]    @ q14{r12,i12,r13,i13} q15{r14,i14,r15,i15}
131         vadd.f32        d0,  d22, d20
132         vadd.f32        d1,  d21, d23
133         vsub.f32        d2,  d21, d23
134         vsub.f32        d3,  d22, d20
135         sub             r0,  r0,  #96
136         vext.32         q13, q13, q13, #1
137         vsub.f32        q10, q8,  q0            @ {r4,r5,i4,i5}
138         vadd.f32        q8,  q8,  q0            @ {r0,r1,i0,i1}
139         vext.32         q15, q15, q15, #1
140         vsub.f32        q11, q9,  q1            @ {r6,r7,i6,i7}
141         vswp            d25, d26                @ q12{r8,i8,i10,r11} q13{r9,i9,i11,r10}
142         vadd.f32        q9,  q9,  q1            @ {r2,r3,i2,i3}
143         vswp            d29, d30                @ q14{r12,i12,i14,r15} q15{r13,i13,i15,r14}
144         vadd.f32        q0,  q12, q13           @ {t1,t2,t5,t6}
145         vadd.f32        q1,  q14, q15           @ {t1a,t2a,t5a,t6a}
146         movrelx         r2,  X(ff_cos_16)
147         vsub.f32        q13, q12, q13           @ {t3,t4,t7,t8}
148         vrev64.32       d1,  d1
149         vsub.f32        q15, q14, q15           @ {t3a,t4a,t7a,t8a}
150         vrev64.32       d3,  d3
151         movrel          r3,  pmmp
152         vswp            d1,  d26                @ q0{t1,t2,t3,t4} q13{t6,t5,t7,t8}
153         vswp            d3,  d30                @ q1{t1a,t2a,t3a,t4a} q15{t6a,t5a,t7a,t8a}
154         vadd.f32        q12, q0,  q13           @ {r8,i8,r9,i9}
155         vadd.f32        q14, q1,  q15           @ {r12,i12,r13,i13}
156         vld1.32         {d4-d5},  [r2,:64]
157         vsub.f32        q13, q0,  q13           @ {r10,i10,r11,i11}
158         vsub.f32        q15, q1,  q15           @ {r14,i14,r15,i15}
159         vswp            d25, d28                @ q12{r8,i8,r12,i12} q14{r9,i9,r13,i13}
160         vld1.32         {d6-d7},  [r3,:128]
161         vrev64.32       q1,  q14
162         vmul.f32        q14, q14, d4[1]
163         vmul.f32        q1,  q1,  q3
164         vmla.f32        q14, q1,  d5[1]         @ {t1a,t2a,t5a,t6a}
165         vswp            d27, d30                @ q13{r10,i10,r14,i14} q15{r11,i11,r15,i15}
166         vzip.32         q12, q14
167         vadd.f32        d0,  d28, d24
168         vadd.f32        d1,  d25, d29
169         vsub.f32        d2,  d25, d29
170         vsub.f32        d3,  d28, d24
171         vsub.f32        q12, q8,  q0            @ {r8,r9,i8,i9}
172         vadd.f32        q8,  q8,  q0            @ {r0,r1,i0,i1}
173         vsub.f32        q14, q10, q1            @ {r12,r13,i12,i13}
174         mov             r1,  #32
175         vadd.f32        q10, q10, q1            @ {r4,r5,i4,i5}
176         vrev64.32       q0,  q13
177         vmul.f32        q13, q13, d5[0]
178         vrev64.32       q1,  q15
179         vmul.f32        q15, q15, d5[1]
180         vst2.32         {d16-d17},[r0,:128], r1
181         vmul.f32        q0,  q0,  q3
182         vst2.32         {d20-d21},[r0,:128], r1
183         vmul.f32        q1,  q1,  q3
184         vmla.f32        q13, q0,  d5[0]         @ {t1,t2,t5,t6}
185         vmla.f32        q15, q1,  d4[1]         @ {t1a,t2a,t5a,t6a}
186         vst2.32         {d24-d25},[r0,:128], r1
187         vst2.32         {d28-d29},[r0,:128]
188         vzip.32         q13, q15
189         sub             r0, r0, #80
190         vadd.f32        d0,  d30, d26
191         vadd.f32        d1,  d27, d31
192         vsub.f32        d2,  d27, d31
193         vsub.f32        d3,  d30, d26
194         vsub.f32        q13, q9,  q0            @ {r10,r11,i10,i11}
195         vadd.f32        q9,  q9,  q0            @ {r2,r3,i2,i3}
196         vsub.f32        q15, q11, q1            @ {r14,r15,i14,i15}
197         vadd.f32        q11, q11, q1            @ {r6,r7,i6,i7}
198         vst2.32         {d18-d19},[r0,:128], r1
199         vst2.32         {d22-d23},[r0,:128], r1
200         vst2.32         {d26-d27},[r0,:128], r1
201         vst2.32         {d30-d31},[r0,:128]
202         bx              lr
203 endfunc
204
205 function fft_pass_neon
206         push            {r4-r6,lr}
207         mov             r6,  r2                 @ n
208         lsl             r5,  r2,  #3            @ 2 * n * sizeof FFTSample
209         lsl             r4,  r2,  #4            @ 2 * n * sizeof FFTComplex
210         lsl             r2,  r2,  #5            @ 4 * n * sizeof FFTComplex
211         add             r3,  r2,  r4
212         add             r4,  r4,  r0            @ &z[o1]
213         add             r2,  r2,  r0            @ &z[o2]
214         add             r3,  r3,  r0            @ &z[o3]
215         vld1.32         {d20-d21},[r2,:128]     @ {z[o2],z[o2+1]}
216         movrel          r12, pmmp
217         vld1.32         {d22-d23},[r3,:128]     @ {z[o3],z[o3+1]}
218         add             r5,  r5,  r1            @ wim
219         vld1.32         {d6-d7},  [r12,:128]    @ pmmp
220         vswp            d21, d22
221         vld1.32         {d4},     [r1,:64]!     @ {wre[0],wre[1]}
222         sub             r5,  r5,  #4            @ wim--
223         vrev64.32       q1,  q11
224         vmul.f32        q11, q11, d4[1]
225         vmul.f32        q1,  q1,  q3
226         vld1.32         {d5[0]},  [r5,:32]      @ d5[0] = wim[-1]
227         vmla.f32        q11, q1,  d5[0]         @ {t1a,t2a,t5a,t6a}
228         vld2.32         {d16-d17},[r0,:128]     @ {z[0],z[1]}
229         sub             r6, r6, #1              @ n--
230         vld2.32         {d18-d19},[r4,:128]     @ {z[o1],z[o1+1]}
231         vzip.32         q10, q11
232         vadd.f32        d0,  d22, d20
233         vadd.f32        d1,  d21, d23
234         vsub.f32        d2,  d21, d23
235         vsub.f32        d3,  d22, d20
236         vsub.f32        q10, q8,  q0
237         vadd.f32        q8,  q8,  q0
238         vsub.f32        q11, q9,  q1
239         vadd.f32        q9,  q9,  q1
240         vst2.32         {d20-d21},[r2,:128]!    @ {z[o2],z[o2+1]}
241         vst2.32         {d16-d17},[r0,:128]!    @ {z[0],z[1]}
242         vst2.32         {d22-d23},[r3,:128]!    @ {z[o3],z[o3+1]}
243         vst2.32         {d18-d19},[r4,:128]!    @ {z[o1],z[o1+1]}
244         sub             r5,  r5,  #8            @ wim -= 2
245 1:
246         vld1.32         {d20-d21},[r2,:128]     @ {z[o2],z[o2+1]}
247         vld1.32         {d22-d23},[r3,:128]     @ {z[o3],z[o3+1]}
248         vswp            d21, d22
249         vld1.32         {d4}, [r1]!             @ {wre[0],wre[1]}
250         vrev64.32       q0,  q10
251         vmul.f32        q10, q10, d4[0]
252         vrev64.32       q1,  q11
253         vmul.f32        q11, q11, d4[1]
254         vld1.32         {d5}, [r5]              @ {wim[-1],wim[0]}
255         vmul.f32        q0,  q0,  q3
256         sub             r5,  r5,  #8            @ wim -= 2
257         vmul.f32        q1,  q1,  q3
258         vmla.f32        q10, q0,  d5[1]         @ {t1,t2,t5,t6}
259         vmla.f32        q11, q1,  d5[0]         @ {t1a,t2a,t5a,t6a}
260         vld2.32         {d16-d17},[r0,:128]     @ {z[0],z[1]}
261         subs            r6,  r6,  #1            @ n--
262         vld2.32         {d18-d19},[r4,:128]     @ {z[o1],z[o1+1]}
263         vzip.32         q10, q11
264         vadd.f32        d0,  d22, d20
265         vadd.f32        d1,  d21, d23
266         vsub.f32        d2,  d21, d23
267         vsub.f32        d3,  d22, d20
268         vsub.f32        q10, q8,  q0
269         vadd.f32        q8,  q8,  q0
270         vsub.f32        q11, q9,  q1
271         vadd.f32        q9,  q9,  q1
272         vst2.32         {d20-d21}, [r2,:128]!   @ {z[o2],z[o2+1]}
273         vst2.32         {d16-d17}, [r0,:128]!   @ {z[0],z[1]}
274         vst2.32         {d22-d23}, [r3,:128]!   @ {z[o3],z[o3+1]}
275         vst2.32         {d18-d19}, [r4,:128]!   @ {z[o1],z[o1+1]}
276         bne             1b
277
278         pop             {r4-r6,pc}
279 endfunc
280
281 .macro  def_fft n, n2, n4
282         .align 6
283 function fft\n\()_neon
284         push            {r4, lr}
285         mov             r4,  r0
286         bl              fft\n2\()_neon
287         add             r0,  r4,  #\n4*2*8
288         bl              fft\n4\()_neon
289         add             r0,  r4,  #\n4*3*8
290         bl              fft\n4\()_neon
291         mov             r0,  r4
292         pop             {r4, lr}
293         movrelx         r1,  X(ff_cos_\n)
294         mov             r2,  #\n4/2
295         b               fft_pass_neon
296 endfunc
297 .endm
298
299         def_fft    32,    16,     8
300         def_fft    64,    32,    16
301         def_fft   128,    64,    32
302         def_fft   256,   128,    64
303         def_fft   512,   256,   128
304         def_fft  1024,   512,   256
305         def_fft  2048,  1024,   512
306         def_fft  4096,  2048,  1024
307         def_fft  8192,  4096,  2048
308         def_fft 16384,  8192,  4096
309         def_fft 32768, 16384,  8192
310         def_fft 65536, 32768, 16384
311
312 function ff_fft_calc_neon, export=1
313         ldr             r2,  [r0]
314         sub             r2,  r2,  #2
315         movrel          r3,  fft_tab_neon
316         ldr             r3,  [r3, r2, lsl #2]
317         mov             r0,  r1
318         bx              r3
319 endfunc
320
321 function ff_fft_permute_neon, export=1
322         push            {r4,lr}
323         mov             r12, #1
324         ldr             r2,  [r0]       @ nbits
325         ldr             r3,  [r0, #12]  @ tmp_buf
326         ldr             r0,  [r0, #8]   @ revtab
327         lsl             r12, r12, r2
328         mov             r2,  r12
329 1:
330         vld1.32         {d0-d1}, [r1,:128]!
331         ldr             r4,  [r0], #4
332         uxth            lr,  r4
333         uxth            r4,  r4,  ror #16
334         add             lr,  r3,  lr,  lsl #3
335         add             r4,  r3,  r4,  lsl #3
336         vst1.32         {d0}, [lr,:64]
337         vst1.32         {d1}, [r4,:64]
338         subs            r12, r12, #2
339         bgt             1b
340
341         sub             r1,  r1,  r2,  lsl #3
342 1:
343         vld1.32         {d0-d3}, [r3,:128]!
344         vst1.32         {d0-d3}, [r1,:128]!
345         subs            r2,  r2,  #4
346         bgt             1b
347
348         pop             {r4,pc}
349 endfunc
350
351 const   fft_tab_neon, relocate=1
352         .word fft4_neon
353         .word fft8_neon
354         .word fft16_neon
355         .word fft32_neon
356         .word fft64_neon
357         .word fft128_neon
358         .word fft256_neon
359         .word fft512_neon
360         .word fft1024_neon
361         .word fft2048_neon
362         .word fft4096_neon
363         .word fft8192_neon
364         .word fft16384_neon
365         .word fft32768_neon
366         .word fft65536_neon
367 endconst
368
369 const   pmmp, align=4
370         .float          +1.0, -1.0, -1.0, +1.0
371 endconst
372
373 const   mppm, align=4
374         .float          -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2
375 endconst