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
12 // This header file includes the inline functions in
13 // the fix point signal processing library.
14
15 #ifndef WEBRTC_SPL_SPL_INL_MIPS_H_
16 #define WEBRTC_SPL_SPL_INL_MIPS_H_
17
WEBRTC_SPL_MUL_16_16(int32_t a,int32_t b)18 static __inline int32_t WEBRTC_SPL_MUL_16_16(int32_t a,
19 int32_t b) {
20 int32_t value32 = 0;
21 int32_t a1 = 0, b1 = 0;
22
23 __asm __volatile(
24 #if defined(MIPS32_R2_LE)
25 "seh %[a1], %[a] \n\t"
26 "seh %[b1], %[b] \n\t"
27 #else
28 "sll %[a1], %[a], 16 \n\t"
29 "sll %[b1], %[b], 16 \n\t"
30 "sra %[a1], %[a1], 16 \n\t"
31 "sra %[b1], %[b1], 16 \n\t"
32 #endif
33 "mul %[value32], %[a1], %[b1] \n\t"
34 : [value32] "=r" (value32), [a1] "=&r" (a1), [b1] "=&r" (b1)
35 : [a] "r" (a), [b] "r" (b)
36 : "hi", "lo"
37 );
38 return value32;
39 }
40
WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a,int32_t b)41 static __inline int32_t WEBRTC_SPL_MUL_16_32_RSFT16(int16_t a,
42 int32_t b) {
43 int32_t value32 = 0, b1 = 0, b2 = 0;
44 int32_t a1 = 0;
45
46 __asm __volatile(
47 #if defined(MIPS32_R2_LE)
48 "seh %[a1], %[a] \n\t"
49 #else
50 "sll %[a1], %[a], 16 \n\t"
51 "sra %[a1], %[a1], 16 \n\t"
52 #endif
53 "andi %[b2], %[b], 0xFFFF \n\t"
54 "sra %[b1], %[b], 16 \n\t"
55 "sra %[b2], %[b2], 1 \n\t"
56 "mul %[value32], %[a1], %[b1] \n\t"
57 "mul %[b2], %[a1], %[b2] \n\t"
58 "addiu %[b2], %[b2], 0x4000 \n\t"
59 "sra %[b2], %[b2], 15 \n\t"
60 "addu %[value32], %[value32], %[b2] \n\t"
61 : [value32] "=&r" (value32), [b1] "=&r" (b1), [b2] "=&r" (b2),
62 [a1] "=&r" (a1)
63 : [a] "r" (a), [b] "r" (b)
64 : "hi", "lo"
65 );
66 return value32;
67 }
68
WEBRTC_SPL_MUL_32_32_RSFT32BI(int32_t a,int32_t b)69 static __inline int32_t WEBRTC_SPL_MUL_32_32_RSFT32BI(int32_t a,
70 int32_t b) {
71 int32_t tmp = 0;
72
73 if ((32767 < a) || (a < 0))
74 tmp = WEBRTC_SPL_MUL_16_32_RSFT16(((int16_t)(a >> 16)), b);
75 tmp += WEBRTC_SPL_MUL_16_32_RSFT16(((int16_t)((a & 0x0000FFFF) >> 1)),
76 b) >> 15;
77
78 return tmp;
79 }
80
WEBRTC_SPL_MUL_32_32_RSFT32(int16_t a,int16_t b,int32_t c)81 static __inline int32_t WEBRTC_SPL_MUL_32_32_RSFT32(int16_t a,
82 int16_t b,
83 int32_t c) {
84 int32_t tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;
85
86 __asm __volatile(
87 "sra %[tmp1], %[c], 16 \n\t"
88 "andi %[tmp2], %[c], 0xFFFF \n\t"
89 #if defined(MIPS32_R2_LE)
90 "seh %[a], %[a] \n\t"
91 "seh %[b], %[b] \n\t"
92 #else
93 "sll %[a], %[a], 16 \n\t"
94 "sra %[a], %[a], 16 \n\t"
95 "sll %[b], %[b], 16 \n\t"
96 "sra %[b], %[b], 16 \n\t"
97 #endif
98 "sra %[tmp2], %[tmp2], 1 \n\t"
99 "mul %[tmp3], %[a], %[tmp2] \n\t"
100 "mul %[tmp4], %[b], %[tmp2] \n\t"
101 "mul %[tmp2], %[a], %[tmp1] \n\t"
102 "mul %[tmp1], %[b], %[tmp1] \n\t"
103 #if defined(MIPS_DSP_R1_LE)
104 "shra_r.w %[tmp3], %[tmp3], 15 \n\t"
105 "shra_r.w %[tmp4], %[tmp4], 15 \n\t"
106 #else
107 "addiu %[tmp3], %[tmp3], 0x4000 \n\t"
108 "sra %[tmp3], %[tmp3], 15 \n\t"
109 "addiu %[tmp4], %[tmp4], 0x4000 \n\t"
110 "sra %[tmp4], %[tmp4], 15 \n\t"
111 #endif
112 "addu %[tmp3], %[tmp3], %[tmp2] \n\t"
113 "addu %[tmp4], %[tmp4], %[tmp1] \n\t"
114 "sra %[tmp4], %[tmp4], 16 \n\t"
115 "addu %[tmp1], %[tmp3], %[tmp4] \n\t"
116 : [tmp1] "=&r" (tmp1), [tmp2] "=&r" (tmp2),
117 [tmp3] "=&r" (tmp3), [tmp4] "=&r" (tmp4),
118 [a] "+r" (a), [b] "+r" (b)
119 : [c] "r" (c)
120 : "hi", "lo"
121 );
122 return tmp1;
123 }
124
125 #if defined(MIPS_DSP_R1_LE)
WebRtcSpl_SatW32ToW16(int32_t value32)126 static __inline int16_t WebRtcSpl_SatW32ToW16(int32_t value32) {
127 __asm __volatile(
128 "shll_s.w %[value32], %[value32], 16 \n\t"
129 "sra %[value32], %[value32], 16 \n\t"
130 : [value32] "+r" (value32)
131 :
132 );
133 int16_t out16 = (int16_t)value32;
134 return out16;
135 }
136
WebRtcSpl_AddSatW16(int16_t a,int16_t b)137 static __inline int16_t WebRtcSpl_AddSatW16(int16_t a, int16_t b) {
138 int32_t value32 = 0;
139
140 __asm __volatile(
141 "addq_s.ph %[value32], %[a], %[b] \n\t"
142 : [value32] "=r" (value32)
143 : [a] "r" (a), [b] "r" (b)
144 );
145 return (int16_t)value32;
146 }
147
WebRtcSpl_AddSatW32(int32_t l_var1,int32_t l_var2)148 static __inline int32_t WebRtcSpl_AddSatW32(int32_t l_var1, int32_t l_var2) {
149 int32_t l_sum;
150
151 __asm __volatile(
152 "addq_s.w %[l_sum], %[l_var1], %[l_var2] \n\t"
153 : [l_sum] "=r" (l_sum)
154 : [l_var1] "r" (l_var1), [l_var2] "r" (l_var2)
155 );
156
157 return l_sum;
158 }
159
WebRtcSpl_SubSatW16(int16_t var1,int16_t var2)160 static __inline int16_t WebRtcSpl_SubSatW16(int16_t var1, int16_t var2) {
161 int32_t value32;
162
163 __asm __volatile(
164 "subq_s.ph %[value32], %[var1], %[var2] \n\t"
165 : [value32] "=r" (value32)
166 : [var1] "r" (var1), [var2] "r" (var2)
167 );
168
169 return (int16_t)value32;
170 }
171
WebRtcSpl_SubSatW32(int32_t l_var1,int32_t l_var2)172 static __inline int32_t WebRtcSpl_SubSatW32(int32_t l_var1, int32_t l_var2) {
173 int32_t l_diff;
174
175 __asm __volatile(
176 "subq_s.w %[l_diff], %[l_var1], %[l_var2] \n\t"
177 : [l_diff] "=r" (l_diff)
178 : [l_var1] "r" (l_var1), [l_var2] "r" (l_var2)
179 );
180
181 return l_diff;
182 }
183 #endif
184
WebRtcSpl_GetSizeInBits(uint32_t n)185 static __inline int16_t WebRtcSpl_GetSizeInBits(uint32_t n) {
186 int bits = 0;
187 int i32 = 32;
188
189 __asm __volatile(
190 "clz %[bits], %[n] \n\t"
191 "subu %[bits], %[i32], %[bits] \n\t"
192 : [bits] "=&r" (bits)
193 : [n] "r" (n), [i32] "r" (i32)
194 );
195
196 return bits;
197 }
198
WebRtcSpl_NormW32(int32_t a)199 static __inline int WebRtcSpl_NormW32(int32_t a) {
200 int zeros = 0;
201
202 __asm __volatile(
203 ".set push \n\t"
204 ".set noreorder \n\t"
205 "bnez %[a], 1f \n\t"
206 " sra %[zeros], %[a], 31 \n\t"
207 "b 2f \n\t"
208 " move %[zeros], $zero \n\t"
209 "1: \n\t"
210 "xor %[zeros], %[a], %[zeros] \n\t"
211 "clz %[zeros], %[zeros] \n\t"
212 "addiu %[zeros], %[zeros], -1 \n\t"
213 "2: \n\t"
214 ".set pop \n\t"
215 : [zeros]"=&r"(zeros)
216 : [a] "r" (a)
217 );
218
219 return zeros;
220 }
221
WebRtcSpl_NormU32(uint32_t a)222 static __inline int WebRtcSpl_NormU32(uint32_t a) {
223 int zeros = 0;
224
225 __asm __volatile(
226 "clz %[zeros], %[a] \n\t"
227 : [zeros] "=r" (zeros)
228 : [a] "r" (a)
229 );
230
231 return (zeros & 0x1f);
232 }
233
WebRtcSpl_NormW16(int16_t a)234 static __inline int WebRtcSpl_NormW16(int16_t a) {
235 int zeros = 0;
236 int a0 = a << 16;
237
238 __asm __volatile(
239 ".set push \n\t"
240 ".set noreorder \n\t"
241 "bnez %[a0], 1f \n\t"
242 " sra %[zeros], %[a0], 31 \n\t"
243 "b 2f \n\t"
244 " move %[zeros], $zero \n\t"
245 "1: \n\t"
246 "xor %[zeros], %[a0], %[zeros] \n\t"
247 "clz %[zeros], %[zeros] \n\t"
248 "addiu %[zeros], %[zeros], -1 \n\t"
249 "2: \n\t"
250 ".set pop \n\t"
251 : [zeros]"=&r"(zeros)
252 : [a0] "r" (a0)
253 );
254
255 return zeros;
256 }
257
WebRtc_MulAccumW16(int16_t a,int16_t b,int32_t c)258 static __inline int32_t WebRtc_MulAccumW16(int16_t a,
259 int16_t b,
260 int32_t c) {
261 int32_t res = 0, c1 = 0;
262 __asm __volatile(
263 #if defined(MIPS32_R2_LE)
264 "seh %[a], %[a] \n\t"
265 "seh %[b], %[b] \n\t"
266 #else
267 "sll %[a], %[a], 16 \n\t"
268 "sll %[b], %[b], 16 \n\t"
269 "sra %[a], %[a], 16 \n\t"
270 "sra %[b], %[b], 16 \n\t"
271 #endif
272 "mul %[res], %[a], %[b] \n\t"
273 "addu %[c1], %[c], %[res] \n\t"
274 : [c1] "=r" (c1), [res] "=&r" (res)
275 : [a] "r" (a), [b] "r" (b), [c] "r" (c)
276 : "hi", "lo"
277 );
278 return (c1);
279 }
280
281 #endif // WEBRTC_SPL_SPL_INL_MIPS_H_
282