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 32function 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 48endfunc 49 50function 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 101endfunc 102 103function 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 203endfunc 204 205function 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 2451: 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} 279endfunc 280 281.macro def_fft n, n2, n4 282 .align 6 283function 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 296endfunc 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 312function 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 319endfunc 320 321function 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 3291: 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 3421: 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} 349endfunc 350 351const 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 367endconst 368 369const pmmp, align=4 370 .float +1.0, -1.0, -1.0, +1.0 371endconst 372 373const mppm, align=4 374 .float -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2 375endconst 376