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.

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