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