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.

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