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 // This header file includes the inline functions in
12 // the fix point signal processing library.
13 
14 #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_
15 #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_
16 
WEBRTC_SPL_MUL_16_16(int32_t a,int32_t b)17 static __inline int32_t WEBRTC_SPL_MUL_16_16(int32_t a, int32_t b) {
18   int32_t value32 = 0;
19   int32_t a1 = 0, b1 = 0;
20 
21   __asm __volatile(
22 #if defined(MIPS32_R2_LE)
23       "seh    %[a1],          %[a]                \n\t"
24       "seh    %[b1],          %[b]                \n\t"
25 #else
26       "sll    %[a1],          %[a],         16    \n\t"
27       "sll    %[b1],          %[b],         16    \n\t"
28       "sra    %[a1],          %[a1],        16    \n\t"
29       "sra    %[b1],          %[b1],        16    \n\t"
30 #endif
31       "mul    %[value32],     %[a1],  %[b1]       \n\t"
32       : [value32] "=r"(value32), [a1] "=&r"(a1), [b1] "=&r"(b1)
33       : [a] "r"(a), [b] "r"(b)
34       : "hi", "lo");
35   return value32;
36 }
37 
WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a,int32_t b)38 static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a, int32_t b) {
39   int32_t value32 = 0, b1 = 0, b2 = 0;
40   int32_t a1 = 0;
41 
42   __asm __volatile(
43 #if defined(MIPS32_R2_LE)
44       "seh    %[a1],          %[a]                        \n\t"
45 #else
46       "sll    %[a1],          %[a],           16          \n\t"
47       "sra    %[a1],          %[a1],          16          \n\t"
48 #endif
49       "andi   %[b2],          %[b],           0xFFFF      \n\t"
50       "sra    %[b1],          %[b],           16          \n\t"
51       "sra    %[b2],          %[b2],          1           \n\t"
52       "mul    %[value32],     %[a1],          %[b1]       \n\t"
53       "mul    %[b2],          %[a1],          %[b2]       \n\t"
54       "addiu  %[b2],          %[b2],          0x4000      \n\t"
55       "sra    %[b2],          %[b2],          15          \n\t"
56       "addu   %[value32],     %[value32],     %[b2]       \n\t"
57       : [value32] "=&r"(value32), [b1] "=&r"(b1), [b2] "=&r"(b2), [a1] "=&r"(a1)
58       : [a] "r"(a), [b] "r"(b)
59       : "hi", "lo");
60   return value32;
61 }
62 
63 #if defined(MIPS_DSP_R1_LE)
WebRtcSpl_SatW32ToW16(int32_t value32)64 static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
65   __asm __volatile(
66       "shll_s.w   %[value32], %[value32], 16      \n\t"
67       "sra        %[value32], %[value32], 16      \n\t"
68       : [value32] "+r"(value32)
69       :);
70   int16_t out16 = (int16_t)value32;
71   return out16;
72 }
73 
WebRtcSpl_AddSatW16(int16_t a,int16_t b)74 static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
75   int32_t value32 = 0;
76 
77   __asm __volatile("addq_s.ph      %[value32],     %[a],   %[b]    \n\t"
78                    : [value32] "=r"(value32)
79                    : [a] "r"(a), [b] "r"(b));
80   return (int16_t)value32;
81 }
82 
WebRtcSpl_AddSatW32(int32_t l_var1,int32_t l_var2)83 static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
84   int32_t l_sum;
85 
86   __asm __volatile(
87       "addq_s.w   %[l_sum],       %[l_var1],      %[l_var2]    \n\t"
88       : [l_sum] "=r"(l_sum)
89       : [l_var1] "r"(l_var1), [l_var2] "r"(l_var2));
90 
91   return l_sum;
92 }
93 
WebRtcSpl_SubSatW16(int16_t var1,int16_t var2)94 static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
95   int32_t value32;
96 
97   __asm __volatile("subq_s.ph  %[value32], %[var1],    %[var2]     \n\t"
98                    : [value32] "=r"(value32)
99                    : [var1] "r"(var1), [var2] "r"(var2));
100 
101   return (int16_t)value32;
102 }
103 
WebRtcSpl_SubSatW32(int32_t l_var1,int32_t l_var2)104 static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
105   int32_t l_diff;
106 
107   __asm __volatile(
108       "subq_s.w   %[l_diff],      %[l_var1],      %[l_var2]    \n\t"
109       : [l_diff] "=r"(l_diff)
110       : [l_var1] "r"(l_var1), [l_var2] "r"(l_var2));
111 
112   return l_diff;
113 }
114 #endif
115 
WebRtcSpl_GetSizeInBits(uint32_t n)116 static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
117   int bits = 0;
118   int i32 = 32;
119 
120   __asm __volatile(
121       "clz    %[bits],    %[n]                    \n\t"
122       "subu   %[bits],    %[i32],     %[bits]     \n\t"
123       : [bits] "=&r"(bits)
124       : [n] "r"(n), [i32] "r"(i32));
125 
126   return (int16_t)bits;
127 }
128 
WebRtcSpl_NormW32(int32_t a)129 static __inline int16_t WebRtcSpl_NormW32(int32_t a) {
130   int zeros = 0;
131 
132   __asm __volatile(
133       ".set       push                                \n\t"
134       ".set       noreorder                           \n\t"
135       "bnez       %[a],       1f                      \n\t"
136       " sra       %[zeros],   %[a],       31          \n\t"
137       "b          2f                                  \n\t"
138       " move      %[zeros],   $zero                   \n\t"
139       "1:                                              \n\t"
140       "xor        %[zeros],   %[a],       %[zeros]    \n\t"
141       "clz        %[zeros],   %[zeros]                \n\t"
142       "addiu      %[zeros],   %[zeros],   -1          \n\t"
143       "2:                                              \n\t"
144       ".set       pop                                 \n\t"
145       : [zeros] "=&r"(zeros)
146       : [a] "r"(a));
147 
148   return (int16_t)zeros;
149 }
150 
WebRtcSpl_NormU32(uint32_t a)151 static __inline int16_t WebRtcSpl_NormU32(uint32_t a) {
152   int zeros = 0;
153 
154   __asm __volatile("clz    %[zeros],   %[a]    \n\t"
155                    : [zeros] "=r"(zeros)
156                    : [a] "r"(a));
157 
158   return (int16_t)(zeros & 0x1f);
159 }
160 
WebRtcSpl_NormW16(int16_t a)161 static __inline int16_t WebRtcSpl_NormW16(int16_t a) {
162   int zeros = 0;
163   int a0 = a << 16;
164 
165   __asm __volatile(
166       ".set       push                                \n\t"
167       ".set       noreorder                           \n\t"
168       "bnez       %[a0],      1f                      \n\t"
169       " sra       %[zeros],   %[a0],      31          \n\t"
170       "b          2f                                  \n\t"
171       " move      %[zeros],   $zero                   \n\t"
172       "1:                                              \n\t"
173       "xor        %[zeros],   %[a0],      %[zeros]    \n\t"
174       "clz        %[zeros],   %[zeros]                \n\t"
175       "addiu      %[zeros],   %[zeros],   -1          \n\t"
176       "2:                                              \n\t"
177       ".set       pop                                 \n\t"
178       : [zeros] "=&r"(zeros)
179       : [a0] "r"(a0));
180 
181   return (int16_t)zeros;
182 }
183 
WebRtc_MulAccumW16(int16_t a,int16_t b,int32_t c)184 static __inline int32_t WebRtc_MulAccumW16(int16_t a, int16_t b, int32_t c) {
185   int32_t res = 0, c1 = 0;
186   __asm __volatile(
187 #if defined(MIPS32_R2_LE)
188       "seh    %[a],       %[a]            \n\t"
189       "seh    %[b],       %[b]            \n\t"
190 #else
191       "sll    %[a],       %[a],   16      \n\t"
192       "sll    %[b],       %[b],   16      \n\t"
193       "sra    %[a],       %[a],   16      \n\t"
194       "sra    %[b],       %[b],   16      \n\t"
195 #endif
196       "mul    %[res],     %[a],   %[b]    \n\t"
197       "addu   %[c1],      %[c],   %[res]  \n\t"
198       : [c1] "=r"(c1), [res] "=&r"(res)
199       : [a] "r"(a), [b] "r"(b), [c] "r"(c)
200       : "hi", "lo");
201   return (c1);
202 }
203 
204 #endif  // COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_SPL_INL_MIPS_H_
205