Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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
  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
  376.