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