| /* | |
| * 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/include/signal_processing_library.h" | |
| // Version of WebRtcSpl_DownsampleFast() for MIPS platforms. | |
| int WebRtcSpl_DownsampleFast_mips(const int16_t* data_in, | |
| size_t data_in_length, | |
| int16_t* data_out, | |
| size_t data_out_length, | |
| const int16_t* __restrict coefficients, | |
| size_t coefficients_length, | |
| int factor, | |
| size_t delay) { | |
| int i; | |
| int j; | |
| int k; | |
| int32_t out_s32 = 0; | |
| size_t endpos = delay + factor * (data_out_length - 1) + 1; | |
| int32_t tmp1, tmp2, tmp3, tmp4, factor_2; | |
| int16_t* p_coefficients; | |
| int16_t* p_data_in; | |
| int16_t* p_data_in_0 = (int16_t*)&data_in[delay]; | |
| int16_t* p_coefficients_0 = (int16_t*)&coefficients[0]; | |
| #if !defined(MIPS_DSP_R1_LE) | |
| int32_t max_16 = 0x7FFF; | |
| int32_t min_16 = 0xFFFF8000; | |
| #endif // #if !defined(MIPS_DSP_R1_LE) | |
| // Return error if any of the running conditions doesn't meet. | |
| if (data_out_length == 0 || coefficients_length == 0 || | |
| data_in_length < endpos) { | |
| return -1; | |
| } | |
| #if defined(MIPS_DSP_R2_LE) | |
| __asm __volatile( | |
| ".set push \n\t" | |
| ".set noreorder \n\t" | |
| "subu %[i], %[endpos], %[delay] \n\t" | |
| "sll %[factor_2], %[factor], 1 \n\t" | |
| "1: \n\t" | |
| "move %[p_data_in], %[p_data_in_0] \n\t" | |
| "mult $zero, $zero \n\t" | |
| "move %[p_coefs], %[p_coefs_0] \n\t" | |
| "sra %[j], %[coef_length], 2 \n\t" | |
| "beq %[j], $zero, 3f \n\t" | |
| " andi %[k], %[coef_length], 3 \n\t" | |
| "2: \n\t" | |
| "lwl %[tmp1], 1(%[p_data_in]) \n\t" | |
| "lwl %[tmp2], 3(%[p_coefs]) \n\t" | |
| "lwl %[tmp3], -3(%[p_data_in]) \n\t" | |
| "lwl %[tmp4], 7(%[p_coefs]) \n\t" | |
| "lwr %[tmp1], -2(%[p_data_in]) \n\t" | |
| "lwr %[tmp2], 0(%[p_coefs]) \n\t" | |
| "lwr %[tmp3], -6(%[p_data_in]) \n\t" | |
| "lwr %[tmp4], 4(%[p_coefs]) \n\t" | |
| "packrl.ph %[tmp1], %[tmp1], %[tmp1] \n\t" | |
| "packrl.ph %[tmp3], %[tmp3], %[tmp3] \n\t" | |
| "dpa.w.ph $ac0, %[tmp1], %[tmp2] \n\t" | |
| "dpa.w.ph $ac0, %[tmp3], %[tmp4] \n\t" | |
| "addiu %[j], %[j], -1 \n\t" | |
| "addiu %[p_data_in], %[p_data_in], -8 \n\t" | |
| "bgtz %[j], 2b \n\t" | |
| " addiu %[p_coefs], %[p_coefs], 8 \n\t" | |
| "3: \n\t" | |
| "beq %[k], $zero, 5f \n\t" | |
| " nop \n\t" | |
| "4: \n\t" | |
| "lhu %[tmp1], 0(%[p_data_in]) \n\t" | |
| "lhu %[tmp2], 0(%[p_coefs]) \n\t" | |
| "addiu %[p_data_in], %[p_data_in], -2 \n\t" | |
| "addiu %[k], %[k], -1 \n\t" | |
| "dpa.w.ph $ac0, %[tmp1], %[tmp2] \n\t" | |
| "bgtz %[k], 4b \n\t" | |
| " addiu %[p_coefs], %[p_coefs], 2 \n\t" | |
| "5: \n\t" | |
| "extr_r.w %[out_s32], $ac0, 12 \n\t" | |
| "addu %[p_data_in_0], %[p_data_in_0], %[factor_2] \n\t" | |
| "subu %[i], %[i], %[factor] \n\t" | |
| "shll_s.w %[out_s32], %[out_s32], 16 \n\t" | |
| "sra %[out_s32], %[out_s32], 16 \n\t" | |
| "sh %[out_s32], 0(%[data_out]) \n\t" | |
| "bgtz %[i], 1b \n\t" | |
| " addiu %[data_out], %[data_out], 2 \n\t" | |
| ".set pop \n\t" | |
| : [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2), [tmp3] "=&r"(tmp3), | |
| [tmp4] "=&r"(tmp4), [p_data_in] "=&r"(p_data_in), | |
| [p_data_in_0] "+r"(p_data_in_0), [p_coefs] "=&r"(p_coefficients), | |
| [j] "=&r"(j), [out_s32] "=&r"(out_s32), [factor_2] "=&r"(factor_2), | |
| [i] "=&r"(i), [k] "=&r"(k) | |
| : [coef_length] "r"(coefficients_length), [data_out] "r"(data_out), | |
| [p_coefs_0] "r"(p_coefficients_0), [endpos] "r"(endpos), | |
| [delay] "r"(delay), [factor] "r"(factor) | |
| : "memory", "hi", "lo"); | |
| #else // #if defined(MIPS_DSP_R2_LE) | |
| __asm __volatile( | |
| ".set push \n\t" | |
| ".set noreorder \n\t" | |
| "sll %[factor_2], %[factor], 1 \n\t" | |
| "subu %[i], %[endpos], %[delay] \n\t" | |
| "1: \n\t" | |
| "move %[p_data_in], %[p_data_in_0] \n\t" | |
| "addiu %[out_s32], $zero, 2048 \n\t" | |
| "move %[p_coefs], %[p_coefs_0] \n\t" | |
| "sra %[j], %[coef_length], 1 \n\t" | |
| "beq %[j], $zero, 3f \n\t" | |
| " andi %[k], %[coef_length], 1 \n\t" | |
| "2: \n\t" | |
| "lh %[tmp1], 0(%[p_data_in]) \n\t" | |
| "lh %[tmp2], 0(%[p_coefs]) \n\t" | |
| "lh %[tmp3], -2(%[p_data_in]) \n\t" | |
| "lh %[tmp4], 2(%[p_coefs]) \n\t" | |
| "mul %[tmp1], %[tmp1], %[tmp2] \n\t" | |
| "addiu %[p_coefs], %[p_coefs], 4 \n\t" | |
| "mul %[tmp3], %[tmp3], %[tmp4] \n\t" | |
| "addiu %[j], %[j], -1 \n\t" | |
| "addiu %[p_data_in], %[p_data_in], -4 \n\t" | |
| "addu %[tmp1], %[tmp1], %[tmp3] \n\t" | |
| "bgtz %[j], 2b \n\t" | |
| " addu %[out_s32], %[out_s32], %[tmp1] \n\t" | |
| "3: \n\t" | |
| "beq %[k], $zero, 4f \n\t" | |
| " nop \n\t" | |
| "lh %[tmp1], 0(%[p_data_in]) \n\t" | |
| "lh %[tmp2], 0(%[p_coefs]) \n\t" | |
| "mul %[tmp1], %[tmp1], %[tmp2] \n\t" | |
| "addu %[out_s32], %[out_s32], %[tmp1] \n\t" | |
| "4: \n\t" | |
| "sra %[out_s32], %[out_s32], 12 \n\t" | |
| "addu %[p_data_in_0], %[p_data_in_0], %[factor_2] \n\t" | |
| #if defined(MIPS_DSP_R1_LE) | |
| "shll_s.w %[out_s32], %[out_s32], 16 \n\t" | |
| "sra %[out_s32], %[out_s32], 16 \n\t" | |
| #else // #if defined(MIPS_DSP_R1_LE) | |
| "slt %[tmp1], %[max_16], %[out_s32] \n\t" | |
| "movn %[out_s32], %[max_16], %[tmp1] \n\t" | |
| "slt %[tmp1], %[out_s32], %[min_16] \n\t" | |
| "movn %[out_s32], %[min_16], %[tmp1] \n\t" | |
| #endif // #if defined(MIPS_DSP_R1_LE) | |
| "subu %[i], %[i], %[factor] \n\t" | |
| "sh %[out_s32], 0(%[data_out]) \n\t" | |
| "bgtz %[i], 1b \n\t" | |
| " addiu %[data_out], %[data_out], 2 \n\t" | |
| ".set pop \n\t" | |
| : [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2), [tmp3] "=&r"(tmp3), | |
| [tmp4] "=&r"(tmp4), [p_data_in] "=&r"(p_data_in), [k] "=&r"(k), | |
| [p_data_in_0] "+r"(p_data_in_0), [p_coefs] "=&r"(p_coefficients), | |
| [j] "=&r"(j), [out_s32] "=&r"(out_s32), [factor_2] "=&r"(factor_2), | |
| [i] "=&r"(i) | |
| : [coef_length] "r"(coefficients_length), [data_out] "r"(data_out), | |
| [p_coefs_0] "r"(p_coefficients_0), [endpos] "r"(endpos), | |
| #if !defined(MIPS_DSP_R1_LE) | |
| [max_16] "r"(max_16), [min_16] "r"(min_16), | |
| #endif // #if !defined(MIPS_DSP_R1_LE) | |
| [delay] "r"(delay), [factor] "r"(factor) | |
| : "memory", "hi", "lo"); | |
| #endif // #if defined(MIPS_DSP_R2_LE) | |
| return 0; | |
| } |