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 file contains the implementation of function
13 * WebRtcSpl_MaxAbsValueW16()
14 *
15 * The description header can be found in signal_processing_library.h.
16 *
17 */
18
19 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
20
21 // Maximum absolute value of word16 vector.
WebRtcSpl_MaxAbsValueW16_mips(const int16_t * vector,int length)22 int16_t WebRtcSpl_MaxAbsValueW16_mips(const int16_t* vector, int length) {
23 int32_t totMax = 0;
24 int32_t tmp32_0, tmp32_1, tmp32_2, tmp32_3;
25 int i, loop_size;
26
27 if (vector == NULL || length <= 0) {
28 return -1;
29 }
30 #if defined(MIPS_DSP_R1)
31 const int32_t* tmpvec32 = (int32_t*)vector;
32 loop_size = length >> 4;
33
34 for (i = 0; i < loop_size; i++) {
35 __asm__ volatile (
36 "lw %[tmp32_0], 0(%[tmpvec32]) \n\t"
37 "lw %[tmp32_1], 4(%[tmpvec32]) \n\t"
38 "lw %[tmp32_2], 8(%[tmpvec32]) \n\t"
39 "lw %[tmp32_3], 12(%[tmpvec32]) \n\t"
40
41 "absq_s.ph %[tmp32_0], %[tmp32_0] \n\t"
42 "absq_s.ph %[tmp32_1], %[tmp32_1] \n\t"
43 "cmp.lt.ph %[totMax], %[tmp32_0] \n\t"
44 "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t"
45
46 "lw %[tmp32_0], 16(%[tmpvec32]) \n\t"
47 "absq_s.ph %[tmp32_2], %[tmp32_2] \n\t"
48 "cmp.lt.ph %[totMax], %[tmp32_1] \n\t"
49 "pick.ph %[totMax], %[tmp32_1], %[totMax] \n\t"
50
51 "lw %[tmp32_1], 20(%[tmpvec32]) \n\t"
52 "absq_s.ph %[tmp32_3], %[tmp32_3] \n\t"
53 "cmp.lt.ph %[totMax], %[tmp32_2] \n\t"
54 "pick.ph %[totMax], %[tmp32_2], %[totMax] \n\t"
55
56 "lw %[tmp32_2], 24(%[tmpvec32]) \n\t"
57 "cmp.lt.ph %[totMax], %[tmp32_3] \n\t"
58 "pick.ph %[totMax], %[tmp32_3], %[totMax] \n\t"
59
60 "lw %[tmp32_3], 28(%[tmpvec32]) \n\t"
61 "absq_s.ph %[tmp32_0], %[tmp32_0] \n\t"
62 "absq_s.ph %[tmp32_1], %[tmp32_1] \n\t"
63 "cmp.lt.ph %[totMax], %[tmp32_0] \n\t"
64 "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t"
65
66 "absq_s.ph %[tmp32_2], %[tmp32_2] \n\t"
67 "cmp.lt.ph %[totMax], %[tmp32_1] \n\t"
68 "pick.ph %[totMax], %[tmp32_1], %[totMax] \n\t"
69 "absq_s.ph %[tmp32_3], %[tmp32_3] \n\t"
70 "cmp.lt.ph %[totMax], %[tmp32_2] \n\t"
71 "pick.ph %[totMax], %[tmp32_2], %[totMax] \n\t"
72
73 "cmp.lt.ph %[totMax], %[tmp32_3] \n\t"
74 "pick.ph %[totMax], %[tmp32_3], %[totMax] \n\t"
75
76 "addiu %[tmpvec32], %[tmpvec32], 32 \n\t"
77 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1),
78 [tmp32_2] "=&r" (tmp32_2), [tmp32_3] "=&r" (tmp32_3),
79 [totMax] "+r" (totMax), [tmpvec32] "+r" (tmpvec32)
80 :
81 : "memory"
82 );
83 }
84 __asm__ volatile (
85 "rotr %[tmp32_0], %[totMax], 16 \n\t"
86 "cmp.lt.ph %[totMax], %[tmp32_0] \n\t"
87 "pick.ph %[totMax], %[tmp32_0], %[totMax] \n\t"
88 "packrl.ph %[totMax], $0, %[totMax] \n\t"
89 : [tmp32_0] "=&r" (tmp32_0), [totMax] "+r" (totMax)
90 :
91 );
92 loop_size = length & 0xf;
93 for (i = 0; i < loop_size; i++) {
94 __asm__ volatile (
95 "lh %[tmp32_0], 0(%[tmpvec32]) \n\t"
96 "addiu %[tmpvec32], %[tmpvec32], 2 \n\t"
97 "absq_s.w %[tmp32_0], %[tmp32_0] \n\t"
98 "slt %[tmp32_1], %[totMax], %[tmp32_0] \n\t"
99 "movn %[totMax], %[tmp32_0], %[tmp32_1] \n\t"
100 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1),
101 [tmpvec32] "+r" (tmpvec32), [totMax] "+r" (totMax)
102 :
103 : "memory"
104 );
105 }
106 #else // #if defined(MIPS_DSP_R1)
107 int32_t v16MaxMax = WEBRTC_SPL_WORD16_MAX;
108 int32_t r, r1, r2, r3;
109 const int16_t* tmpvector = vector;
110 loop_size = length >> 4;
111 for (i = 0; i < loop_size; i++) {
112 __asm__ volatile (
113 "lh %[tmp32_0], 0(%[tmpvector]) \n\t"
114 "lh %[tmp32_1], 2(%[tmpvector]) \n\t"
115 "lh %[tmp32_2], 4(%[tmpvector]) \n\t"
116 "lh %[tmp32_3], 6(%[tmpvector]) \n\t"
117
118 "abs %[tmp32_0], %[tmp32_0] \n\t"
119 "abs %[tmp32_1], %[tmp32_1] \n\t"
120 "abs %[tmp32_2], %[tmp32_2] \n\t"
121 "abs %[tmp32_3], %[tmp32_3] \n\t"
122
123 "slt %[r], %[totMax], %[tmp32_0] \n\t"
124 "movn %[totMax], %[tmp32_0], %[r] \n\t"
125 "slt %[r1], %[totMax], %[tmp32_1] \n\t"
126 "movn %[totMax], %[tmp32_1], %[r1] \n\t"
127 "slt %[r2], %[totMax], %[tmp32_2] \n\t"
128 "movn %[totMax], %[tmp32_2], %[r2] \n\t"
129 "slt %[r3], %[totMax], %[tmp32_3] \n\t"
130 "movn %[totMax], %[tmp32_3], %[r3] \n\t"
131
132 "lh %[tmp32_0], 8(%[tmpvector]) \n\t"
133 "lh %[tmp32_1], 10(%[tmpvector]) \n\t"
134 "lh %[tmp32_2], 12(%[tmpvector]) \n\t"
135 "lh %[tmp32_3], 14(%[tmpvector]) \n\t"
136
137 "abs %[tmp32_0], %[tmp32_0] \n\t"
138 "abs %[tmp32_1], %[tmp32_1] \n\t"
139 "abs %[tmp32_2], %[tmp32_2] \n\t"
140 "abs %[tmp32_3], %[tmp32_3] \n\t"
141
142 "slt %[r], %[totMax], %[tmp32_0] \n\t"
143 "movn %[totMax], %[tmp32_0], %[r] \n\t"
144 "slt %[r1], %[totMax], %[tmp32_1] \n\t"
145 "movn %[totMax], %[tmp32_1], %[r1] \n\t"
146 "slt %[r2], %[totMax], %[tmp32_2] \n\t"
147 "movn %[totMax], %[tmp32_2], %[r2] \n\t"
148 "slt %[r3], %[totMax], %[tmp32_3] \n\t"
149 "movn %[totMax], %[tmp32_3], %[r3] \n\t"
150
151 "lh %[tmp32_0], 16(%[tmpvector]) \n\t"
152 "lh %[tmp32_1], 18(%[tmpvector]) \n\t"
153 "lh %[tmp32_2], 20(%[tmpvector]) \n\t"
154 "lh %[tmp32_3], 22(%[tmpvector]) \n\t"
155
156 "abs %[tmp32_0], %[tmp32_0] \n\t"
157 "abs %[tmp32_1], %[tmp32_1] \n\t"
158 "abs %[tmp32_2], %[tmp32_2] \n\t"
159 "abs %[tmp32_3], %[tmp32_3] \n\t"
160
161 "slt %[r], %[totMax], %[tmp32_0] \n\t"
162 "movn %[totMax], %[tmp32_0], %[r] \n\t"
163 "slt %[r1], %[totMax], %[tmp32_1] \n\t"
164 "movn %[totMax], %[tmp32_1], %[r1] \n\t"
165 "slt %[r2], %[totMax], %[tmp32_2] \n\t"
166 "movn %[totMax], %[tmp32_2], %[r2] \n\t"
167 "slt %[r3], %[totMax], %[tmp32_3] \n\t"
168 "movn %[totMax], %[tmp32_3], %[r3] \n\t"
169
170 "lh %[tmp32_0], 24(%[tmpvector]) \n\t"
171 "lh %[tmp32_1], 26(%[tmpvector]) \n\t"
172 "lh %[tmp32_2], 28(%[tmpvector]) \n\t"
173 "lh %[tmp32_3], 30(%[tmpvector]) \n\t"
174
175 "abs %[tmp32_0], %[tmp32_0] \n\t"
176 "abs %[tmp32_1], %[tmp32_1] \n\t"
177 "abs %[tmp32_2], %[tmp32_2] \n\t"
178 "abs %[tmp32_3], %[tmp32_3] \n\t"
179
180 "slt %[r], %[totMax], %[tmp32_0] \n\t"
181 "movn %[totMax], %[tmp32_0], %[r] \n\t"
182 "slt %[r1], %[totMax], %[tmp32_1] \n\t"
183 "movn %[totMax], %[tmp32_1], %[r1] \n\t"
184 "slt %[r2], %[totMax], %[tmp32_2] \n\t"
185 "movn %[totMax], %[tmp32_2], %[r2] \n\t"
186 "slt %[r3], %[totMax], %[tmp32_3] \n\t"
187 "movn %[totMax], %[tmp32_3], %[r3] \n\t"
188
189 "addiu %[tmpvector], %[tmpvector], 32 \n\t"
190 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1),
191 [tmp32_2] "=&r" (tmp32_2), [tmp32_3] "=&r" (tmp32_3),
192 [totMax] "+r" (totMax), [r] "=&r" (r), [tmpvector] "+r" (tmpvector),
193 [r1] "=&r" (r1), [r2] "=&r" (r2), [r3] "=&r" (r3)
194 :
195 : "memory"
196 );
197 }
198 loop_size = length & 0xf;
199 for (i = 0; i < loop_size; i++) {
200 __asm__ volatile (
201 "lh %[tmp32_0], 0(%[tmpvector]) \n\t"
202 "addiu %[tmpvector], %[tmpvector], 2 \n\t"
203 "abs %[tmp32_0], %[tmp32_0] \n\t"
204 "slt %[tmp32_1], %[totMax], %[tmp32_0] \n\t"
205 "movn %[totMax], %[tmp32_0], %[tmp32_1] \n\t"
206 : [tmp32_0] "=&r" (tmp32_0), [tmp32_1] "=&r" (tmp32_1),
207 [tmpvector] "+r" (tmpvector), [totMax] "+r" (totMax)
208 :
209 : "memory"
210 );
211 }
212
213 __asm__ volatile (
214 "slt %[r], %[v16MaxMax], %[totMax] \n\t"
215 "movn %[totMax], %[v16MaxMax], %[r] \n\t"
216 : [totMax] "+r" (totMax), [r] "=&r" (r)
217 : [v16MaxMax] "r" (v16MaxMax)
218 );
219 #endif // #if defined(MIPS_DSP_R1)
220 return (int16_t)totMax;
221 }
222
223 #if defined(MIPS_DSP_R1_LE)
224 // Maximum absolute value of word32 vector. Version for MIPS platform.
WebRtcSpl_MaxAbsValueW32_mips(const int32_t * vector,int length)225 int32_t WebRtcSpl_MaxAbsValueW32_mips(const int32_t* vector, int length) {
226 // Use uint32_t for the local variables, to accommodate the return value
227 // of abs(0x80000000), which is 0x80000000.
228
229 uint32_t absolute = 0, maximum = 0;
230 int tmp1 = 0, max_value = 0x7fffffff;
231
232 if (vector == NULL || length <= 0) {
233 return -1;
234 }
235
236 __asm__ volatile (
237 ".set push \n\t"
238 ".set noreorder \n\t"
239
240 "1: \n\t"
241 "lw %[absolute], 0(%[vector]) \n\t"
242 "absq_s.w %[absolute], %[absolute] \n\t"
243 "addiu %[length], %[length], -1 \n\t"
244 "slt %[tmp1], %[maximum], %[absolute] \n\t"
245 "movn %[maximum], %[absolute], %[tmp1] \n\t"
246 "bgtz %[length], 1b \n\t"
247 " addiu %[vector], %[vector], 4 \n\t"
248 "slt %[tmp1], %[max_value], %[maximum] \n\t"
249 "movn %[maximum], %[max_value], %[tmp1] \n\t"
250
251 ".set pop \n\t"
252
253 : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [absolute] "+r" (absolute)
254 : [vector] "r" (vector), [length] "r" (length), [max_value] "r" (max_value)
255 : "memory"
256 );
257
258 return (int32_t)maximum;
259 }
260 #endif // #if defined(MIPS_DSP_R1_LE)
261
262 // Maximum value of word16 vector. Version for MIPS platform.
WebRtcSpl_MaxValueW16_mips(const int16_t * vector,int length)263 int16_t WebRtcSpl_MaxValueW16_mips(const int16_t* vector, int length) {
264 int16_t maximum = WEBRTC_SPL_WORD16_MIN;
265 int tmp1;
266 int16_t value;
267
268 if (vector == NULL || length <= 0) {
269 return maximum;
270 }
271
272 __asm__ volatile (
273 ".set push \n\t"
274 ".set noreorder \n\t"
275
276 "1: \n\t"
277 "lh %[value], 0(%[vector]) \n\t"
278 "addiu %[length], %[length], -1 \n\t"
279 "slt %[tmp1], %[maximum], %[value] \n\t"
280 "movn %[maximum], %[value], %[tmp1] \n\t"
281 "bgtz %[length], 1b \n\t"
282 " addiu %[vector], %[vector], 2 \n\t"
283 ".set pop \n\t"
284
285 : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [value] "=&r" (value)
286 : [vector] "r" (vector), [length] "r" (length)
287 : "memory"
288 );
289
290 return maximum;
291 }
292
293 // Maximum value of word32 vector. Version for MIPS platform.
WebRtcSpl_MaxValueW32_mips(const int32_t * vector,int length)294 int32_t WebRtcSpl_MaxValueW32_mips(const int32_t* vector, int length) {
295 int32_t maximum = WEBRTC_SPL_WORD32_MIN;
296 int tmp1, value;
297
298 if (vector == NULL || length <= 0) {
299 return maximum;
300 }
301
302 __asm__ volatile (
303 ".set push \n\t"
304 ".set noreorder \n\t"
305
306 "1: \n\t"
307 "lw %[value], 0(%[vector]) \n\t"
308 "addiu %[length], %[length], -1 \n\t"
309 "slt %[tmp1], %[maximum], %[value] \n\t"
310 "movn %[maximum], %[value], %[tmp1] \n\t"
311 "bgtz %[length], 1b \n\t"
312 " addiu %[vector], %[vector], 4 \n\t"
313
314 ".set pop \n\t"
315
316 : [tmp1] "=&r" (tmp1), [maximum] "+r" (maximum), [value] "=&r" (value)
317 : [vector] "r" (vector), [length] "r" (length)
318 : "memory"
319 );
320
321 return maximum;
322 }
323
324 // Minimum value of word16 vector. Version for MIPS platform.
WebRtcSpl_MinValueW16_mips(const int16_t * vector,int length)325 int16_t WebRtcSpl_MinValueW16_mips(const int16_t* vector, int length) {
326 int16_t minimum = WEBRTC_SPL_WORD16_MAX;
327 int tmp1;
328 int16_t value;
329
330 if (vector == NULL || length <= 0) {
331 return minimum;
332 }
333
334 __asm__ volatile (
335 ".set push \n\t"
336 ".set noreorder \n\t"
337
338 "1: \n\t"
339 "lh %[value], 0(%[vector]) \n\t"
340 "addiu %[length], %[length], -1 \n\t"
341 "slt %[tmp1], %[value], %[minimum] \n\t"
342 "movn %[minimum], %[value], %[tmp1] \n\t"
343 "bgtz %[length], 1b \n\t"
344 " addiu %[vector], %[vector], 2 \n\t"
345
346 ".set pop \n\t"
347
348 : [tmp1] "=&r" (tmp1), [minimum] "+r" (minimum), [value] "=&r" (value)
349 : [vector] "r" (vector), [length] "r" (length)
350 : "memory"
351 );
352
353 return minimum;
354 }
355
356 // Minimum value of word32 vector. Version for MIPS platform.
WebRtcSpl_MinValueW32_mips(const int32_t * vector,int length)357 int32_t WebRtcSpl_MinValueW32_mips(const int32_t* vector, int length) {
358 int32_t minimum = WEBRTC_SPL_WORD32_MAX;
359 int tmp1, value;
360
361 if (vector == NULL || length <= 0) {
362 return minimum;
363 }
364
365 __asm__ volatile (
366 ".set push \n\t"
367 ".set noreorder \n\t"
368
369 "1: \n\t"
370 "lw %[value], 0(%[vector]) \n\t"
371 "addiu %[length], %[length], -1 \n\t"
372 "slt %[tmp1], %[value], %[minimum] \n\t"
373 "movn %[minimum], %[value], %[tmp1] \n\t"
374 "bgtz %[length], 1b \n\t"
375 " addiu %[vector], %[vector], 4 \n\t"
376
377 ".set pop \n\t"
378
379 : [tmp1] "=&r" (tmp1), [minimum] "+r" (minimum), [value] "=&r" (value)
380 : [vector] "r" (vector), [length] "r" (length)
381 : "memory"
382 );
383
384 return minimum;
385 }
386