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 11 12#include "webrtc/common_audio/signal_processing/complex_fft_tables.h" 13#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 14 15#define CFFTSFT 14 16#define CFFTRND 1 17#define CFFTRND2 16384 18 19#define CIFFTSFT 14 20#define CIFFTRND 1 21 22int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode) { 23 int i = 0; 24 int l = 0; 25 int k = 0; 26 int istep = 0; 27 int n = 0; 28 int m = 0; 29 int32_t wr = 0, wi = 0; 30 int32_t tmp1 = 0; 31 int32_t tmp2 = 0; 32 int32_t tmp3 = 0; 33 int32_t tmp4 = 0; 34 int32_t tmp5 = 0; 35 int32_t tmp6 = 0; 36 int32_t tmp = 0; 37 int16_t* ptr_j = NULL; 38 int16_t* ptr_i = NULL; 39 40 n = 1 << stages; 41 if (n > 1024) { 42 return -1; 43 } 44 45 __asm __volatile ( 46 ".set push \n\t" 47 ".set noreorder \n\t" 48 49 "addiu %[k], $zero, 10 \n\t" 50 "addiu %[l], $zero, 1 \n\t" 51 "3: \n\t" 52 "sll %[istep], %[l], 1 \n\t" 53 "move %[m], $zero \n\t" 54 "sll %[tmp], %[l], 2 \n\t" 55 "move %[i], $zero \n\t" 56 "2: \n\t" 57#if defined(MIPS_DSP_R1_LE) 58 "sllv %[tmp3], %[m], %[k] \n\t" 59 "addiu %[tmp2], %[tmp3], 512 \n\t" 60 "addiu %[m], %[m], 1 \n\t" 61 "lhx %[wi], %[tmp3](%[kSinTable1024]) \n\t" 62 "lhx %[wr], %[tmp2](%[kSinTable1024]) \n\t" 63#else // #if defined(MIPS_DSP_R1_LE) 64 "sllv %[tmp3], %[m], %[k] \n\t" 65 "addu %[ptr_j], %[tmp3], %[kSinTable1024] \n\t" 66 "addiu %[ptr_i], %[ptr_j], 512 \n\t" 67 "addiu %[m], %[m], 1 \n\t" 68 "lh %[wi], 0(%[ptr_j]) \n\t" 69 "lh %[wr], 0(%[ptr_i]) \n\t" 70#endif // #if defined(MIPS_DSP_R1_LE) 71 "1: \n\t" 72 "sll %[tmp1], %[i], 2 \n\t" 73 "addu %[ptr_i], %[frfi], %[tmp1] \n\t" 74 "addu %[ptr_j], %[ptr_i], %[tmp] \n\t" 75 "lh %[tmp6], 0(%[ptr_i]) \n\t" 76 "lh %[tmp5], 2(%[ptr_i]) \n\t" 77 "lh %[tmp3], 0(%[ptr_j]) \n\t" 78 "lh %[tmp4], 2(%[ptr_j]) \n\t" 79 "addu %[i], %[i], %[istep] \n\t" 80#if defined(MIPS_DSP_R2_LE) 81 "mult %[wr], %[tmp3] \n\t" 82 "madd %[wi], %[tmp4] \n\t" 83 "mult $ac1, %[wr], %[tmp4] \n\t" 84 "msub $ac1, %[wi], %[tmp3] \n\t" 85 "mflo %[tmp1] \n\t" 86 "mflo %[tmp2], $ac1 \n\t" 87 "sll %[tmp6], %[tmp6], 14 \n\t" 88 "sll %[tmp5], %[tmp5], 14 \n\t" 89 "shra_r.w %[tmp1], %[tmp1], 1 \n\t" 90 "shra_r.w %[tmp2], %[tmp2], 1 \n\t" 91 "subu %[tmp4], %[tmp6], %[tmp1] \n\t" 92 "addu %[tmp1], %[tmp6], %[tmp1] \n\t" 93 "addu %[tmp6], %[tmp5], %[tmp2] \n\t" 94 "subu %[tmp5], %[tmp5], %[tmp2] \n\t" 95 "shra_r.w %[tmp1], %[tmp1], 15 \n\t" 96 "shra_r.w %[tmp6], %[tmp6], 15 \n\t" 97 "shra_r.w %[tmp4], %[tmp4], 15 \n\t" 98 "shra_r.w %[tmp5], %[tmp5], 15 \n\t" 99#else // #if defined(MIPS_DSP_R2_LE) 100 "mul %[tmp2], %[wr], %[tmp4] \n\t" 101 "mul %[tmp1], %[wr], %[tmp3] \n\t" 102 "mul %[tmp4], %[wi], %[tmp4] \n\t" 103 "mul %[tmp3], %[wi], %[tmp3] \n\t" 104 "sll %[tmp6], %[tmp6], 14 \n\t" 105 "sll %[tmp5], %[tmp5], 14 \n\t" 106 "addiu %[tmp6], %[tmp6], 16384 \n\t" 107 "addiu %[tmp5], %[tmp5], 16384 \n\t" 108 "addu %[tmp1], %[tmp1], %[tmp4] \n\t" 109 "subu %[tmp2], %[tmp2], %[tmp3] \n\t" 110 "addiu %[tmp1], %[tmp1], 1 \n\t" 111 "addiu %[tmp2], %[tmp2], 1 \n\t" 112 "sra %[tmp1], %[tmp1], 1 \n\t" 113 "sra %[tmp2], %[tmp2], 1 \n\t" 114 "subu %[tmp4], %[tmp6], %[tmp1] \n\t" 115 "addu %[tmp1], %[tmp6], %[tmp1] \n\t" 116 "addu %[tmp6], %[tmp5], %[tmp2] \n\t" 117 "subu %[tmp5], %[tmp5], %[tmp2] \n\t" 118 "sra %[tmp4], %[tmp4], 15 \n\t" 119 "sra %[tmp1], %[tmp1], 15 \n\t" 120 "sra %[tmp6], %[tmp6], 15 \n\t" 121 "sra %[tmp5], %[tmp5], 15 \n\t" 122#endif // #if defined(MIPS_DSP_R2_LE) 123 "sh %[tmp1], 0(%[ptr_i]) \n\t" 124 "sh %[tmp6], 2(%[ptr_i]) \n\t" 125 "sh %[tmp4], 0(%[ptr_j]) \n\t" 126 "blt %[i], %[n], 1b \n\t" 127 " sh %[tmp5], 2(%[ptr_j]) \n\t" 128 "blt %[m], %[l], 2b \n\t" 129 " addu %[i], $zero, %[m] \n\t" 130 "move %[l], %[istep] \n\t" 131 "blt %[l], %[n], 3b \n\t" 132 " addiu %[k], %[k], -1 \n\t" 133 134 ".set pop \n\t" 135 136 : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), 137 [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6), 138 [ptr_i] "=&r" (ptr_i), [i] "=&r" (i), [wi] "=&r" (wi), [wr] "=&r" (wr), 139 [m] "=&r" (m), [istep] "=&r" (istep), [l] "=&r" (l), [k] "=&r" (k), 140 [ptr_j] "=&r" (ptr_j), [tmp] "=&r" (tmp) 141 : [n] "r" (n), [frfi] "r" (frfi), [kSinTable1024] "r" (kSinTable1024) 142 : "hi", "lo", "memory" 143#if defined(MIPS_DSP_R2_LE) 144 , "$ac1hi", "$ac1lo" 145#endif // #if defined(MIPS_DSP_R2_LE) 146 ); 147 148 return 0; 149} 150 151int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode) { 152 int i = 0, l = 0, k = 0; 153 int istep = 0, n = 0, m = 0; 154 int scale = 0, shift = 0; 155 int32_t wr = 0, wi = 0; 156 int32_t tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0; 157 int32_t tmp5 = 0, tmp6 = 0, tmp = 0, tempMax = 0, round2 = 0; 158 int16_t* ptr_j = NULL; 159 int16_t* ptr_i = NULL; 160 161 n = 1 << stages; 162 if (n > 1024) { 163 return -1; 164 } 165 166 __asm __volatile ( 167 ".set push \n\t" 168 ".set noreorder \n\t" 169 170 "addiu %[k], $zero, 10 \n\t" 171 "addiu %[l], $zero, 1 \n\t" 172 "move %[scale], $zero \n\t" 173 "3: \n\t" 174 "addiu %[shift], $zero, 14 \n\t" 175 "addiu %[round2], $zero, 8192 \n\t" 176 "move %[ptr_i], %[frfi] \n\t" 177 "move %[tempMax], $zero \n\t" 178 "addu %[i], %[n], %[n] \n\t" 179 "5: \n\t" 180 "lh %[tmp1], 0(%[ptr_i]) \n\t" 181 "lh %[tmp2], 2(%[ptr_i]) \n\t" 182 "lh %[tmp3], 4(%[ptr_i]) \n\t" 183 "lh %[tmp4], 6(%[ptr_i]) \n\t" 184#if defined(MIPS_DSP_R1_LE) 185 "absq_s.w %[tmp1], %[tmp1] \n\t" 186 "absq_s.w %[tmp2], %[tmp2] \n\t" 187 "absq_s.w %[tmp3], %[tmp3] \n\t" 188 "absq_s.w %[tmp4], %[tmp4] \n\t" 189#else // #if defined(MIPS_DSP_R1_LE) 190 "slt %[tmp5], %[tmp1], $zero \n\t" 191 "subu %[tmp6], $zero, %[tmp1] \n\t" 192 "movn %[tmp1], %[tmp6], %[tmp5] \n\t" 193 "slt %[tmp5], %[tmp2], $zero \n\t" 194 "subu %[tmp6], $zero, %[tmp2] \n\t" 195 "movn %[tmp2], %[tmp6], %[tmp5] \n\t" 196 "slt %[tmp5], %[tmp3], $zero \n\t" 197 "subu %[tmp6], $zero, %[tmp3] \n\t" 198 "movn %[tmp3], %[tmp6], %[tmp5] \n\t" 199 "slt %[tmp5], %[tmp4], $zero \n\t" 200 "subu %[tmp6], $zero, %[tmp4] \n\t" 201 "movn %[tmp4], %[tmp6], %[tmp5] \n\t" 202#endif // #if defined(MIPS_DSP_R1_LE) 203 "slt %[tmp5], %[tempMax], %[tmp1] \n\t" 204 "movn %[tempMax], %[tmp1], %[tmp5] \n\t" 205 "addiu %[i], %[i], -4 \n\t" 206 "slt %[tmp5], %[tempMax], %[tmp2] \n\t" 207 "movn %[tempMax], %[tmp2], %[tmp5] \n\t" 208 "slt %[tmp5], %[tempMax], %[tmp3] \n\t" 209 "movn %[tempMax], %[tmp3], %[tmp5] \n\t" 210 "slt %[tmp5], %[tempMax], %[tmp4] \n\t" 211 "movn %[tempMax], %[tmp4], %[tmp5] \n\t" 212 "bgtz %[i], 5b \n\t" 213 " addiu %[ptr_i], %[ptr_i], 8 \n\t" 214 "addiu %[tmp1], $zero, 13573 \n\t" 215 "addiu %[tmp2], $zero, 27146 \n\t" 216#if !defined(MIPS32_R2_LE) 217 "sll %[tempMax], %[tempMax], 16 \n\t" 218 "sra %[tempMax], %[tempMax], 16 \n\t" 219#else // #if !defined(MIPS32_R2_LE) 220 "seh %[tempMax] \n\t" 221#endif // #if !defined(MIPS32_R2_LE) 222 "slt %[tmp1], %[tmp1], %[tempMax] \n\t" 223 "slt %[tmp2], %[tmp2], %[tempMax] \n\t" 224 "addu %[tmp1], %[tmp1], %[tmp2] \n\t" 225 "addu %[shift], %[shift], %[tmp1] \n\t" 226 "addu %[scale], %[scale], %[tmp1] \n\t" 227 "sllv %[round2], %[round2], %[tmp1] \n\t" 228 "sll %[istep], %[l], 1 \n\t" 229 "move %[m], $zero \n\t" 230 "sll %[tmp], %[l], 2 \n\t" 231 "2: \n\t" 232#if defined(MIPS_DSP_R1_LE) 233 "sllv %[tmp3], %[m], %[k] \n\t" 234 "addiu %[tmp2], %[tmp3], 512 \n\t" 235 "addiu %[m], %[m], 1 \n\t" 236 "lhx %[wi], %[tmp3](%[kSinTable1024]) \n\t" 237 "lhx %[wr], %[tmp2](%[kSinTable1024]) \n\t" 238#else // #if defined(MIPS_DSP_R1_LE) 239 "sllv %[tmp3], %[m], %[k] \n\t" 240 "addu %[ptr_j], %[tmp3], %[kSinTable1024] \n\t" 241 "addiu %[ptr_i], %[ptr_j], 512 \n\t" 242 "addiu %[m], %[m], 1 \n\t" 243 "lh %[wi], 0(%[ptr_j]) \n\t" 244 "lh %[wr], 0(%[ptr_i]) \n\t" 245#endif // #if defined(MIPS_DSP_R1_LE) 246 "1: \n\t" 247 "sll %[tmp1], %[i], 2 \n\t" 248 "addu %[ptr_i], %[frfi], %[tmp1] \n\t" 249 "addu %[ptr_j], %[ptr_i], %[tmp] \n\t" 250 "lh %[tmp3], 0(%[ptr_j]) \n\t" 251 "lh %[tmp4], 2(%[ptr_j]) \n\t" 252 "lh %[tmp6], 0(%[ptr_i]) \n\t" 253 "lh %[tmp5], 2(%[ptr_i]) \n\t" 254 "addu %[i], %[i], %[istep] \n\t" 255#if defined(MIPS_DSP_R2_LE) 256 "mult %[wr], %[tmp3] \n\t" 257 "msub %[wi], %[tmp4] \n\t" 258 "mult $ac1, %[wr], %[tmp4] \n\t" 259 "madd $ac1, %[wi], %[tmp3] \n\t" 260 "mflo %[tmp1] \n\t" 261 "mflo %[tmp2], $ac1 \n\t" 262 "sll %[tmp6], %[tmp6], 14 \n\t" 263 "sll %[tmp5], %[tmp5], 14 \n\t" 264 "shra_r.w %[tmp1], %[tmp1], 1 \n\t" 265 "shra_r.w %[tmp2], %[tmp2], 1 \n\t" 266 "addu %[tmp6], %[tmp6], %[round2] \n\t" 267 "addu %[tmp5], %[tmp5], %[round2] \n\t" 268 "subu %[tmp4], %[tmp6], %[tmp1] \n\t" 269 "addu %[tmp1], %[tmp6], %[tmp1] \n\t" 270 "addu %[tmp6], %[tmp5], %[tmp2] \n\t" 271 "subu %[tmp5], %[tmp5], %[tmp2] \n\t" 272 "srav %[tmp4], %[tmp4], %[shift] \n\t" 273 "srav %[tmp1], %[tmp1], %[shift] \n\t" 274 "srav %[tmp6], %[tmp6], %[shift] \n\t" 275 "srav %[tmp5], %[tmp5], %[shift] \n\t" 276#else // #if defined(MIPS_DSP_R2_LE) 277 "mul %[tmp1], %[wr], %[tmp3] \n\t" 278 "mul %[tmp2], %[wr], %[tmp4] \n\t" 279 "mul %[tmp4], %[wi], %[tmp4] \n\t" 280 "mul %[tmp3], %[wi], %[tmp3] \n\t" 281 "sll %[tmp6], %[tmp6], 14 \n\t" 282 "sll %[tmp5], %[tmp5], 14 \n\t" 283 "sub %[tmp1], %[tmp1], %[tmp4] \n\t" 284 "addu %[tmp2], %[tmp2], %[tmp3] \n\t" 285 "addiu %[tmp1], %[tmp1], 1 \n\t" 286 "addiu %[tmp2], %[tmp2], 1 \n\t" 287 "sra %[tmp2], %[tmp2], 1 \n\t" 288 "sra %[tmp1], %[tmp1], 1 \n\t" 289 "addu %[tmp6], %[tmp6], %[round2] \n\t" 290 "addu %[tmp5], %[tmp5], %[round2] \n\t" 291 "subu %[tmp4], %[tmp6], %[tmp1] \n\t" 292 "addu %[tmp1], %[tmp6], %[tmp1] \n\t" 293 "addu %[tmp6], %[tmp5], %[tmp2] \n\t" 294 "subu %[tmp5], %[tmp5], %[tmp2] \n\t" 295 "sra %[tmp4], %[tmp4], %[shift] \n\t" 296 "sra %[tmp1], %[tmp1], %[shift] \n\t" 297 "sra %[tmp6], %[tmp6], %[shift] \n\t" 298 "sra %[tmp5], %[tmp5], %[shift] \n\t" 299#endif // #if defined(MIPS_DSP_R2_LE) 300 "sh %[tmp1], 0(%[ptr_i]) \n\t" 301 "sh %[tmp6], 2(%[ptr_i]) \n\t" 302 "sh %[tmp4], 0(%[ptr_j]) \n\t" 303 "blt %[i], %[n], 1b \n\t" 304 " sh %[tmp5], 2(%[ptr_j]) \n\t" 305 "blt %[m], %[l], 2b \n\t" 306 " addu %[i], $zero, %[m] \n\t" 307 "move %[l], %[istep] \n\t" 308 "blt %[l], %[n], 3b \n\t" 309 " addiu %[k], %[k], -1 \n\t" 310 311 ".set pop \n\t" 312 313 : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), 314 [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6), 315 [ptr_i] "=&r" (ptr_i), [i] "=&r" (i), [m] "=&r" (m), [tmp] "=&r" (tmp), 316 [istep] "=&r" (istep), [wi] "=&r" (wi), [wr] "=&r" (wr), [l] "=&r" (l), 317 [k] "=&r" (k), [round2] "=&r" (round2), [ptr_j] "=&r" (ptr_j), 318 [shift] "=&r" (shift), [scale] "=&r" (scale), [tempMax] "=&r" (tempMax) 319 : [n] "r" (n), [frfi] "r" (frfi), [kSinTable1024] "r" (kSinTable1024) 320 : "hi", "lo", "memory" 321#if defined(MIPS_DSP_R2_LE) 322 , "$ac1hi", "$ac1lo" 323#endif // #if defined(MIPS_DSP_R2_LE) 324 ); 325 326 return scale; 327 328} 329