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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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