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;
69 if (a > (MAX_32 >> b))
70 out_val = MAX_32;
71 else if (a < (MIN_32 >> b))
72 out_val = MIN_32;
73 else
74 out_val = a << b;
75 return (out_val);
76 }
77
ixheaacd_shl32_dir(WORD32 a,WORD b)78 static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir(WORD32 a, WORD b) {
79 WORD32 out_val;
80
81 if (b < 0) {
82 out_val = ixheaacd_shr32(a, -b);
83 } else {
84 out_val = ixheaacd_shl32(a, b);
85 }
86
87 return out_val;
88 }
89
ixheaacd_shl32_dir_sat(WORD32 a,WORD b)90 static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir_sat(WORD32 a, WORD b) {
91 WORD32 out_val;
92
93 if (b < 0) {
94 out_val = ixheaacd_shr32(a, -b);
95 } else {
96 out_val = ixheaacd_shl32_sat(a, b);
97 }
98
99 return out_val;
100 }
101
ixheaacd_shr32_dir(WORD32 a,WORD b)102 static PLATFORM_INLINE WORD32 ixheaacd_shr32_dir(WORD32 a, WORD b) {
103 WORD32 out_val;
104
105 if (b < 0) {
106 out_val = ixheaacd_shl32(a, -b);
107 } else {
108 out_val = ixheaacd_shr32(a, b);
109 }
110
111 return out_val;
112 }
113
shr32_dir_sat(WORD32 a,WORD b)114 static PLATFORM_INLINE WORD32 shr32_dir_sat(WORD32 a, WORD b) {
115 WORD32 out_val;
116
117 if (b < 0) {
118 out_val = ixheaacd_shl32_sat(a, -b);
119 } else {
120 out_val = ixheaacd_shr32(a, b);
121 }
122
123 return out_val;
124 }
125
ixheaacd_mult16x16in32(WORD16 a,WORD16 b)126 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32(WORD16 a, WORD16 b) {
127 WORD32 product;
128
129 product = (WORD32)a * (WORD32)b;
130
131 return product;
132 }
133
mult16x16in32_32(WORD32 a,WORD32 b)134 static PLATFORM_INLINE WORD32 mult16x16in32_32(WORD32 a, WORD32 b) {
135 WORD32 product;
136
137 product = (WORD32)a * (WORD32)b;
138
139 return product;
140 }
141
ixheaacd_mult16x16in32_shl(WORD16 a,WORD16 b)142 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl(WORD16 a, WORD16 b) {
143 WORD32 product;
144
145 product = ixheaacd_shl32(ixheaacd_mult16x16in32(a, b), 1);
146
147 return product;
148 }
149
ixheaacd_mult16x16in32_shl_sat(WORD16 a,WORD16 b)150 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl_sat(WORD16 a,
151 WORD16 b) {
152 WORD32 product;
153 product = (WORD32)a * (WORD32)b;
154 if (product != (WORD32)0x40000000L) {
155 product = ixheaacd_shl32(product, 1);
156 } else {
157 product = MAX_32;
158 }
159 return product;
160 }
161
ixheaacd_add32(WORD32 a,WORD32 b)162 static PLATFORM_INLINE WORD32 ixheaacd_add32(WORD32 a, WORD32 b) {
163 WORD32 sum;
164
165 sum = (WORD32)a + (WORD32)b;
166
167 return sum;
168 }
169
ixheaacd_sub32(WORD32 a,WORD32 b)170 static PLATFORM_INLINE WORD32 ixheaacd_sub32(WORD32 a, WORD32 b) {
171 WORD32 diff;
172
173 diff = (WORD32)a - (WORD32)b;
174
175 return diff;
176 }
177
ixheaacd_add32_sat(WORD32 a,WORD32 b)178 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat(WORD32 a, WORD32 b) {
179 WORD64 sum;
180
181 sum = (WORD64)a + (WORD64)b;
182
183 if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) == 0) {
184 if (((WORD32)sum ^ (WORD32)a) & (WORD32)MIN_32) {
185 sum = (a < 0) ? MIN_32 : MAX_32;
186 }
187 }
188
189 return (WORD32)sum;
190 }
191
ixheaacd_add32_sat3(WORD32 a,WORD32 b,WORD32 c)192 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b,
193 WORD32 c) {
194 WORD64 sum;
195
196 sum = (WORD64)a + (WORD64)b;
197
198 sum = (WORD64)sum + (WORD64)c;
199
200 if (sum > MAX_32) {
201 sum = MAX_32;
202 }
203 if (sum < MIN_32) {
204 sum = MIN_32;
205 }
206
207 return (WORD32)sum;
208 }
209
ixheaacd_sub32_sat(WORD32 a,WORD32 b)210 static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) {
211 WORD64 diff;
212
213 diff = (WORD64)a - (WORD64)b;
214
215 if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) != 0) {
216 if (((WORD32)diff ^ (WORD32)a) & (WORD32)MIN_32) {
217 diff = (a < 0L) ? MIN_32 : MAX_32;
218 }
219 }
220
221 return (WORD32)diff;
222 }
223
ixheaacd_norm32(WORD32 a)224 static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) {
225 WORD norm_val;
226
227 if (a == 0) {
228 norm_val = 31;
229 } else {
230 if (a == (WORD32)0xffffffffL) {
231 norm_val = 31;
232 } else {
233 if (a < 0) {
234 a = ~a;
235 }
236 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
237 a <<= 1;
238 }
239 }
240 }
241
242 return norm_val;
243 }
244
ixheaacd_pnorm32(WORD32 a)245 static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) {
246 WORD norm_val;
247
248 if (a == 0) {
249 norm_val = 31;
250 } else {
251 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
252 a <<= 1;
253 }
254 }
255
256 return norm_val;
257 }
258
bin_expo32(WORD32 a)259 static PLATFORM_INLINE WORD bin_expo32(WORD32 a) {
260 WORD bin_expo_val;
261
262 bin_expo_val = 31 - ixheaacd_norm32(a);
263
264 return bin_expo_val;
265 }
266
ixheaacd_abs32(WORD32 a)267 static PLATFORM_INLINE WORD32 ixheaacd_abs32(WORD32 a) {
268 WORD32 abs_val;
269
270 abs_val = a;
271
272 if (a < 0) {
273 abs_val = -a;
274 }
275
276 return abs_val;
277 }
278
ixheaacd_abs32_nrm(WORD32 a)279 static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(WORD32 a) {
280 WORD32 abs_val;
281
282 abs_val = a;
283
284 if (a < 0) {
285 abs_val = ~a;
286 }
287
288 return abs_val;
289 }
290
ixheaacd_abs32_sat(WORD32 a)291 static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) {
292 WORD32 abs_val;
293
294 abs_val = a;
295
296 if (a == MIN_32) {
297 abs_val = MAX_32;
298 } else if (a < 0) {
299 abs_val = -a;
300 }
301
302 return abs_val;
303 }
304
ixheaacd_negate32(WORD32 a)305 static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) {
306 WORD32 neg_val;
307
308 neg_val = -a;
309
310 return neg_val;
311 }
312
ixheaacd_negate32_sat(WORD32 a)313 static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) {
314 WORD32 neg_val;
315
316 if (a == MIN_32) {
317 neg_val = MAX_32;
318 } else {
319 neg_val = -a;
320 }
321 return neg_val;
322 }
323
div32(WORD32 a,WORD32 b,WORD * q_format)324 static PLATFORM_INLINE WORD32 div32(WORD32 a, WORD32 b, WORD *q_format) {
325 WORD32 quotient;
326 UWORD32 mantissa_nr, mantissa_dr;
327 WORD16 sign = 0;
328
329 LOOPINDEX i;
330 WORD q_nr, q_dr;
331
332 mantissa_nr = a;
333 mantissa_dr = b;
334 quotient = 0;
335
336 if ((a < 0) && (0 != b)) {
337 a = -a;
338 sign = (WORD16)(sign ^ -1);
339 }
340
341 if (b < 0) {
342 b = -b;
343 sign = (WORD16)(sign ^ -1);
344 }
345
346 if (0 == b) {
347 *q_format = 0;
348 return (a);
349 }
350
351 quotient = 0;
352
353 q_nr = ixheaacd_norm32(a);
354 mantissa_nr = (UWORD32)a << (q_nr);
355 q_dr = ixheaacd_norm32(b);
356 mantissa_dr = (UWORD32)b << (q_dr);
357 *q_format = (WORD)(30 + q_nr - q_dr);
358
359 for (i = 0; i < 31; i++) {
360 quotient = quotient << 1;
361
362 if (mantissa_nr >= mantissa_dr) {
363 mantissa_nr = mantissa_nr - mantissa_dr;
364 quotient += 1;
365 }
366
367 mantissa_nr = (UWORD32)mantissa_nr << 1;
368 }
369
370 if (sign < 0) {
371 quotient = -quotient;
372 }
373
374 return quotient;
375 }
376
ixheaacd_mac16x16in32_sat(WORD32 a,WORD16 b,WORD16 c)377 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_sat(WORD32 a, WORD16 b,
378 WORD16 c) {
379 WORD32 acc;
380
381 acc = ixheaacd_mult16x16in32(b, c);
382
383 acc = ixheaacd_add32_sat(a, acc);
384
385 return acc;
386 }
387
mac16x16hin32(WORD32 a,WORD32 b,WORD32 c)388 static PLATFORM_INLINE WORD32 mac16x16hin32(WORD32 a, WORD32 b, WORD32 c) {
389 WORD32 acc;
390
391 acc = ixheaacd_mult16x16in32((WORD16)b, (WORD16)(c >> 16));
392
393 acc = ixheaacd_add32(a, acc);
394
395 return acc;
396 }
397
ixheaacd_mac16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)398 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b,
399 WORD16 c) {
400 WORD32 acc;
401
402 acc = ixheaacd_mult16x16in32_shl(b, c);
403
404 acc = ixheaacd_add32(a, acc);
405
406 return acc;
407 }
408
ixheaacd_mac16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)409 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b,
410 WORD16 c) {
411 WORD32 acc;
412
413 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
414
415 acc = ixheaacd_add32_sat(a, acc);
416
417 return acc;
418 }
419
msu16x16in32(WORD32 a,WORD16 b,WORD16 c)420 static PLATFORM_INLINE WORD32 msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
421 WORD32 acc;
422
423 acc = ixheaacd_mult16x16in32(b, c);
424
425 acc = ixheaacd_sub32(a, acc);
426
427 return acc;
428 }
429
msu16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)430 static PLATFORM_INLINE WORD32 msu16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) {
431 WORD32 acc;
432
433 acc = ixheaacd_mult16x16in32_shl(b, c);
434
435 acc = ixheaacd_sub32(a, acc);
436
437 return acc;
438 }
439
msu16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)440 static PLATFORM_INLINE WORD32 msu16x16in32_shl_sat(WORD32 a, WORD16 b,
441 WORD16 c) {
442 WORD32 acc;
443
444 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
445
446 acc = ixheaacd_sub32_sat(a, acc);
447
448 return acc;
449 }
450
add32_shr(WORD32 a,WORD32 b)451 static PLATFORM_INLINE WORD32 add32_shr(WORD32 a, WORD32 b) {
452 WORD32 sum;
453
454 a = ixheaacd_shr32(a, 1);
455 b = ixheaacd_shr32(b, 1);
456
457 sum = ixheaacd_add32(a, b);
458
459 return sum;
460 }
461
sub32_shr(WORD32 a,WORD32 b)462 static PLATFORM_INLINE WORD32 sub32_shr(WORD32 a, WORD32 b) {
463 WORD32 diff;
464
465 a = ixheaacd_shr32(a, 1);
466 b = ixheaacd_shr32(b, 1);
467
468 diff = ixheaacd_sub32(a, b);
469
470 return diff;
471 }
472 #endif