| /* |
| * 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 "webrtc/common_audio/signal_processing/complex_fft_tables.h" |
| #include "webrtc/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; |
| |
| } |