/* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "common_audio/signal_processing/complex_fft_tables.h" #include "common_audio/signal_processing/include/signal_processing_library.h" #define CFFTSFT 14 #define CFFTRND 1 #define CFFTRND2 16384 #define CIFFTSFT 14 #define CIFFTRND 1 int WebRtcSpl_ComplexFFT(int16_t frfi[], int stages, int mode) { int i = 0; int l = 0; int k = 0; int istep = 0; int n = 0; int m = 0; int32_t wr = 0, wi = 0; int32_t tmp1 = 0; int32_t tmp2 = 0; int32_t tmp3 = 0; int32_t tmp4 = 0; int32_t tmp5 = 0; int32_t tmp6 = 0; int32_t tmp = 0; int16_t* ptr_j = NULL; int16_t* ptr_i = NULL; n = 1 << stages; if (n > 1024) { return -1; } __asm __volatile ( ".set push \n\t" ".set noreorder \n\t" "addiu %[k], $zero, 10 \n\t" "addiu %[l], $zero, 1 \n\t" "3: \n\t" "sll %[istep], %[l], 1 \n\t" "move %[m], $zero \n\t" "sll %[tmp], %[l], 2 \n\t" "move %[i], $zero \n\t" "2: \n\t" #if defined(MIPS_DSP_R1_LE) "sllv %[tmp3], %[m], %[k] \n\t" "addiu %[tmp2], %[tmp3], 512 \n\t" "addiu %[m], %[m], 1 \n\t" "lhx %[wi], %[tmp3](%[kSinTable1024]) \n\t" "lhx %[wr], %[tmp2](%[kSinTable1024]) \n\t" #else // #if defined(MIPS_DSP_R1_LE) "sllv %[tmp3], %[m], %[k] \n\t" "addu %[ptr_j], %[tmp3], %[kSinTable1024] \n\t" "addiu %[ptr_i], %[ptr_j], 512 \n\t" "addiu %[m], %[m], 1 \n\t" "lh %[wi], 0(%[ptr_j]) \n\t" "lh %[wr], 0(%[ptr_i]) \n\t" #endif // #if defined(MIPS_DSP_R1_LE) "1: \n\t" "sll %[tmp1], %[i], 2 \n\t" "addu %[ptr_i], %[frfi], %[tmp1] \n\t" "addu %[ptr_j], %[ptr_i], %[tmp] \n\t" "lh %[tmp6], 0(%[ptr_i]) \n\t" "lh %[tmp5], 2(%[ptr_i]) \n\t" "lh %[tmp3], 0(%[ptr_j]) \n\t" "lh %[tmp4], 2(%[ptr_j]) \n\t" "addu %[i], %[i], %[istep] \n\t" #if defined(MIPS_DSP_R2_LE) "mult %[wr], %[tmp3] \n\t" "madd %[wi], %[tmp4] \n\t" "mult $ac1, %[wr], %[tmp4] \n\t" "msub $ac1, %[wi], %[tmp3] \n\t" "mflo %[tmp1] \n\t" "mflo %[tmp2], $ac1 \n\t" "sll %[tmp6], %[tmp6], 14 \n\t" "sll %[tmp5], %[tmp5], 14 \n\t" "shra_r.w %[tmp1], %[tmp1], 1 \n\t" "shra_r.w %[tmp2], %[tmp2], 1 \n\t" "subu %[tmp4], %[tmp6], %[tmp1] \n\t" "addu %[tmp1], %[tmp6], %[tmp1] \n\t" "addu %[tmp6], %[tmp5], %[tmp2] \n\t" "subu %[tmp5], %[tmp5], %[tmp2] \n\t" "shra_r.w %[tmp1], %[tmp1], 15 \n\t" "shra_r.w %[tmp6], %[tmp6], 15 \n\t" "shra_r.w %[tmp4], %[tmp4], 15 \n\t" "shra_r.w %[tmp5], %[tmp5], 15 \n\t" #else // #if defined(MIPS_DSP_R2_LE) "mul %[tmp2], %[wr], %[tmp4] \n\t" "mul %[tmp1], %[wr], %[tmp3] \n\t" "mul %[tmp4], %[wi], %[tmp4] \n\t" "mul %[tmp3], %[wi], %[tmp3] \n\t" "sll %[tmp6], %[tmp6], 14 \n\t" "sll %[tmp5], %[tmp5], 14 \n\t" "addiu %[tmp6], %[tmp6], 16384 \n\t" "addiu %[tmp5], %[tmp5], 16384 \n\t" "addu %[tmp1], %[tmp1], %[tmp4] \n\t" "subu %[tmp2], %[tmp2], %[tmp3] \n\t" "addiu %[tmp1], %[tmp1], 1 \n\t" "addiu %[tmp2], %[tmp2], 1 \n\t" "sra %[tmp1], %[tmp1], 1 \n\t" "sra %[tmp2], %[tmp2], 1 \n\t" "subu %[tmp4], %[tmp6], %[tmp1] \n\t" "addu %[tmp1], %[tmp6], %[tmp1] \n\t" "addu %[tmp6], %[tmp5], %[tmp2] \n\t" "subu %[tmp5], %[tmp5], %[tmp2] \n\t" "sra %[tmp4], %[tmp4], 15 \n\t" "sra %[tmp1], %[tmp1], 15 \n\t" "sra %[tmp6], %[tmp6], 15 \n\t" "sra %[tmp5], %[tmp5], 15 \n\t" #endif // #if defined(MIPS_DSP_R2_LE) "sh %[tmp1], 0(%[ptr_i]) \n\t" "sh %[tmp6], 2(%[ptr_i]) \n\t" "sh %[tmp4], 0(%[ptr_j]) \n\t" "blt %[i], %[n], 1b \n\t" " sh %[tmp5], 2(%[ptr_j]) \n\t" "blt %[m], %[l], 2b \n\t" " addu %[i], $zero, %[m] \n\t" "move %[l], %[istep] \n\t" "blt %[l], %[n], 3b \n\t" " addiu %[k], %[k], -1 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6), [ptr_i] "=&r" (ptr_i), [i] "=&r" (i), [wi] "=&r" (wi), [wr] "=&r" (wr), [m] "=&r" (m), [istep] "=&r" (istep), [l] "=&r" (l), [k] "=&r" (k), [ptr_j] "=&r" (ptr_j), [tmp] "=&r" (tmp) : [n] "r" (n), [frfi] "r" (frfi), [kSinTable1024] "r" (kSinTable1024) : "hi", "lo", "memory" #if defined(MIPS_DSP_R2_LE) , "$ac1hi", "$ac1lo" #endif // #if defined(MIPS_DSP_R2_LE) ); return 0; } int WebRtcSpl_ComplexIFFT(int16_t frfi[], int stages, int mode) { int i = 0, l = 0, k = 0; int istep = 0, n = 0, m = 0; int scale = 0, shift = 0; int32_t wr = 0, wi = 0; int32_t tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0; int32_t tmp5 = 0, tmp6 = 0, tmp = 0, tempMax = 0, round2 = 0; int16_t* ptr_j = NULL; int16_t* ptr_i = NULL; n = 1 << stages; if (n > 1024) { return -1; } __asm __volatile ( ".set push \n\t" ".set noreorder \n\t" "addiu %[k], $zero, 10 \n\t" "addiu %[l], $zero, 1 \n\t" "move %[scale], $zero \n\t" "3: \n\t" "addiu %[shift], $zero, 14 \n\t" "addiu %[round2], $zero, 8192 \n\t" "move %[ptr_i], %[frfi] \n\t" "move %[tempMax], $zero \n\t" "addu %[i], %[n], %[n] \n\t" "5: \n\t" "lh %[tmp1], 0(%[ptr_i]) \n\t" "lh %[tmp2], 2(%[ptr_i]) \n\t" "lh %[tmp3], 4(%[ptr_i]) \n\t" "lh %[tmp4], 6(%[ptr_i]) \n\t" #if defined(MIPS_DSP_R1_LE) "absq_s.w %[tmp1], %[tmp1] \n\t" "absq_s.w %[tmp2], %[tmp2] \n\t" "absq_s.w %[tmp3], %[tmp3] \n\t" "absq_s.w %[tmp4], %[tmp4] \n\t" #else // #if defined(MIPS_DSP_R1_LE) "slt %[tmp5], %[tmp1], $zero \n\t" "subu %[tmp6], $zero, %[tmp1] \n\t" "movn %[tmp1], %[tmp6], %[tmp5] \n\t" "slt %[tmp5], %[tmp2], $zero \n\t" "subu %[tmp6], $zero, %[tmp2] \n\t" "movn %[tmp2], %[tmp6], %[tmp5] \n\t" "slt %[tmp5], %[tmp3], $zero \n\t" "subu %[tmp6], $zero, %[tmp3] \n\t" "movn %[tmp3], %[tmp6], %[tmp5] \n\t" "slt %[tmp5], %[tmp4], $zero \n\t" "subu %[tmp6], $zero, %[tmp4] \n\t" "movn %[tmp4], %[tmp6], %[tmp5] \n\t" #endif // #if defined(MIPS_DSP_R1_LE) "slt %[tmp5], %[tempMax], %[tmp1] \n\t" "movn %[tempMax], %[tmp1], %[tmp5] \n\t" "addiu %[i], %[i], -4 \n\t" "slt %[tmp5], %[tempMax], %[tmp2] \n\t" "movn %[tempMax], %[tmp2], %[tmp5] \n\t" "slt %[tmp5], %[tempMax], %[tmp3] \n\t" "movn %[tempMax], %[tmp3], %[tmp5] \n\t" "slt %[tmp5], %[tempMax], %[tmp4] \n\t" "movn %[tempMax], %[tmp4], %[tmp5] \n\t" "bgtz %[i], 5b \n\t" " addiu %[ptr_i], %[ptr_i], 8 \n\t" "addiu %[tmp1], $zero, 13573 \n\t" "addiu %[tmp2], $zero, 27146 \n\t" #if !defined(MIPS32_R2_LE) "sll %[tempMax], %[tempMax], 16 \n\t" "sra %[tempMax], %[tempMax], 16 \n\t" #else // #if !defined(MIPS32_R2_LE) "seh %[tempMax] \n\t" #endif // #if !defined(MIPS32_R2_LE) "slt %[tmp1], %[tmp1], %[tempMax] \n\t" "slt %[tmp2], %[tmp2], %[tempMax] \n\t" "addu %[tmp1], %[tmp1], %[tmp2] \n\t" "addu %[shift], %[shift], %[tmp1] \n\t" "addu %[scale], %[scale], %[tmp1] \n\t" "sllv %[round2], %[round2], %[tmp1] \n\t" "sll %[istep], %[l], 1 \n\t" "move %[m], $zero \n\t" "sll %[tmp], %[l], 2 \n\t" "2: \n\t" #if defined(MIPS_DSP_R1_LE) "sllv %[tmp3], %[m], %[k] \n\t" "addiu %[tmp2], %[tmp3], 512 \n\t" "addiu %[m], %[m], 1 \n\t" "lhx %[wi], %[tmp3](%[kSinTable1024]) \n\t" "lhx %[wr], %[tmp2](%[kSinTable1024]) \n\t" #else // #if defined(MIPS_DSP_R1_LE) "sllv %[tmp3], %[m], %[k] \n\t" "addu %[ptr_j], %[tmp3], %[kSinTable1024] \n\t" "addiu %[ptr_i], %[ptr_j], 512 \n\t" "addiu %[m], %[m], 1 \n\t" "lh %[wi], 0(%[ptr_j]) \n\t" "lh %[wr], 0(%[ptr_i]) \n\t" #endif // #if defined(MIPS_DSP_R1_LE) "1: \n\t" "sll %[tmp1], %[i], 2 \n\t" "addu %[ptr_i], %[frfi], %[tmp1] \n\t" "addu %[ptr_j], %[ptr_i], %[tmp] \n\t" "lh %[tmp3], 0(%[ptr_j]) \n\t" "lh %[tmp4], 2(%[ptr_j]) \n\t" "lh %[tmp6], 0(%[ptr_i]) \n\t" "lh %[tmp5], 2(%[ptr_i]) \n\t" "addu %[i], %[i], %[istep] \n\t" #if defined(MIPS_DSP_R2_LE) "mult %[wr], %[tmp3] \n\t" "msub %[wi], %[tmp4] \n\t" "mult $ac1, %[wr], %[tmp4] \n\t" "madd $ac1, %[wi], %[tmp3] \n\t" "mflo %[tmp1] \n\t" "mflo %[tmp2], $ac1 \n\t" "sll %[tmp6], %[tmp6], 14 \n\t" "sll %[tmp5], %[tmp5], 14 \n\t" "shra_r.w %[tmp1], %[tmp1], 1 \n\t" "shra_r.w %[tmp2], %[tmp2], 1 \n\t" "addu %[tmp6], %[tmp6], %[round2] \n\t" "addu %[tmp5], %[tmp5], %[round2] \n\t" "subu %[tmp4], %[tmp6], %[tmp1] \n\t" "addu %[tmp1], %[tmp6], %[tmp1] \n\t" "addu %[tmp6], %[tmp5], %[tmp2] \n\t" "subu %[tmp5], %[tmp5], %[tmp2] \n\t" "srav %[tmp4], %[tmp4], %[shift] \n\t" "srav %[tmp1], %[tmp1], %[shift] \n\t" "srav %[tmp6], %[tmp6], %[shift] \n\t" "srav %[tmp5], %[tmp5], %[shift] \n\t" #else // #if defined(MIPS_DSP_R2_LE) "mul %[tmp1], %[wr], %[tmp3] \n\t" "mul %[tmp2], %[wr], %[tmp4] \n\t" "mul %[tmp4], %[wi], %[tmp4] \n\t" "mul %[tmp3], %[wi], %[tmp3] \n\t" "sll %[tmp6], %[tmp6], 14 \n\t" "sll %[tmp5], %[tmp5], 14 \n\t" "sub %[tmp1], %[tmp1], %[tmp4] \n\t" "addu %[tmp2], %[tmp2], %[tmp3] \n\t" "addiu %[tmp1], %[tmp1], 1 \n\t" "addiu %[tmp2], %[tmp2], 1 \n\t" "sra %[tmp2], %[tmp2], 1 \n\t" "sra %[tmp1], %[tmp1], 1 \n\t" "addu %[tmp6], %[tmp6], %[round2] \n\t" "addu %[tmp5], %[tmp5], %[round2] \n\t" "subu %[tmp4], %[tmp6], %[tmp1] \n\t" "addu %[tmp1], %[tmp6], %[tmp1] \n\t" "addu %[tmp6], %[tmp5], %[tmp2] \n\t" "subu %[tmp5], %[tmp5], %[tmp2] \n\t" "sra %[tmp4], %[tmp4], %[shift] \n\t" "sra %[tmp1], %[tmp1], %[shift] \n\t" "sra %[tmp6], %[tmp6], %[shift] \n\t" "sra %[tmp5], %[tmp5], %[shift] \n\t" #endif // #if defined(MIPS_DSP_R2_LE) "sh %[tmp1], 0(%[ptr_i]) \n\t" "sh %[tmp6], 2(%[ptr_i]) \n\t" "sh %[tmp4], 0(%[ptr_j]) \n\t" "blt %[i], %[n], 1b \n\t" " sh %[tmp5], 2(%[ptr_j]) \n\t" "blt %[m], %[l], 2b \n\t" " addu %[i], $zero, %[m] \n\t" "move %[l], %[istep] \n\t" "blt %[l], %[n], 3b \n\t" " addiu %[k], %[k], -1 \n\t" ".set pop \n\t" : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2), [tmp3] "=&r" (tmp3), [tmp4] "=&r" (tmp4), [tmp5] "=&r" (tmp5), [tmp6] "=&r" (tmp6), [ptr_i] "=&r" (ptr_i), [i] "=&r" (i), [m] "=&r" (m), [tmp] "=&r" (tmp), [istep] "=&r" (istep), [wi] "=&r" (wi), [wr] "=&r" (wr), [l] "=&r" (l), [k] "=&r" (k), [round2] "=&r" (round2), [ptr_j] "=&r" (ptr_j), [shift] "=&r" (shift), [scale] "=&r" (scale), [tempMax] "=&r" (tempMax) : [n] "r" (n), [frfi] "r" (frfi), [kSinTable1024] "r" (kSinTable1024) : "hi", "lo", "memory" #if defined(MIPS_DSP_R2_LE) , "$ac1hi", "$ac1lo" #endif // #if defined(MIPS_DSP_R2_LE) ); return scale; }