1 @ 2 @ Copyright (c) 2012 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 @ Reference code in transform.c. Bit not exact due to how rounding is 11 @ done in C code and ARM instructions, but quality by assembly code is 12 @ not worse. 13 14 #include "webrtc/modules/audio_coding/codecs/isac/fix/source/settings.h" 15 #include "webrtc/system_wrappers/interface/asm_defines.h" 16 17 GLOBAL_FUNCTION WebRtcIsacfix_Spec2TimeNeon 18 GLOBAL_FUNCTION WebRtcIsacfix_Time2SpecNeon 19 GLOBAL_LABEL WebRtcIsacfix_kSinTab1 20 GLOBAL_LABEL WebRtcIsacfix_kCosTab1 21 GLOBAL_LABEL WebRtcIsacfix_kSinTab2 22 23 @ void WebRtcIsacfix_Time2SpecNeon(int16_t* inre1Q9, 24 @ int16_t* inre2Q9, 25 @ int16_t* outreQ7, 26 @ int16_t* outimQ7); 27 28 DEFINE_FUNCTION WebRtcIsacfix_Time2SpecNeon 29 .align 2 30 push {r4-r11,lr} 31 sub sp, sp, #(16 + FRAMESAMPLES * 4) 32 33 str r0, [sp] @ inre1Q9 34 str r1, [sp, #4] @ inre2Q9 35 str r2, [sp, #8] @ outreQ7 36 str r3, [sp, #12] @ outimQ7 37 38 mov r8, #(FRAMESAMPLES - 16) 39 add r12, r0, r8 @ &inreQ7[FRAMESAMPLES / 2 - 4] 40 add r11, r1, r8 @ &inimQ7[FRAMESAMPLES / 2 - 4] 41 add r4, sp, #16 @ tmpreQ16; 42 add r5, sp, #(16 + FRAMESAMPLES * 2) @ tmpimQ16; 43 44 adr r9, WebRtcIsacfix_kCosTab1 45 #if defined(__APPLE__) 46 mov r6, #:lower16:(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1) 47 #else 48 mov r6, #(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1) 49 #endif 50 add r10, r9, r6 @ WebRtcIsacfix_kSinTab1 51 52 vmov.u32 q14, #0 @ Initialize the maximum values for tmpInIm. 53 vmov.u32 q15, #0 @ Initialize the maximum values for tmpInRe. 54 movw r6, #16921 @ 0.5 / sqrt(240) in Q19 55 lsl r6, #5 @ Together with vqdmulh, net effect is ">> 26". 56 mov r8, #(FRAMESAMPLES / 2) @ loop counter 57 vdup.s32 q11, r6 58 59 Time2Spec_TransformAndFindMax: 60 @ Use ">> 26", instead of ">> 7", ">> 16" and then ">> 3" as in the C code. 61 62 subs r8, #8 63 64 vld1.16 {q0}, [r9, :64]! @ WebRtcIsacfix_kCosTab1[] 65 vld1.16 {q2}, [r0]! @ inre1Q9[] 66 vmull.s16 q8, d0, d4 @ WebRtcIsacfix_kCosTab1[k] * inre1Q9[k] 67 vld1.16 {q1}, [r10, :64]! @ WebRtcIsacfix_kSinTab1[] 68 vmull.s16 q9, d1, d5 @ WebRtcIsacfix_kCosTab1[k] * inre1Q9[k] 69 vld1.16 {q3}, [r1]! @ inre2Q9[] 70 vmlal.s16 q8, d2, d6 @ WebRtcIsacfix_kSinTab1[k] * inre2Q9[k] 71 vmlal.s16 q9, d3, d7 @ WebRtcIsacfix_kSinTab1[k] * inre2Q9[k] 72 vmull.s16 q12, d0, d6 @ WebRtcIsacfix_kCosTab1[k] * inre2Q9[k] 73 vmull.s16 q13, d1, d7 @ WebRtcIsacfix_kCosTab1[k] * inre2Q9[k] 74 vmlsl.s16 q12, d2, d4 @ WebRtcIsacfix_kSinTab1[k] * inre1Q9[k] 75 vmlsl.s16 q13, d3, d5 @ WebRtcIsacfix_kSinTab1[k] * inre1Q9[k] 76 77 vqdmulh.s32 q0, q8, q11 @ xrQ16 * factQ19 78 vqdmulh.s32 q1, q9, q11 @ xrQ16 * factQ19 79 vqdmulh.s32 q2, q12, q11 @ xrQ16 * factQ19 80 vqdmulh.s32 q3, q13, q11 @ xrQ16 * factQ19 81 82 @ Find the absolute maximum in the vectors and store them. 83 vabs.s32 q8, q0 84 vabs.s32 q9, q1 85 vabs.s32 q12, q2 86 vst1.32 {q0, q1}, [r4]! @ tmpreQ16[k] 87 vabs.s32 q13, q3 88 vmax.u32 q14, q8 @ Use u32 so we don't lose the value 0x80000000. 89 vmax.u32 q15, q12 90 vst1.32 {q2, q3}, [r5]! @ tmpimQ16[k] 91 vmax.u32 q15, q13 92 vmax.u32 q14, q9 @ Maximum for outre1Q16[]. 93 94 bgt Time2Spec_TransformAndFindMax 95 96 @ Find the maximum value in the Neon registers 97 vmax.u32 d28, d29 98 vmax.u32 d30, d31 99 vpmax.u32 d28, d28, d28 @ Both 32 bits words hold the same value tmpInIm. 100 vpmax.u32 d30, d30, d30 @ Both 32 bits words hold the same value tmpInRe. 101 vmax.s32 d30, d28, d30 @ if (yrQ16 > xrQ16) {xrQ16 = yrQ16}; 102 103 ldr r4, [sp] @ inre1Q9 104 vcls.s32 d31, d30 @ sh = WebRtcSpl_NormW32(tmpInRe); 105 ldr r5, [sp, #4] @ inre2Q9 106 vmov.i32 d30, #24 107 add r6, sp, #16 @ tmpreQ16; 108 vsub.s32 d31, d31, d30 @ sh = sh - 24; 109 add r7, sp, #(16 + FRAMESAMPLES * 2) @ tmpimQ16; 110 vdup.s32 q8, d31[0] @ sh 111 112 mov r8, #(FRAMESAMPLES / 2) @ loop counter 113 114 Time2Spec_PreFftShift: 115 subs r8, #16 116 117 vld1.32 {q0, q1}, [r6]! @ tmpreQ16[] 118 vrshl.s32 q0, q0, q8 119 vld1.32 {q2, q3}, [r6]! @ tmpreQ16[] 120 vrshl.s32 q1, q1, q8 121 vld1.32 {q10, q11}, [r7]! @ tmpimQ16[] 122 vrshl.s32 q2, q2, q8 123 vld1.32 {q12, q13}, [r7]! @ tmpimQ16[] 124 vrshl.s32 q3, q3, q8 125 vrshl.s32 q10, q10, q8 126 vrshl.s32 q11, q11, q8 127 vrshl.s32 q12, q12, q8 128 vrshl.s32 q13, q13, q8 129 130 vmovn.s32 d0, q0 131 vmovn.s32 d1, q1 132 vmovn.s32 d2, q2 133 vmovn.s32 d3, q3 134 vmovn.s32 d4, q10 135 vmovn.s32 d5, q11 136 vmovn.s32 d6, q12 137 vmovn.s32 d7, q13 138 139 vst1.16 {q0, q1}, [r4]! @ inre1Q9[] 140 vst1.16 {q2, q3}, [r5]! @ inre2Q9[] 141 142 bgt Time2Spec_PreFftShift 143 144 vmov.s32 r10, d16[0] @ Store value of sh. 145 ldr r0, [sp] @ inre1Q9 146 ldr r1, [sp, #4] @ inre2Q9 147 mov r2, #-1 148 CALL_FUNCTION WebRtcIsacfix_FftRadix16Fastest 149 150 vdup.s32 q8, r10 @ sh 151 mov r8, #(FRAMESAMPLES - 8) 152 ldr r2, [sp, #8] @ outreQ7 153 ldr r3, [sp, #12] @ outimQ7 154 add r11, r2, r8 @ &outRe1Q16[FRAMESAMPLES / 2 - 4] 155 add r12, r3, r8 @ &outim2Q16[FRAMESAMPLES / 2 - 4] 156 ldr r6, [sp] @ inre1Q9 157 ldr r7, [sp, #4] @ inre2Q9 158 add r4, r6, r8 @ &inre1Q9[FRAMESAMPLES / 2 - 4] 159 add r5, r7, r8 @ &inre2Q9[FRAMESAMPLES / 2 - 4] 160 adr r10, WebRtcIsacfix_kSinTab2 161 162 add r9, r10, #(120*2 - 8) @ &WebRtcIsacfix_kSinTab2[119 - 4] 163 164 vneg.s32 q15, q8 @ -sh 165 vmov.i32 q0, #23 166 vsub.s32 q15, q15, q0 @ -sh - 23 167 168 mov r8, #(FRAMESAMPLES / 4) @ loop counter 169 170 @ Pre-load variables. 171 vld1.16 {d2}, [r4] @ inre1Q9[FRAMESAMPLES / 2 - 4 - i] 172 vld1.16 {d3}, [r5] @ inre2Q9[FRAMESAMPLES / 2 - 4 - i] 173 vld1.16 {d0}, [r6]! @ inre1Q9 174 vld1.16 {d1}, [r7]! @ inre2Q9 175 176 Time2Spec_PostFftTransform: 177 @ By vshl, we effectively did "<< (-sh - 23)", instead of "<< (-sh)", 178 @ ">> 14" and then ">> 9" as in the C code. 179 180 vld1.16 {d6}, [r9, :64] @ kCosTab2[] 181 vneg.s16 d6, d6 182 vld1.16 {d7}, [r10, :64]! @ WebRtcIsacfix_kSinTab2[] 183 vrev64.16 q1, q1 @ Reverse samples in 2nd half of xrQ16[]. 184 vqadd.s16 d4, d0, d2 @ xrQ16 185 vqsub.s16 d5, d1, d3 @ xiQ16 186 vrev64.16 d6, d6 187 188 sub r9, #8 @ Update pointers for kCosTab2[]. 189 sub r4, #8 @ Update pointers for inre1Q9[]. 190 sub r5, #8 @ Update pointers for inr22Q9[]. 191 subs r8, #4 @ Update loop counter. 192 193 vqadd.s16 d1, d1, d3 @ yrQ16 194 vqsub.s16 d0, d2, d0 @ yiQ16 195 196 vmull.s16 q12, d6, d4 @ kCosTab2[k] * xrQ16 197 vmlsl.s16 q12, d7, d5 @ WebRtcIsacfix_kSinTab2[k] * xiQ16 198 vmull.s16 q13, d7, d4 @ WebRtcIsacfix_kSinTab2[k] * xrQ16 199 vmlal.s16 q13, d6, d5 @ kCosTab2[k] * xiQ16 200 vmull.s16 q9, d7, d1 @ WebRtcIsacfix_kSinTab2[k] * yrQ16 201 vmlal.s16 q9, d6, d0 @ kCosTab2[k] * yiQ16 202 vmull.s16 q10, d7, d0 @ WebRtcIsacfix_kSinTab2[k] * yiQ16 203 vmlsl.s16 q10, d6, d1 @ kCosTab2[k] * yrQ16 204 205 vshl.s32 q12, q12, q15 206 vshl.s32 q13, q13, q15 207 vshl.s32 q9, q9, q15 208 vshl.s32 q10, q10, q15 209 210 vneg.s32 q8, q9 211 vld1.16 {d0}, [r6]! @ inre1Q9 212 vmovn.s32 d24, q12 213 vld1.16 {d1}, [r7]! @ inre2Q9 214 vmovn.s32 d25, q13 215 vld1.16 {d2}, [r4] @ inre1Q9[FRAMESAMPLES / 2 - 4 - i] 216 vmovn.s32 d5, q10 217 vld1.16 {d3}, [r5] @ inre2Q9[FRAMESAMPLES / 2 - 4 - i] 218 vmovn.s32 d4, q8 219 vst1.16 {d24}, [r2]! @ outreQ7[k] 220 vrev64.16 q2, q2 @ Reverse the order of the samples. 221 vst1.16 {d25}, [r3]! @ outimQ7[k] 222 vst1.16 {d4}, [r11] @ outreQ7[FRAMESAMPLES / 2 - 1 - k] 223 vst1.16 {d5}, [r12] @ outimQ7[FRAMESAMPLES / 2 - 1 - k] 224 sub r11, #8 @ Update pointers for outreQ7[]. 225 sub r12, #8 @ Update pointers for outimQ7[]. 226 227 bgt Time2Spec_PostFftTransform 228 229 add sp, sp, #(16 + FRAMESAMPLES * 4) 230 pop {r4-r11,pc} 231 232 .align 8 233 @ Cosine table 1 in Q14 234 WebRtcIsacfix_kCosTab1: 235 _WebRtcIsacfix_kCosTab1: @ Label for iOS 236 .short 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315 237 .short 16294, 16270, 16244, 16214, 16182, 16147, 16110, 16069 238 .short 16026, 15980, 15931, 15880, 15826, 15769, 15709, 15647 239 .short 15582, 15515, 15444, 15371, 15296, 15218, 15137, 15053 240 .short 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295 241 .short 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380 242 .short 13255, 13128, 12998, 12867, 12733, 12597, 12458, 12318 243 .short 12176, 12031, 11885, 11736, 11585, 11433, 11278, 11121 244 .short 10963, 10803, 10641, 10477, 10311, 10143, 9974, 9803 245 .short 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377 246 .short 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859 247 .short 6664, 6467, 6270, 6071, 5872, 5671, 5469, 5266 248 .short 5063, 4859, 4653, 4447, 4240, 4033, 3825, 3616 249 .short 3406, 3196, 2986, 2775, 2563, 2351, 2139, 1926 250 .short 1713, 1499, 1285, 1072, 857, 643, 429, 214 251 .short 0, -214, -429, -643, -857, -1072, -1285, -1499 252 .short -1713, -1926, -2139, -2351, -2563, -2775, -2986, -3196 253 .short -3406, -3616, -3825, -4033, -4240, -4447, -4653, -4859 254 .short -5063, -5266, -5469, -5671, -5872, -6071, -6270, -6467 255 .short -6664, -6859, -7053, -7246, -7438, -7629, -7818, -8006 256 .short -8192, -8377, -8561, -8743, -8923, -9102, -9280, -9456 257 .short -9630, -9803, -9974, -10143, -10311, -10477, -10641, -10803 258 .short -10963, -11121, -11278, -11433, -11585, -11736, -11885, -12031 259 .short -12176, -12318, -12458, -12597, -12733, -12867, -12998, -13128 260 .short -13255, -13380, -13502, -13623, -13741, -13856, -13970, -14081 261 .short -14189, -14295, -14399, -14500, -14598, -14694, -14788, -14879 262 .short -14968, -15053, -15137, -15218, -15296, -15371, -15444, -15515 263 .short -15582, -15647, -15709, -15769, -15826, -15880, -15931, -15980 264 .short -16026, -16069, -16110, -16147, -16182, -16214, -16244, -16270 265 .short -16294, -16315, -16333, -16349, -16362, -16371, -16378, -16383 266 267 .align 8 268 @ Sine table 2 in Q14 269 WebRtcIsacfix_kSinTab2: 270 _WebRtcIsacfix_kSinTab2: @ Label for iOS 271 .short 16384, -16381, 16375, -16367, 16356, -16342, 16325, -16305 272 .short 16283, -16257, 16229, -16199, 16165, -16129, 16090, -16048 273 .short 16003, -15956, 15906, -15853, 15798, -15739, 15679, -15615 274 .short 15549, -15480, 15408, -15334, 15257, -15178, 15095, -15011 275 .short 14924, -14834, 14741, -14647, 14549, -14449, 14347, -14242 276 .short 14135, -14025, 13913, -13799, 13682, -13563, 13441, -13318 277 .short 13192, -13063, 12933, -12800, 12665, -12528, 12389, -12247 278 .short 12104, -11958, 11810, -11661, 11509, -11356, 11200, -11042 279 .short 10883, -10722, 10559, -10394, 10227, -10059, 9889, -9717 280 .short 9543, -9368, 9191, -9013, 8833, -8652, 8469, -8285 281 .short 8099, -7912, 7723, -7534, 7342, -7150, 6957, -6762 282 .short 6566, -6369, 6171, -5971, 5771, -5570, 5368, -5165 283 .short 4961, -4756, 4550, -4344, 4137, -3929, 3720, -3511 284 .short 3301, -3091, 2880, -2669, 2457, -2245, 2032, -1819 285 .short 1606, -1392, 1179, -965, 750, -536, 322, -107 286 287 @ Table kCosTab2 was removed since its data is redundant with kSinTab2. 288 289 .align 8 290 @ Sine table 1 in Q14 291 WebRtcIsacfix_kSinTab1: 292 _WebRtcIsacfix_kSinTab1: @ Label for iOS 293 .short 0, 214, 429, 643, 857, 1072, 1285, 1499 294 .short 1713, 1926, 2139, 2351, 2563, 2775, 2986, 3196 295 .short 3406, 3616, 3825, 4033, 4240, 4447, 4653, 4859 296 .short 5063, 5266, 5469, 5671, 5872, 6071, 6270, 6467 297 .short 6664, 6859, 7053, 7246, 7438, 7629, 7818, 8006 298 .short 8192, 8377, 8561, 8743, 8923, 9102, 9280, 9456 299 .short 9630, 9803, 9974, 10143, 10311, 10477, 10641, 10803 300 .short 10963, 11121, 11278, 11433, 11585, 11736, 11885, 12031 301 .short 12176, 12318, 12458, 12597, 12733, 12867, 12998, 13128 302 .short 13255, 13380, 13502, 13623, 13741, 13856, 13970, 14081 303 .short 14189, 14295, 14399, 14500, 14598, 14694, 14788, 14879 304 .short 14968, 15053, 15137, 15218, 15296, 15371, 15444, 15515 305 .short 15582, 15647, 15709, 15769, 15826, 15880, 15931, 15980 306 .short 16026, 16069, 16110, 16147, 16182, 16214, 16244, 16270 307 .short 16294, 16315, 16333, 16349, 16362, 16371, 16378, 16383 308 .short 16384, 16383, 16378, 16371, 16362, 16349, 16333, 16315 309 .short 16294, 16270, 16244, 16214, 16182, 16147, 16110, 16069 310 .short 16026, 15980, 15931, 15880, 15826, 15769, 15709, 15647 311 .short 15582, 15515, 15444, 15371, 15296, 15218, 15137, 15053 312 .short 14968, 14879, 14788, 14694, 14598, 14500, 14399, 14295 313 .short 14189, 14081, 13970, 13856, 13741, 13623, 13502, 13380 314 .short 13255, 13128, 12998, 12867, 12733, 12597, 12458, 12318 315 .short 12176, 12031, 11885, 11736, 11585, 11433, 11278, 11121 316 .short 10963, 10803, 10641, 10477, 10311, 10143, 9974, 9803 317 .short 9630, 9456, 9280, 9102, 8923, 8743, 8561, 8377 318 .short 8192, 8006, 7818, 7629, 7438, 7246, 7053, 6859 319 .short 6664, 6467, 6270, 6071, 5872, 5671, 5469, 5266 320 .short 5063, 4859, 4653, 4447, 4240, 4033, 3825, 3616 321 .short 3406, 3196, 2986, 2775, 2563, 2351, 2139, 1926 322 .short 1713, 1499, 1285, 1072, 857, 643, 429, 214 323 324 @ void WebRtcIsacfix_Spec2TimeNeon(int16_t *inreQ7, 325 @ int16_t *inimQ7, 326 @ int32_t *outre1Q16, 327 @ int32_t *outre2Q16); 328 329 DEFINE_FUNCTION WebRtcIsacfix_Spec2TimeNeon 330 .align 2 331 push {r4-r11,lr} 332 333 sub sp, sp, #16 334 str r0, [sp] @ inreQ7 335 str r1, [sp, #4] @ inimQ7 336 str r2, [sp, #8] @ outre1Q16 337 str r3, [sp, #12] @ outre2Q16 338 339 mov r8, #(FRAMESAMPLES - 16) 340 add r12, r0, r8 @ &inreQ7[FRAMESAMPLES / 2 - 8] 341 add r11, r1, r8 @ &inimQ7[FRAMESAMPLES / 2 - 8] 342 add r4, r2, r8, lsl #1 @ &outRe1Q16[FRAMESAMPLES / 2 - 8] 343 add r6, r3, r8, lsl #1 @ &outRe2Q16[FRAMESAMPLES / 2 - 8] 344 345 mov r8, #(FRAMESAMPLES / 2) @ loop counter 346 adr r10, WebRtcIsacfix_kSinTab2 347 add r9, r10, #(120*2 - 16) @ &WebRtcIsacfix_kSinTab2[119 - 8] 348 349 vpush {q4-q7} 350 351 mov r5, #-32 352 mov r7, #-16 353 vmov.u32 q6, #0 @ Initialize the maximum values for tmpInIm. 354 vmov.u32 q7, #0 @ Initialize the maximum values for tmpInRe. 355 356 TransformAndFindMax: 357 @ Use ">> 5", instead of "<< 9" and then ">> 14" as in the C code. 358 @ Bit-exact. 359 360 subs r8, #16 361 362 vld1.16 {q0}, [r9, :64] @ kCosTab2[] 363 sub r9, #16 364 vld1.16 {q2}, [r0]! @ inreQ7[] 365 vneg.s16 q0, q0 366 vld1.16 {q3}, [r1]! @ inimQ7[] 367 vrev64.16 d0, d0 368 vrev64.16 d1, d1 369 vld1.16 {q1}, [r10, :64]! @ WebRtcIsacfix_kSinTab2[] 370 vswp d0, d1 371 372 vmull.s16 q8, d2, d6 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k] 373 vmull.s16 q9, d3, d7 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k] 374 vmlal.s16 q8, d0, d4 @ kCosTab2[k] * inreQ7[k] 375 vmlal.s16 q9, d1, d5 @ kCosTab2[k] * inreQ7[k] 376 vmull.s16 q12, d0, d6 @ kCosTab2[k] * inimQ7[k] 377 vmull.s16 q13, d1, d7 @ kCosTab2[k] * inimQ7[k] 378 vmlsl.s16 q12, d2, d4 @ WebRtcIsacfix_kSinTab2[k] * inreQ7[k] 379 vmlsl.s16 q13, d3, d5 @ WebRtcIsacfix_kSinTab2[k] * inreQ7[k] 380 381 vld1.16 {q2}, [r11], r7 @ inimQ7[FRAMESAMPLES / 2 - 8 + i] 382 vld1.16 {q3}, [r12], r7 @ inreQ7[FRAMESAMPLES / 2 - 8 + i] 383 384 vrev64.16 q2, q2 @ Reverse the order of the samples 385 vrev64.16 q3, q3 @ Reverse the order of the samples 386 387 vmull.s16 q14, d2, d5 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k] 388 vmull.s16 q15, d3, d4 @ WebRtcIsacfix_kSinTab2[k] * inimQ7[k] 389 vmlsl.s16 q14, d0, d7 @ q14 -= kCosTab2[k] * inreQ7[k] 390 vmlsl.s16 q15, d1, d6 @ q15 -= kCosTab2[k] * inreQ7[k] 391 392 vmull.s16 q10, d0, d5 @ kCosTab2[k] * inimQ7[] 393 vmull.s16 q11, d1, d4 @ kCosTab2[k] * inimQ7[] 394 vmlal.s16 q10, d2, d7 @ q10 += WebRtcIsacfix_kSinTab2[k] * inreQ7[] 395 vmlal.s16 q11, d3, d6 @ q11 += WebRtcIsacfix_kSinTab2[k] * inreQ7[] 396 397 vshr.s32 q8, q8, #5 @ xrQ16 398 vshr.s32 q9, q9, #5 @ xrQ16 399 vshr.s32 q12, q12, #5 @ xiQ16 400 vshr.s32 q13, q13, #5 @ xiQ16 401 vshr.s32 q14, q14, #5 @ yiQ16 402 vshr.s32 q15, q15, #5 @ yiQ16 403 404 vneg.s32 q10, q10 405 vneg.s32 q11, q11 406 407 @ xrQ16 - yiQ16 408 vsub.s32 q0, q8, q14 409 vsub.s32 q1, q9, q15 410 411 vshr.s32 q10, q10, #5 @ yrQ16 412 vshr.s32 q11, q11, #5 @ yrQ16 413 414 @ xrQ16 + yiQ16 415 vadd.s32 q3, q8, q14 416 vadd.s32 q2, q9, q15 417 418 @ yrQ16 + xiQ16 419 vadd.s32 q4, q10, q12 420 vadd.s32 q5, q11, q13 421 422 @ yrQ16 - xiQ16 423 vsub.s32 q8, q11, q13 424 vsub.s32 q9, q10, q12 425 426 @ Reverse the order of the samples 427 vrev64.32 q2, q2 428 vrev64.32 q3, q3 429 vrev64.32 q8, q8 430 vrev64.32 q9, q9 431 vswp d4, d5 432 vswp d6, d7 433 434 vst1.32 {q0, q1}, [r2]! @ outre1Q16[k] 435 vswp d16, d17 436 vswp d18, d19 437 vst1.32 {q2, q3}, [r4], r5 @ outre1Q16[FRAMESAMPLES / 2 - 1 - k] 438 439 @ Find the absolute maximum in the vectors and store them in q6 and q7. 440 vabs.s32 q10, q0 441 vabs.s32 q14, q4 442 vabs.s32 q11, q1 443 vabs.s32 q15, q5 444 vabs.s32 q12, q2 445 vmax.u32 q6, q10 @ Use u32 so we don't lose the value 0x80000000. 446 vmax.u32 q7, q14 @ Maximum for outre2Q16[]. 447 vabs.s32 q0, q8 448 vmax.u32 q6, q11 @ Maximum for outre1Q16[]. 449 vmax.u32 q7, q15 450 vabs.s32 q13, q3 451 vmax.u32 q6, q12 452 vmax.u32 q7, q0 453 vabs.s32 q1, q9 454 vst1.32 {q4, q5}, [r3]! @ outre2Q16[k] 455 vst1.32 {q8, q9}, [r6], r5 @ outre2Q16[FRAMESAMPLES / 2 - 1 - k] 456 vmax.u32 q6, q13 457 vmax.u32 q7, q1 458 459 bgt TransformAndFindMax 460 461 adr r10, WebRtcIsacfix_kSinTab1 462 #if defined(__APPLE__) 463 mov r2, #:lower16:(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1) 464 #else 465 mov r2, #(WebRtcIsacfix_kSinTab1 - WebRtcIsacfix_kCosTab1) 466 #endif 467 468 sub r11, r10, r2 @ WebRtcIsacfix_kCosTab1 469 470 @ Find the maximum value in the Neon registers 471 vmax.u32 d12, d13 472 vmax.u32 d14, d15 473 vpmax.u32 d12, d12, d12 @ Both 32 bits words hold the same value tmpInIm. 474 vpmax.u32 d14, d14, d14 @ Both 32 bits words hold the same value tmpInRe. 475 vmax.s32 d0, d12, d14 @ if (tmpInIm>tmpInRe) tmpInRe = tmpInIm; 476 477 vpop {q4-q7} 478 479 ldr r4, [sp] @ inreQ7 480 vcls.s32 d1, d0 @ sh = WebRtcSpl_NormW32(tmpInRe); 481 ldr r5, [sp, #4] @ inimQ7 482 vmov.i32 d0, #24 @ sh = sh-24; 483 ldr r6, [sp, #8] @ outre1Q16 484 vsub.s32 d1, d1, d0 485 ldr r7, [sp, #12] @ outre2Q16 486 vdup.s32 q8, d1[0] @ sh 487 488 mov r8, #(FRAMESAMPLES / 2) 489 490 PreFftShift: 491 subs r8, #16 492 vld1.32 {q0, q1}, [r6]! @ outre1Q16[] 493 vld1.32 {q2, q3}, [r6]! @ outre1Q16[] 494 vrshl.s32 q0, q0, q8 495 vrshl.s32 q1, q1, q8 496 vrshl.s32 q2, q2, q8 497 vrshl.s32 q3, q3, q8 498 vld1.32 {q10, q11}, [r7]! @ outre2Q16[] 499 vld1.32 {q12, q13}, [r7]! @ outre2Q16[] 500 vrshl.s32 q10, q10, q8 501 vrshl.s32 q11, q11, q8 502 vrshl.s32 q12, q12, q8 503 vrshl.s32 q13, q13, q8 504 505 vmovn.s32 d0, q0 506 vmovn.s32 d1, q1 507 vmovn.s32 d2, q2 508 vmovn.s32 d3, q3 509 vmovn.s32 d4, q10 510 vmovn.s32 d5, q11 511 vmovn.s32 d6, q12 512 vmovn.s32 d7, q13 513 514 vst1.16 {q0, q1}, [r4]! @ inreQ7[] 515 vst1.16 {q2, q3}, [r5]! @ inimQ7[] 516 517 bgt PreFftShift 518 519 vmov.s32 r8, d16[0] @ Store value of sh. 520 ldr r0, [sp] @ inreQ7 521 ldr r1, [sp, #4] @ inimQ7 522 mov r2, #1 523 CALL_FUNCTION WebRtcIsacfix_FftRadix16Fastest 524 525 vdup.s32 q8, r8 @ sh 526 mov r9, r11 @ WebRtcIsacfix_kCosTab1 527 ldr r4, [sp] @ inreQ7 528 ldr r5, [sp, #4] @ inimQ7 529 ldr r6, [sp, #8] @ outre1Q16 530 ldr r7, [sp, #12] @ outre2Q16 531 mov r8, #(FRAMESAMPLES / 2) 532 vneg.s32 q15, q8 @ -sh 533 movw r0, #273 534 lsl r0, #15 @ Together with vqdmulh, net effect is ">> 16". 535 vdup.s32 q14, r0 536 537 PostFftShiftDivide: 538 subs r8, #16 539 540 vld1.16 {q0, q1}, [r4]! @ inreQ7 541 vmovl.s16 q10, d0 542 vmovl.s16 q11, d1 543 vld1.16 {q2, q3}, [r5]! @ inimQ7 544 vmovl.s16 q8, d2 545 vmovl.s16 q9, d3 546 547 vshl.s32 q10, q10, q15 548 vshl.s32 q11, q11, q15 549 vshl.s32 q8, q8, q15 550 vshl.s32 q9, q9, q15 551 552 vqdmulh.s32 q10, q10, q14 553 vqdmulh.s32 q11, q11, q14 554 vqdmulh.s32 q8, q8, q14 555 vqdmulh.s32 q9, q9, q14 556 557 vmovl.s16 q0, d4 558 vmovl.s16 q1, d5 559 vmovl.s16 q2, d6 560 vmovl.s16 q3, d7 561 562 vshl.s32 q0, q0, q15 563 vshl.s32 q1, q1, q15 564 vshl.s32 q2, q2, q15 565 vshl.s32 q3, q3, q15 566 567 @ WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k]) 568 vqdmulh.s32 q0, q0, q14 569 vqdmulh.s32 q1, q1, q14 570 vst1.32 {q10, q11}, [r6]! @ outre1Q16[] 571 vqdmulh.s32 q2, q2, q14 572 vqdmulh.s32 q3, q3, q14 573 vst1.32 {q8, q9}, [r6]! @ outre1Q16[] 574 vst1.32 {q0, q1}, [r7]! @ outre2Q16[] 575 vst1.32 {q2, q3}, [r7]! @ outre2Q16[] 576 577 bgt PostFftShiftDivide 578 579 mov r8, #(FRAMESAMPLES / 2) 580 ldr r2, [sp, #8] @ outre1Q16 581 ldr r3, [sp, #12] @ outre2Q16 582 movw r0, #31727 583 lsl r0, #16 @ With vqdmulh and vrshrn, net effect is ">> 25". 584 585 DemodulateAndSeparate: 586 subs r8, #8 587 588 vld1.16 {q0}, [r9, :64]! @ WebRtcIsacfix_kCosTab1[] 589 vmovl.s16 q10, d0 @ WebRtcIsacfix_kCosTab1[] 590 vld1.16 {q1}, [r10, :64]! @ WebRtcIsacfix_kSinTab1[] 591 vmovl.s16 q11, d1 @ WebRtcIsacfix_kCosTab1[] 592 vld1.32 {q2, q3}, [r2] @ outre1Q16 593 vmovl.s16 q12, d2 @ WebRtcIsacfix_kSinTab1[] 594 vld1.32 {q14, q15}, [r3] @ outre2Q16 595 vmovl.s16 q13, d3 @ WebRtcIsacfix_kSinTab1[] 596 597 vmull.s32 q0, d20, d4 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k] 598 vmull.s32 q1, d21, d5 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k] 599 vmull.s32 q8, d22, d6 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k] 600 vmull.s32 q9, d23, d7 @ WebRtcIsacfix_kCosTab1[k] * outre1Q16[k] 601 602 vmlsl.s32 q0, d24, d28 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k] 603 vmlsl.s32 q1, d25, d29 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k] 604 vmlsl.s32 q8, d26, d30 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k] 605 vmlsl.s32 q9, d27, d31 @ += WebRtcIsacfix_kSinTab1[k] * outre2Q16[k] 606 607 vrshrn.s64 d0, q0, #10 @ xrQ16 608 vrshrn.s64 d1, q1, #10 @ xrQ16 609 vrshrn.s64 d2, q8, #10 @ xrQ16 610 vrshrn.s64 d3, q9, #10 @ xrQ16 611 612 vmull.s32 q8, d20, d28 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k] 613 vmull.s32 q9, d21, d29 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k] 614 vmull.s32 q14, d22, d30 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k] 615 vmull.s32 q15, d23, d31 @ WebRtcIsacfix_kCosTab1[k] * outre2Q16[k] 616 617 vmlal.s32 q8, d24, d4 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k] 618 vmlal.s32 q9, d25, d5 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k] 619 vmlal.s32 q14, d26, d6 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k] 620 vmlal.s32 q15, d27, d7 @ += WebRtcIsacfix_kSinTab1[k] * outre1Q16[k] 621 622 vdup.s32 q11, r0 @ generic -> Neon doesn't cost extra cycles. 623 624 vrshrn.s64 d24, q8, #10 @ xiQ16 625 vrshrn.s64 d25, q9, #10 @ xiQ16 626 vqdmulh.s32 q0, q0, q11 627 vrshrn.s64 d26, q14, #10 @ xiQ16 628 vrshrn.s64 d27, q15, #10 @ xiQ16 629 630 @ WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16) 631 @ WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16) 632 633 vqdmulh.s32 q1, q1, q11 634 vqdmulh.s32 q2, q12, q11 635 vqdmulh.s32 q3, q13, q11 636 637 vst1.16 {q0, q1}, [r2]! @ outre1Q16[] 638 vst1.16 {q2, q3}, [r3]! @ outre2Q16[] 639 640 bgt DemodulateAndSeparate 641 642 add sp, sp, #16 643 pop {r4-r11,pc} 644