blob: 34c4f232a0b3eb52030571f80ad85829cbe1eef1 [file] [log] [blame]
/*
* 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;
}