1 @// 2 @// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 @// 4 @// Use of this source code is governed by a BSD-style license 5 @// that can be found in the LICENSE file in the root of the source 6 @// tree. An additional intellectual property rights grant can be found 7 @// in the file PATENTS. All contributing project authors may 8 @// be found in the AUTHORS file in the root of the source tree. 9 @// 10 @// This is a modification of armSP_FFT_CToC_SC32_Radix4_unsafe_s.S 11 @// to support float instead of SC32. 12 @// 13 14 @// 15 @// Description: 16 @// Compute a Radix 4 FFT stage for a N point complex signal 17 @// 18 @// 19 20 21 @// Include standard headers 22 23 #include "dl/api/arm/armCOMM_s.h" 24 #include "dl/api/arm/omxtypes_s.h" 25 26 @// M_VARIANTS ARM1136JS 27 28 @// Import symbols required from other files 29 @// (For example tables) 30 31 32 33 34 @// Set debugging level 35 @//DEBUG_ON SETL {TRUE} 36 37 38 39 @// Guarding implementation by the processor name 40 41 @// IF ARM1136JS 42 43 @//Input Registers 44 45 #define pSrc r0 46 #define pDst r2 47 #define pTwiddle r1 48 #define subFFTNum r6 49 #define subFFTSize r7 50 51 52 53 @//Output Registers 54 55 56 @//Local Scratch Registers 57 58 #define grpCount r12 59 #define step r12 /*@// Reuse grpCount*/ 60 #define outPointStep r3 61 #define setCount r8 62 #define diff r9 63 #define pointStep r14 64 65 #define t1 r3 /*@// Reuse outPointStep*/ 66 67 @// Real and Imaginary parts used in the inner grp loop 68 #define x0r s0 69 #define x0i s1 70 #define x1r s2 71 #define x1i s3 72 #define x2r s4 73 #define x2i s5 74 #define x3r s6 75 #define x3i s7 76 77 @// Temporary reg to hold the twiddle multiplies 78 79 #define t0r s8 80 #define t0i s9 81 #define t2r s10 82 #define t2i s11 83 #define sr s12 84 #define si s13 85 86 87 88 89 .macro FFTSTAGE scaled, inverse , name 90 91 @// Define stack arguments 92 93 94 @// Update grpCount and grpSize rightaway inorder to reuse 95 @// pGrpCount and pGrpSize regs 96 97 LSL grpCount,subFFTSize,#2 98 lsr subFFTNum, subFFTNum, #2 99 mov subFFTSize, grpCount 100 101 102 @// pT0+1 increments pT0 by 8 bytes 103 @// pT0+pointStep = increment of 8*pointStep bytes = 2*grpSize bytes 104 mov pointStep, subFFTNum, lsl #1 105 106 107 @// pOut0+1 increments pOut0 by 8 bytes 108 @// pOut0+outPointStep == increment of 8*outPointStep bytes = 2*size 109 @// bytes 110 111 @// Use setCount as dummy. It's set correctly below. 112 smull outPointStep, setCount, grpCount, pointStep 113 114 LSL pointStep,pointStep,#2 @// 2*grpSize 115 116 117 MOV setCount,pointStep,LSR #3 118 119 @// Interchange grpLoop and setLoop 120 121 setLoop\name: 122 123 MOV step,#0 124 @// Set pSrc and pDst for the grpLoop 125 126 SUB diff,outPointStep,pointStep 127 128 @// Save setCount on stack to reuse the reg 129 130 ADD pSrc,pSrc,diff,LSL #2 @// pSrc += (grpCount-1)*grpStep 131 ADD pDst,pDst,diff @// pDst += (grpCount-1)*setCount 132 ADD step,step,diff @// step += (grpCount-1)*setCount 133 134 135 136 @// Loop on the grps 137 138 grpLoop\name: 139 140 141 142 @// butterfly loop 143 add pSrc, pointStep 144 vldm.f32 pSrc, {x3r, x3i} @// data[1] 145 add pTwiddle, step 146 vldm.f32 pTwiddle, {x1r, x1i} @// coef[1] 147 add pTwiddle, step 148 vldm.f32 pTwiddle, {x2r, x2i} @// coef[2] 149 add pSrc, pointStep 150 vldm.f32 pSrc, {x0r, x0i} @// data[2] 151 152 @// do first complex multiply 153 vmul.f32 t0r, x3r, x1r 154 vmul.f32 t0i, x3i, x1r 155 156 .ifeqs "\inverse", "TRUE" 157 vmla.f32 t0r, x3i, x1i 158 vmls.f32 t0i, x3r, x1i 159 vmov.f32 x1r, t0r 160 vmov.f32 x1i, t0i 161 .else 162 vmls.f32 t0r, x3i, x1i 163 vmla.f32 t0i, x3r, x1i 164 vmov.f32 x1r, t0r 165 vmov.f32 x1i, t0i 166 .endif 167 168 add pTwiddle, pTwiddle, step 169 vldm pTwiddle, {x3r, x3i} @// coef[3] 170 sub pTwiddle, pTwiddle, step 171 172 @// do second complex multiply 173 vmul.f32 t0r, x0r, x2r 174 vmul.f32 t0i, x0i, x2r 175 176 .ifeqs "\inverse", "TRUE" 177 vmla.f32 t0r, x0i, x2i 178 vmls.f32 t0i, x0r, x2i 179 vmov.f32 x2r, t0r 180 vmov.f32 x2i, t0i 181 .else 182 vmls.f32 t0r, x0i, x2i 183 vmla.f32 t0i, x0r, x2i 184 vmov.f32 x2r, t0r 185 vmov.f32 x2i, t0i 186 .endif 187 188 add pSrc, pointStep 189 vldm pSrc, {x0r, x0i} @// data[3] 190 sub pSrc, pointStep 191 192 SUB pTwiddle,pTwiddle,step,LSL #1 @// reset pTwiddle 193 SUBS step,step,pointStep @// decrement loop counter 194 195 @// do third complex multiply 196 SUB pSrc,pSrc,pointStep,LSL #1 @// reset pSrc to data[0] 197 vmul.f32 t0r, x0r, x3r 198 vmul.f32 t0i, x0i, x3r 199 200 .ifeqs "\inverse", "TRUE" 201 vmla.f32 t0r, x0i, x3i 202 vmls.f32 t0i, x0r, x3i 203 vmov.f32 x3r, t0r 204 vmov.f32 x3i, t0i 205 .else 206 vmls.f32 t0r, x0i, x3i 207 vmla.f32 t0i, x0r, x3i 208 vmov.f32 x3r, t0r 209 vmov.f32 x3i, t0i 210 .endif 211 212 vldm pSrc, {x0r, x0i} @// data[0] 213 214 @// finish first stage of 4 point FFT 215 vadd.f32 x0r,x0r,x2r @// x0 = x0 + x2 (u0) 216 vadd.f32 x0i,x0i,x2i 217 218 vadd.f32 sr, x2r, x2r 219 vadd.f32 si, x2i, x2i 220 vsub.f32 x2r,x0r,sr @// x2 = x0 - x2 (u1) 221 vsub.f32 x2i,x0i,si 222 223 vadd.f32 x1r,x1r,x3r @// x1 = x1/2 + x3/2 (u2/2) 224 vadd.f32 x1i,x1i,x3i 225 226 vadd.f32 sr, x3r, x3r 227 vadd.f32 si, x3i, x3i 228 vsub.f32 x3r,x1r,sr @// x3 = x1/2 - x3/2 (u3/2) 229 vsub.f32 x3i,x1i,si 230 231 232 @// finish second stage of 4 point FFT 233 234 @// y0 = u1-u2 since twiddle's are stored as -ve values 235 vsub.f32 x2r,x2r,x1r 236 vsub.f32 x2i,x2i,x1i 237 238 vadd.f32 sr, x1r, x1r 239 vadd.f32 si, x1i, x1i 240 vadd.f32 x1r,x2r,sr @// y2 = u1+u2 241 vadd.f32 x1i,x2i,si 242 vstm pDst, {x2r, x2i} @// store y0 243 244 vsub.f32 x0r,x0r,x3i @// y3 = u0+ju3 245 vadd.f32 x0i,x0i,x3r 246 247 vadd.f32 sr, x3r, x3r 248 vadd.f32 si, x3i, x3i 249 vadd.f32 t2r,x0r,si @// y1 = u0-ju3 250 vsub.f32 t2i,x0i,sr @// t2 will be same as x2r reg 251 252 .ifeqs "\inverse", "TRUE" 253 add pDst, outPointStep 254 vstm pDst, {t2r, t2i} @// store y1 255 add pDst, outPointStep 256 vstm pDst, {x1r, x1i} @// store y2 257 add pDst, outPointStep 258 vstm pDst, {x0r, x0i} @// store y3 259 sub pDst, outPointStep 260 .else 261 add pDst, outPointStep 262 vstm pDst, {x0r, x0i} @// store y1 263 add pDst, outPointStep 264 vstm pDst, {x1r, x1i} @// store y2 265 add pDst, outPointStep 266 vstm pDst, {t2r, t2i} @// store y3 267 sub pDst, outPointStep 268 .endif 269 270 SUB pDst,pDst,outPointStep, LSL #1 @// reset pDst 271 @// update the pDst for the next grp 272 SUBGE pDst,pDst,pointStep 273 @// update the pSrc for the next grp 274 SUBGE pSrc,pSrc,pointStep,LSL #2 275 276 277 BGE grpLoop\name 278 279 ADD pSrc,pSrc,#8 @// pSrc += 1; for the next set 280 ADD pDst,pDst,#8 @// pDst += 1; for the next set 281 282 SUBS setCount,setCount,#1 @// decrement loop counter 283 284 285 BGT setLoop\name 286 287 @// Reset and Swap pSrc and pDst for the next stage 288 MOV t1,pDst 289 SUB pDst,pSrc,subFFTNum,LSL #3 290 SUB pSrc,t1,subFFTNum,LSL #3 291 292 .endm 293 294 295 M_START armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace_unsafe_vfp,r4 296 FFTSTAGE "FALSE","FALSE",FWD 297 M_END 298 299 M_START armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace_unsafe_vfp,r4 300 FFTSTAGE "FALSE","TRUE",INV 301 M_END 302 303 304 @// ENDIF @//ARM1136JS 305 306 307 308 @// Guarding implementation by the processor name 309 310 .end 311