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 (sum >= MAX_32) return MAX_32;
184 if (sum <= MIN_32) return MIN_32;
185
186 return (WORD32)sum;
187 }
188
ixheaacd_add32_sat3(WORD32 a,WORD32 b,WORD32 c)189 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b,
190 WORD32 c) {
191 WORD64 sum;
192
193 sum = (WORD64)a + (WORD64)b;
194
195 sum = (WORD64)sum + (WORD64)c;
196
197 if (sum > MAX_32) {
198 sum = MAX_32;
199 }
200 if (sum < MIN_32) {
201 sum = MIN_32;
202 }
203
204 return (WORD32)sum;
205 }
206
ixheaacd_sub32_sat(WORD32 a,WORD32 b)207 static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) {
208 WORD64 diff;
209
210 diff = (WORD64)a - (WORD64)b;
211
212 if (diff >= MAX_32) return MAX_32;
213 if (diff <= MIN_32) return MIN_32;
214
215 return (WORD32)diff;
216 }
217
ixheaacd_norm32(WORD32 a)218 static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) {
219 WORD norm_val;
220
221 if (a == 0) {
222 norm_val = 31;
223 } else {
224 if (a == (WORD32)0xffffffffL) {
225 norm_val = 31;
226 } else {
227 if (a < 0) {
228 a = ~a;
229 }
230 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
231 a <<= 1;
232 }
233 }
234 }
235
236 return norm_val;
237 }
238
ixheaacd_pnorm32(WORD32 a)239 static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) {
240 WORD norm_val;
241
242 if (a == 0) {
243 norm_val = 31;
244 } else {
245 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
246 a <<= 1;
247 }
248 }
249
250 return norm_val;
251 }
252
bin_expo32(WORD32 a)253 static PLATFORM_INLINE WORD bin_expo32(WORD32 a) {
254 WORD bin_expo_val;
255
256 bin_expo_val = 31 - ixheaacd_norm32(a);
257
258 return bin_expo_val;
259 }
260
ixheaacd_abs32(WORD32 a)261 static PLATFORM_INLINE WORD32 ixheaacd_abs32(WORD32 a) {
262 WORD32 abs_val;
263
264 abs_val = a;
265
266 if (a < 0) {
267 abs_val = -a;
268 }
269
270 return abs_val;
271 }
272
ixheaacd_abs32_nrm(WORD32 a)273 static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(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_sat(WORD32 a)285 static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) {
286 WORD32 abs_val;
287
288 abs_val = a;
289
290 if (a == MIN_32) {
291 abs_val = MAX_32;
292 } else if (a < 0) {
293 abs_val = -a;
294 }
295
296 return abs_val;
297 }
298
ixheaacd_negate32(WORD32 a)299 static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) {
300 WORD32 neg_val;
301
302 neg_val = -a;
303
304 return neg_val;
305 }
306
ixheaacd_negate32_sat(WORD32 a)307 static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) {
308 WORD32 neg_val;
309
310 if (a == MIN_32) {
311 neg_val = MAX_32;
312 } else {
313 neg_val = -a;
314 }
315 return neg_val;
316 }
317
div32(WORD32 a,WORD32 b,WORD * q_format)318 static PLATFORM_INLINE WORD32 div32(WORD32 a, WORD32 b, WORD *q_format) {
319 WORD32 quotient;
320 UWORD32 mantissa_nr, mantissa_dr;
321 WORD16 sign = 0;
322
323 LOOPINDEX i;
324 WORD q_nr, q_dr;
325
326 mantissa_nr = a;
327 mantissa_dr = b;
328 quotient = 0;
329
330 if ((a < 0) && (0 != b)) {
331 a = -a;
332 sign = (WORD16)(sign ^ -1);
333 }
334
335 if (b < 0) {
336 b = -b;
337 sign = (WORD16)(sign ^ -1);
338 }
339
340 if (0 == b) {
341 *q_format = 0;
342 return (a);
343 }
344
345 quotient = 0;
346
347 q_nr = ixheaacd_norm32(a);
348 mantissa_nr = (UWORD32)a << (q_nr);
349 q_dr = ixheaacd_norm32(b);
350 mantissa_dr = (UWORD32)b << (q_dr);
351 *q_format = (WORD)(30 + q_nr - q_dr);
352
353 for (i = 0; i < 31; i++) {
354 quotient = quotient << 1;
355
356 if (mantissa_nr >= mantissa_dr) {
357 mantissa_nr = mantissa_nr - mantissa_dr;
358 quotient += 1;
359 }
360
361 mantissa_nr = (UWORD32)mantissa_nr << 1;
362 }
363
364 if (sign < 0) {
365 quotient = -quotient;
366 }
367
368 return quotient;
369 }
370
ixheaacd_mac16x16in32_sat(WORD32 a,WORD16 b,WORD16 c)371 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_sat(WORD32 a, WORD16 b,
372 WORD16 c) {
373 WORD32 acc;
374
375 acc = ixheaacd_mult16x16in32(b, c);
376
377 acc = ixheaacd_add32_sat(a, acc);
378
379 return acc;
380 }
381
mac16x16hin32(WORD32 a,WORD32 b,WORD32 c)382 static PLATFORM_INLINE WORD32 mac16x16hin32(WORD32 a, WORD32 b, WORD32 c) {
383 WORD32 acc;
384
385 acc = ixheaacd_mult16x16in32((WORD16)b, (WORD16)(c >> 16));
386
387 acc = ixheaacd_add32(a, acc);
388
389 return acc;
390 }
391
ixheaacd_mac16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)392 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b,
393 WORD16 c) {
394 WORD32 acc;
395
396 acc = ixheaacd_mult16x16in32_shl(b, c);
397
398 acc = ixheaacd_add32(a, acc);
399
400 return acc;
401 }
402
ixheaacd_mac16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)403 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b,
404 WORD16 c) {
405 WORD32 acc;
406
407 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
408
409 acc = ixheaacd_add32_sat(a, acc);
410
411 return acc;
412 }
413
msu16x16in32(WORD32 a,WORD16 b,WORD16 c)414 static PLATFORM_INLINE WORD32 msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
415 WORD32 acc;
416
417 acc = ixheaacd_mult16x16in32(b, c);
418
419 acc = ixheaacd_sub32(a, acc);
420
421 return acc;
422 }
423
msu16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)424 static PLATFORM_INLINE WORD32 msu16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) {
425 WORD32 acc;
426
427 acc = ixheaacd_mult16x16in32_shl(b, c);
428
429 acc = ixheaacd_sub32(a, acc);
430
431 return acc;
432 }
433
msu16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)434 static PLATFORM_INLINE WORD32 msu16x16in32_shl_sat(WORD32 a, WORD16 b,
435 WORD16 c) {
436 WORD32 acc;
437
438 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
439
440 acc = ixheaacd_sub32_sat(a, acc);
441
442 return acc;
443 }
444
add32_shr(WORD32 a,WORD32 b)445 static PLATFORM_INLINE WORD32 add32_shr(WORD32 a, WORD32 b) {
446 WORD32 sum;
447
448 a = ixheaacd_shr32(a, 1);
449 b = ixheaacd_shr32(b, 1);
450
451 sum = ixheaacd_add32(a, b);
452
453 return sum;
454 }
455
sub32_shr(WORD32 a,WORD32 b)456 static PLATFORM_INLINE WORD32 sub32_shr(WORD32 a, WORD32 b) {
457 WORD32 diff;
458
459 a = ixheaacd_shr32(a, 1);
460 b = ixheaacd_shr32(b, 1);
461
462 diff = ixheaacd_sub32(a, b);
463
464 return diff;
465 }
466 #endif