You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
15KB

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