1 /******************************************************************************
2 * *
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #ifndef IXHEAACD_BASIC_OPS32_H
21 #define IXHEAACD_BASIC_OPS32_H
22
ixheaacd_min32(WORD32 a,WORD32 b)23 static PLATFORM_INLINE WORD32 ixheaacd_min32(WORD32 a, WORD32 b) {
24 WORD32 min_val;
25
26 min_val = (a < b) ? a : b;
27
28 return min_val;
29 }
30
ixheaacd_max32(WORD32 a,WORD32 b)31 static PLATFORM_INLINE WORD32 ixheaacd_max32(WORD32 a, WORD32 b) {
32 WORD32 max_val;
33
34 max_val = (a > b) ? a : b;
35
36 return max_val;
37 }
38
ixheaacd_shl32(WORD32 a,WORD b)39 static PLATFORM_INLINE WORD32 ixheaacd_shl32(WORD32 a, WORD b) {
40 WORD32 out_val;
41
42 b = ((UWORD32)(b << 24) >> 24);
43 if (b > 31)
44 out_val = 0;
45 else
46 out_val = (WORD32)a << b;
47
48 return out_val;
49 }
50
ixheaacd_shr32(WORD32 a,WORD b)51 static PLATFORM_INLINE WORD32 ixheaacd_shr32(WORD32 a, WORD b) {
52 WORD32 out_val;
53
54 b = ((UWORD32)(b << 24) >> 24);
55 if (b >= 31) {
56 if (a < 0)
57 out_val = -1;
58 else
59 out_val = 0;
60 } else {
61 out_val = (WORD32)a >> b;
62 }
63
64 return out_val;
65 }
66
ixheaacd_shl32_sat(WORD32 a,WORD b)67 static PLATFORM_INLINE WORD32 ixheaacd_shl32_sat(WORD32 a, WORD b) {
68 WORD32 out_val = a;
69 for (; b > 0; b--) {
70 if (a > (WORD32)0X3fffffffL) {
71 out_val = MAX_32;
72 break;
73 } else if (a < (WORD32)0xc0000000L) {
74 out_val = MIN_32;
75 break;
76 }
77
78 a = ixheaacd_shl32(a, 1);
79 out_val = a;
80 }
81 return (out_val);
82 }
83
ixheaacd_shl32_dir(WORD32 a,WORD b)84 static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir(WORD32 a, WORD b) {
85 WORD32 out_val;
86
87 if (b < 0) {
88 out_val = ixheaacd_shr32(a, -b);
89 } else {
90 out_val = ixheaacd_shl32(a, b);
91 }
92
93 return out_val;
94 }
95
ixheaacd_shl32_dir_sat(WORD32 a,WORD b)96 static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir_sat(WORD32 a, WORD b) {
97 WORD32 out_val;
98
99 if (b < 0) {
100 out_val = ixheaacd_shr32(a, -b);
101 } else {
102 out_val = ixheaacd_shl32_sat(a, b);
103 }
104
105 return out_val;
106 }
107
ixheaacd_shr32_dir(WORD32 a,WORD b)108 static PLATFORM_INLINE WORD32 ixheaacd_shr32_dir(WORD32 a, WORD b) {
109 WORD32 out_val;
110
111 if (b < 0) {
112 out_val = ixheaacd_shl32(a, -b);
113 } else {
114 out_val = ixheaacd_shr32(a, b);
115 }
116
117 return out_val;
118 }
119
shr32_dir_sat(WORD32 a,WORD b)120 static PLATFORM_INLINE WORD32 shr32_dir_sat(WORD32 a, WORD b) {
121 WORD32 out_val;
122
123 if (b < 0) {
124 out_val = ixheaacd_shl32_sat(a, -b);
125 } else {
126 out_val = ixheaacd_shr32(a, b);
127 }
128
129 return out_val;
130 }
131
ixheaacd_mult16x16in32(WORD16 a,WORD16 b)132 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32(WORD16 a, WORD16 b) {
133 WORD32 product;
134
135 product = (WORD32)a * (WORD32)b;
136
137 return product;
138 }
139
mult16x16in32_32(WORD32 a,WORD32 b)140 static PLATFORM_INLINE WORD32 mult16x16in32_32(WORD32 a, WORD32 b) {
141 WORD32 product;
142
143 product = (WORD32)a * (WORD32)b;
144
145 return product;
146 }
147
ixheaacd_mult16x16in32_shl(WORD16 a,WORD16 b)148 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl(WORD16 a, WORD16 b) {
149 WORD32 product;
150
151 product = ixheaacd_shl32(ixheaacd_mult16x16in32(a, b), 1);
152
153 return product;
154 }
155
ixheaacd_mult16x16in32_shl_sat(WORD16 a,WORD16 b)156 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl_sat(WORD16 a,
157 WORD16 b) {
158 WORD32 product;
159 product = (WORD32)a * (WORD32)b;
160 if (product != (WORD32)0x40000000L) {
161 product = ixheaacd_shl32(product, 1);
162 } else {
163 product = MAX_32;
164 }
165 return product;
166 }
167
ixheaacd_add32(WORD32 a,WORD32 b)168 static PLATFORM_INLINE WORD32 ixheaacd_add32(WORD32 a, WORD32 b) {
169 WORD32 sum;
170
171 sum = (WORD32)a + (WORD32)b;
172
173 return sum;
174 }
175
ixheaacd_sub32(WORD32 a,WORD32 b)176 static PLATFORM_INLINE WORD32 ixheaacd_sub32(WORD32 a, WORD32 b) {
177 WORD32 diff;
178
179 diff = (WORD32)a - (WORD32)b;
180
181 return diff;
182 }
183
ixheaacd_add32_sat(WORD32 a,WORD32 b)184 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat(WORD32 a, WORD32 b) {
185 WORD64 sum;
186
187 sum = (WORD64)a + (WORD64)b;
188
189 if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) == 0) {
190 if (((WORD32)sum ^ (WORD32)a) & (WORD32)MIN_32) {
191 sum = (a < 0) ? MIN_32 : MAX_32;
192 }
193 }
194
195 return (WORD32)sum;
196 }
197
ixheaacd_add32_sat3(WORD32 a,WORD32 b,WORD32 c)198 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b,
199 WORD32 c) {
200 WORD64 sum;
201
202 sum = (WORD64)a + (WORD64)b;
203
204 sum = (WORD64)sum + (WORD64)c;
205
206 if (sum > MAX_32) {
207 sum = MAX_32;
208 }
209 if (sum < MIN_32) {
210 sum = MIN_32;
211 }
212
213 return (WORD32)sum;
214 }
215
ixheaacd_sub32_sat(WORD32 a,WORD32 b)216 static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) {
217 WORD64 diff;
218
219 diff = (WORD64)a - (WORD64)b;
220
221 if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) != 0) {
222 if (((WORD32)diff ^ (WORD32)a) & (WORD32)MIN_32) {
223 diff = (a < 0L) ? MIN_32 : MAX_32;
224 }
225 }
226
227 return (WORD32)diff;
228 }
229
ixheaacd_norm32(WORD32 a)230 static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) {
231 WORD norm_val;
232
233 if (a == 0) {
234 norm_val = 31;
235 } else {
236 if (a == (WORD32)0xffffffffL) {
237 norm_val = 31;
238 } else {
239 if (a < 0) {
240 a = ~a;
241 }
242 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
243 a <<= 1;
244 }
245 }
246 }
247
248 return norm_val;
249 }
250
ixheaacd_pnorm32(WORD32 a)251 static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) {
252 WORD norm_val;
253
254 if (a == 0) {
255 norm_val = 31;
256 } else {
257 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
258 a <<= 1;
259 }
260 }
261
262 return norm_val;
263 }
264
bin_expo32(WORD32 a)265 static PLATFORM_INLINE WORD bin_expo32(WORD32 a) {
266 WORD bin_expo_val;
267
268 bin_expo_val = 31 - ixheaacd_norm32(a);
269
270 return bin_expo_val;
271 }
272
ixheaacd_abs32(WORD32 a)273 static PLATFORM_INLINE WORD32 ixheaacd_abs32(WORD32 a) {
274 WORD32 abs_val;
275
276 abs_val = a;
277
278 if (a < 0) {
279 abs_val = -a;
280 }
281
282 return abs_val;
283 }
284
ixheaacd_abs32_nrm(WORD32 a)285 static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(WORD32 a) {
286 WORD32 abs_val;
287
288 abs_val = a;
289
290 if (a < 0) {
291 abs_val = ~a;
292 }
293
294 return abs_val;
295 }
296
ixheaacd_abs32_sat(WORD32 a)297 static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) {
298 WORD32 abs_val;
299
300 abs_val = a;
301
302 if (a == MIN_32) {
303 abs_val = MAX_32;
304 } else if (a < 0) {
305 abs_val = -a;
306 }
307
308 return abs_val;
309 }
310
ixheaacd_negate32(WORD32 a)311 static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) {
312 WORD32 neg_val;
313
314 neg_val = -a;
315
316 return neg_val;
317 }
318
ixheaacd_negate32_sat(WORD32 a)319 static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) {
320 WORD32 neg_val;
321
322 if (a == MIN_32) {
323 neg_val = MAX_32;
324 } else {
325 neg_val = -a;
326 }
327 return neg_val;
328 }
329
div32(WORD32 a,WORD32 b,WORD * q_format)330 static PLATFORM_INLINE WORD32 div32(WORD32 a, WORD32 b, WORD *q_format) {
331 WORD32 quotient;
332 UWORD32 mantissa_nr, mantissa_dr;
333 WORD16 sign = 0;
334
335 LOOPINDEX i;
336 WORD q_nr, q_dr;
337
338 mantissa_nr = a;
339 mantissa_dr = b;
340 quotient = 0;
341
342 if ((a < 0) && (0 != b)) {
343 a = -a;
344 sign = (WORD16)(sign ^ -1);
345 }
346
347 if (b < 0) {
348 b = -b;
349 sign = (WORD16)(sign ^ -1);
350 }
351
352 if (0 == b) {
353 *q_format = 0;
354 return (a);
355 }
356
357 quotient = 0;
358
359 q_nr = ixheaacd_norm32(a);
360 mantissa_nr = (UWORD32)a << (q_nr);
361 q_dr = ixheaacd_norm32(b);
362 mantissa_dr = (UWORD32)b << (q_dr);
363 *q_format = (WORD)(30 + q_nr - q_dr);
364
365 for (i = 0; i < 31; i++) {
366 quotient = quotient << 1;
367
368 if (mantissa_nr >= mantissa_dr) {
369 mantissa_nr = mantissa_nr - mantissa_dr;
370 quotient += 1;
371 }
372
373 mantissa_nr = (UWORD32)mantissa_nr << 1;
374 }
375
376 if (sign < 0) {
377 quotient = -quotient;
378 }
379
380 return quotient;
381 }
382
ixheaacd_mac16x16in32(WORD32 a,WORD16 b,WORD16 c)383 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32(WORD32 a, WORD16 b,
384 WORD16 c) {
385 WORD32 acc;
386
387 acc = ixheaacd_mult16x16in32(b, c);
388
389 acc = ixheaacd_add32(a, acc);
390
391 return acc;
392 }
393
mac16x16hin32(WORD32 a,WORD32 b,WORD32 c)394 static PLATFORM_INLINE WORD32 mac16x16hin32(WORD32 a, WORD32 b, WORD32 c) {
395 WORD32 acc;
396
397 acc = ixheaacd_mult16x16in32((WORD16)b, (WORD16)(c >> 16));
398
399 acc = ixheaacd_add32(a, acc);
400
401 return acc;
402 }
403
ixheaacd_mac16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)404 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b,
405 WORD16 c) {
406 WORD32 acc;
407
408 acc = ixheaacd_mult16x16in32_shl(b, c);
409
410 acc = ixheaacd_add32(a, acc);
411
412 return acc;
413 }
414
ixheaacd_mac16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)415 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b,
416 WORD16 c) {
417 WORD32 acc;
418
419 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
420
421 acc = ixheaacd_add32_sat(a, acc);
422
423 return acc;
424 }
425
msu16x16in32(WORD32 a,WORD16 b,WORD16 c)426 static PLATFORM_INLINE WORD32 msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
427 WORD32 acc;
428
429 acc = ixheaacd_mult16x16in32(b, c);
430
431 acc = ixheaacd_sub32(a, acc);
432
433 return acc;
434 }
435
msu16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)436 static PLATFORM_INLINE WORD32 msu16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) {
437 WORD32 acc;
438
439 acc = ixheaacd_mult16x16in32_shl(b, c);
440
441 acc = ixheaacd_sub32(a, acc);
442
443 return acc;
444 }
445
msu16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)446 static PLATFORM_INLINE WORD32 msu16x16in32_shl_sat(WORD32 a, WORD16 b,
447 WORD16 c) {
448 WORD32 acc;
449
450 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
451
452 acc = ixheaacd_sub32_sat(a, acc);
453
454 return acc;
455 }
456
add32_shr(WORD32 a,WORD32 b)457 static PLATFORM_INLINE WORD32 add32_shr(WORD32 a, WORD32 b) {
458 WORD32 sum;
459
460 a = ixheaacd_shr32(a, 1);
461 b = ixheaacd_shr32(b, 1);
462
463 sum = ixheaacd_add32(a, b);
464
465 return sum;
466 }
467
sub32_shr(WORD32 a,WORD32 b)468 static PLATFORM_INLINE WORD32 sub32_shr(WORD32 a, WORD32 b) {
469 WORD32 diff;
470
471 a = ixheaacd_shr32(a, 1);
472 b = ixheaacd_shr32(b, 1);
473
474 diff = ixheaacd_sub32(a, b);
475
476 return diff;
477 }
478 #endif
479