1/* This is a software fixed-point library. 2 Copyright (C) 2007-2015 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 3, or (at your option) any later 9version. 10 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25/* This implements fixed-point arithmetic. 26 27 Contributed by Chao-ying Fu <fu@mips.com>. */ 28 29/* To use this file, we need to define one of the following: 30 QQ_MODE, UQQ_MODE, HQ_MODE, UHQ_MODE, SQ_MODE, USQ_MODE, DQ_MODE, UDQ_MODE, 31 TQ_MODE, UTQ_MODE, HA_MODE, UHA_MODE, SA_MODE, USA_MODE, DA_MODE, UDA_MODE, 32 TA_MODE, UTA_MODE. 33 Then, all operators for this machine mode will be created. 34 35 Or, we need to define FROM_* TO_* for conversions from one mode to another 36 mode. The mode could be one of the following: 37 Fract: QQ, UQQ, HQ, UHQ, SQ, USQ, DQ, UDQ, TQ, UTQ 38 Accum: HA, UHA, SA, USA, DA, UDA, TA, UTA 39 Signed integer: QI, HI, SI, DI, TI 40 Unsigned integer: UQI, UHI, USI, UDI, UTI 41 Floating-point: SF, DF 42 Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is 43 generated. */ 44 45#include "tconfig.h" 46#include "tsystem.h" 47#include "coretypes.h" 48#include "tm.h" 49#include "libgcc_tm.h" 50 51#ifndef MIN_UNITS_PER_WORD 52#define MIN_UNITS_PER_WORD UNITS_PER_WORD 53#endif 54 55#include "fixed-bit.h" 56 57#if defined(FIXED_ADD) && defined(L_add) 58FIXED_C_TYPE 59FIXED_ADD (FIXED_C_TYPE a, FIXED_C_TYPE b) 60{ 61 FIXED_C_TYPE c; 62 INT_C_TYPE x, y, z; 63 memcpy (&x, &a, FIXED_SIZE); 64 memcpy (&y, &b, FIXED_SIZE); 65 z = x + y; 66#if HAVE_PADDING_BITS 67 z = z << PADDING_BITS; 68 z = z >> PADDING_BITS; 69#endif 70 memcpy (&c, &z, FIXED_SIZE); 71 return c; 72} 73#endif /* FIXED_ADD */ 74 75#if defined(FIXED_SSADD) && defined(L_ssadd) 76FIXED_C_TYPE 77FIXED_SSADD (FIXED_C_TYPE a, FIXED_C_TYPE b) 78{ 79 FIXED_C_TYPE c; 80 INT_C_TYPE x, y, z; 81 memcpy (&x, &a, FIXED_SIZE); 82 memcpy (&y, &b, FIXED_SIZE); 83 z = x + (UINT_C_TYPE) y; 84 if ((((x ^ y) >> I_F_BITS) & 1) == 0) 85 { 86 if (((z ^ x) >> I_F_BITS) & 1) 87 { 88 z = ((UINT_C_TYPE) 1) << I_F_BITS; 89 if (x >= 0) 90 z -= (UINT_C_TYPE) 1; 91 } 92 } 93#if HAVE_PADDING_BITS 94 z = z << PADDING_BITS; 95 z = z >> PADDING_BITS; 96#endif 97 memcpy (&c, &z, FIXED_SIZE); 98 return c; 99} 100#endif /* FIXED_SSADD */ 101 102#if defined(FIXED_USADD) && defined(L_usadd) 103FIXED_C_TYPE 104FIXED_USADD (FIXED_C_TYPE a, FIXED_C_TYPE b) 105{ 106 FIXED_C_TYPE c; 107 INT_C_TYPE x, y, z; 108 memcpy (&x, &a, FIXED_SIZE); 109 memcpy (&y, &b, FIXED_SIZE); 110 z = x + y; 111#if HAVE_PADDING_BITS 112 z = z << PADDING_BITS; 113 z = z >> PADDING_BITS; 114#endif 115 if (z < x || z < y) /* max */ 116 { 117 z = -1; 118#if HAVE_PADDING_BITS 119 z = z << PADDING_BITS; 120 z = z >> PADDING_BITS; 121#endif 122 } 123 memcpy (&c, &z, FIXED_SIZE); 124 return c; 125} 126#endif /* FIXED_USADD */ 127 128#if defined(FIXED_SUB) && defined(L_sub) 129FIXED_C_TYPE 130FIXED_SUB (FIXED_C_TYPE a, FIXED_C_TYPE b) 131{ 132 FIXED_C_TYPE c; 133 INT_C_TYPE x, y, z; 134 memcpy (&x, &a, FIXED_SIZE); 135 memcpy (&y, &b, FIXED_SIZE); 136 z = x - y; 137#if HAVE_PADDING_BITS 138 z = z << PADDING_BITS; 139 z = z >> PADDING_BITS; 140#endif 141 memcpy (&c, &z, FIXED_SIZE); 142 return c; 143} 144#endif /* FIXED_SUB */ 145 146#if defined(FIXED_SSSUB) && defined(L_sssub) 147FIXED_C_TYPE 148FIXED_SSSUB (FIXED_C_TYPE a, FIXED_C_TYPE b) 149{ 150 FIXED_C_TYPE c; 151 INT_C_TYPE x, y, z; 152 memcpy (&x, &a, FIXED_SIZE); 153 memcpy (&y, &b, FIXED_SIZE); 154 z = x - (UINT_C_TYPE) y; 155 if (((x ^ y) >> I_F_BITS) & 1) 156 { 157 if (((z ^ x) >> I_F_BITS) & 1) 158 { 159 z = ((UINT_C_TYPE) 1) << I_F_BITS; 160 if (x >= 0) 161 z -= (UINT_C_TYPE) 1; 162 } 163 } 164#if HAVE_PADDING_BITS 165 z = z << PADDING_BITS; 166 z = z >> PADDING_BITS; 167#endif 168 memcpy (&c, &z, FIXED_SIZE); 169 return c; 170} 171#endif /* FIXED_SSSUB */ 172 173#if defined(FIXED_USSUB) && defined(L_ussub) 174FIXED_C_TYPE 175FIXED_USSUB (FIXED_C_TYPE a, FIXED_C_TYPE b) 176{ 177 FIXED_C_TYPE c; 178 INT_C_TYPE x, y, z; 179 memcpy (&x, &a, FIXED_SIZE); 180 memcpy (&y, &b, FIXED_SIZE); 181 z = x - y; 182 if (x < y) 183 z = 0; 184#if HAVE_PADDING_BITS 185 z = z << PADDING_BITS; 186 z = z >> PADDING_BITS; 187#endif 188 memcpy (&c, &z, FIXED_SIZE); 189 return c; 190} 191#endif /* FIXED_USSUB */ 192 193#if defined(FIXED_SATURATE1) && defined(L_saturate1) 194void 195FIXED_SATURATE1 (DINT_C_TYPE *a) 196{ 197 DINT_C_TYPE max, min; 198 max = (DINT_C_TYPE)1 << I_F_BITS; 199 max = max - 1; 200#if MODE_UNSIGNED == 0 201 min = (DINT_C_TYPE)1 << (2 * FIXED_WIDTH - 1); 202 min = min >> (2 * FIXED_WIDTH - 1 - I_F_BITS); 203#else 204 min = 0; 205#endif 206 if (*a > max) 207 *a = max; 208 else if (*a < min) 209 *a = min; 210} 211#endif /* FIXED_SATURATE1 */ 212 213#if defined(FIXED_SATURATE2) && defined(L_saturate2) 214void 215FIXED_SATURATE2 (INT_C_TYPE *high, INT_C_TYPE *low) 216{ 217 INT_C_TYPE r_max, s_max, r_min, s_min; 218 r_max = 0; 219#if (MODE_UNSIGNED == 0) || HAVE_PADDING_BITS 220 s_max = (INT_C_TYPE)1 << I_F_BITS; 221 s_max = s_max - 1; 222#else 223 s_max = -1; 224#endif 225#if MODE_UNSIGNED == 0 226 r_min = -1; 227 s_min = (INT_C_TYPE)1 << (FIXED_WIDTH - 1); 228 s_min = s_min >> (FIXED_WIDTH - 1 - I_F_BITS); 229#else 230 r_min = 0; 231 s_min = 0; 232#endif 233 234 if (*high > r_max 235 || (*high == r_max && (UINT_C_TYPE)(*low) > (UINT_C_TYPE)s_max)) 236 { 237 *high = r_max; 238 *low = s_max; 239 } 240 else if (*high < r_min || 241 (*high == r_min && (UINT_C_TYPE)(*low) < (UINT_C_TYPE)s_min)) 242 { 243 *high = r_min; 244 *low = s_min; 245 } 246} 247#endif /* FIXED_SATURATE2 */ 248 249#if defined(FIXED_MULHELPER) && defined(L_mulhelper) 250FIXED_C_TYPE 251FIXED_MULHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp) 252{ 253 FIXED_C_TYPE c; 254 INT_C_TYPE x, y; 255 256#if defined (DINT_C_TYPE) 257 INT_C_TYPE z; 258 DINT_C_TYPE dx, dy, dz; 259 memcpy (&x, &a, FIXED_SIZE); 260 memcpy (&y, &b, FIXED_SIZE); 261 dx = (DINT_C_TYPE) x; 262 dy = (DINT_C_TYPE) y; 263 dz = dx * dy; 264 /* Round the result by adding (1 << (FBITS -1)). */ 265 dz += ((DINT_C_TYPE) 1 << (FBITS - 1)); 266 dz = dz >> FBITS; 267 if (satp) 268 FIXED_SATURATE1 (&dz); 269 270 z = (INT_C_TYPE) dz; 271#if HAVE_PADDING_BITS 272 z = z << PADDING_BITS; 273 z = z >> PADDING_BITS; 274#endif 275 memcpy (&c, &z, FIXED_SIZE); 276 return c; 277 278#else /* No DINT_C_TYPE */ 279 /* The result of multiplication expands to two INT_C_TYPE. */ 280 INTunion aa, bb; 281 INTunion a_high, a_low, b_high, b_low; 282 INTunion high_high, high_low, low_high, low_low; 283 INTunion r, s, temp1, temp2; 284 INT_C_TYPE carry = 0; 285 INT_C_TYPE z; 286 287 memcpy (&x, &a, FIXED_SIZE); 288 memcpy (&y, &b, FIXED_SIZE); 289 290 /* Decompose a and b. */ 291 aa.ll = x; 292 bb.ll = y; 293 294 a_high.s.low = aa.s.high; 295 a_high.s.high = 0; 296 a_low.s.low = aa.s.low; 297 a_low.s.high = 0; 298 b_high.s.low = bb.s.high; 299 b_high.s.high = 0; 300 b_low.s.low = bb.s.low; 301 b_low.s.high = 0; 302 303 /* Perform four multiplications. */ 304 low_low.ll = a_low.ll * b_low.ll; 305 low_high.ll = a_low.ll * b_high.ll; 306 high_low.ll = a_high.ll * b_low.ll; 307 high_high.ll = a_high.ll * b_high.ll; 308 309 /* Accumulate four results to {r, s}. */ 310 temp1.s.high = high_low.s.low; 311 temp1.s.low = 0; 312 s.ll = low_low.ll + temp1.ll; 313 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) low_low.ll 314 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll) 315 carry ++; /* Carry. */ 316 temp1.ll = s.ll; 317 temp2.s.high = low_high.s.low; 318 temp2.s.low = 0; 319 s.ll = temp1.ll + temp2.ll; 320 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll 321 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp2.ll) 322 carry ++; /* Carry. */ 323 324 temp1.s.low = high_low.s.high; 325 temp1.s.high = 0; 326 r.ll = high_high.ll + temp1.ll; 327 temp1.s.low = low_high.s.high; 328 temp1.s.high = 0; 329 r.ll = r.ll + temp1.ll + carry; 330 331#if MODE_UNSIGNED == 0 332 /* For signed types, we need to add neg(y) to r, if x < 0. */ 333 if (x < 0) 334 r.ll = r.ll - y; 335 /* We need to add neg(x) to r, if y < 0. */ 336 if (y < 0) 337 r.ll = r.ll - x; 338#endif 339 340 /* Round the result by adding (1 << (FBITS -1)). */ 341 temp1.ll = s.ll; 342 s.ll += ((INT_C_TYPE) 1 << (FBITS -1)); 343 if ((UINT_C_TYPE) s.ll < (UINT_C_TYPE) temp1.ll 344 || (UINT_C_TYPE) s.ll < (UINT_C_TYPE) ((INT_C_TYPE) 1 << (FBITS -1))) 345 r.ll += 1; 346 347 /* Shift right the result by FBITS. */ 348#if FBITS == FIXED_WIDTH 349 /* This happens only for unsigned types without any padding bits. 350 So, it is safe to set r.ll to 0 as it is logically shifted right. */ 351 s.ll = r.ll; 352 r.ll = 0; 353#else 354 s.ll = ((UINT_C_TYPE)s.ll) >> FBITS; 355 temp1.ll = r.ll << (FIXED_WIDTH - FBITS); 356 s.ll = s.ll | temp1.ll; 357 r.ll = r.ll >> FBITS; 358#endif 359 360 if (satp) 361 FIXED_SATURATE2 (&r.ll, &s.ll); 362 363 z = (INT_C_TYPE) s.ll; 364#if HAVE_PADDING_BITS 365 z = z << PADDING_BITS; 366 z = z >> PADDING_BITS; 367#endif 368 memcpy (&c, &z, FIXED_SIZE); 369 return c; 370#endif 371} 372#endif /* FIXED_MULHELPER */ 373 374#if defined(FIXED_MUL) && defined(L_mul) 375FIXED_C_TYPE 376FIXED_MUL (FIXED_C_TYPE a, FIXED_C_TYPE b) 377{ 378 return FIXED_MULHELPER (a, b, 0); 379} 380#endif /* FIXED_MUL */ 381 382#if defined(FIXED_SSMUL) && defined(L_ssmul) 383FIXED_C_TYPE 384FIXED_SSMUL (FIXED_C_TYPE a, FIXED_C_TYPE b) 385{ 386 return FIXED_MULHELPER (a, b, 1); 387} 388#endif /* FIXED_SSMUL */ 389 390#if defined(FIXED_USMUL) && defined(L_usmul) 391FIXED_C_TYPE 392FIXED_USMUL (FIXED_C_TYPE a, FIXED_C_TYPE b) 393{ 394 return FIXED_MULHELPER (a, b, 1); 395} 396#endif /* FIXED_USMUL */ 397 398#if defined(FIXED_DIVHELPER) && defined(L_divhelper) 399FIXED_C_TYPE 400FIXED_DIVHELPER (FIXED_C_TYPE a, FIXED_C_TYPE b, word_type satp) 401{ 402 FIXED_C_TYPE c; 403 INT_C_TYPE x, y; 404 INT_C_TYPE z; 405 406#if defined (DINT_C_TYPE) 407 DINT_C_TYPE dx, dy, dz; 408 memcpy (&x, &a, FIXED_SIZE); 409 memcpy (&y, &b, FIXED_SIZE); 410 dx = (DINT_C_TYPE) x; 411 dy = (DINT_C_TYPE) y; 412 dx = dx << FBITS; 413 dz = dx / dy; 414 if (satp) 415 FIXED_SATURATE1 (&dz); 416 z = (INT_C_TYPE) dz; 417#if HAVE_PADDING_BITS 418 z = z << PADDING_BITS; 419 z = z >> PADDING_BITS; 420#endif 421 memcpy (&c, &z, FIXED_SIZE); 422 return c; 423 424#else /* No DINT_C_TYPE */ 425 INT_C_TYPE pos_a, pos_b, r, s; 426 INT_C_TYPE quo_r, quo_s, mod, temp; 427 word_type i; 428#if MODE_UNSIGNED == 0 429 word_type num_of_neg = 0; 430#endif 431 432 memcpy (&x, &a, FIXED_SIZE); 433 memcpy (&y, &b, FIXED_SIZE); 434 pos_a = x; 435 pos_b = y; 436 437#if MODE_UNSIGNED == 0 438 /* If a < 0, negate a. */ 439 if (pos_a < 0) 440 { 441 pos_a = -pos_a; 442 num_of_neg ++; 443 } 444 /* If b < 0, negate b. */ 445 if (pos_b < 0) 446 { 447 pos_b = -pos_b; 448 num_of_neg ++; 449 } 450#endif 451 452 /* Left shift pos_a to {r, s} by FBITS. */ 453#if FBITS == FIXED_WIDTH 454 /* This happens only for unsigned types without any padding bits. */ 455 r = pos_a; 456 s = 0; 457#else 458 s = pos_a << FBITS; 459 r = pos_a >> (FIXED_WIDTH - FBITS); 460#endif 461 462 /* Unsigned divide r by pos_b to quo_r. The remainder is in mod. */ 463 quo_r = (UINT_C_TYPE)r / (UINT_C_TYPE)pos_b; 464 mod = (UINT_C_TYPE)r % (UINT_C_TYPE)pos_b; 465 quo_s = 0; 466 467 for (i = 0; i < FIXED_WIDTH; i++) 468 { 469 /* Record the leftmost bit of mod. */ 470 word_type leftmost_mode = (mod >> (FIXED_WIDTH - 1)) & 1; 471 /* Shift left mod by 1 bit. */ 472 mod = mod << 1; 473 /* Test the leftmost bit of s to add to mod. */ 474 if ((s >> (FIXED_WIDTH - 1)) & 1) 475 mod ++; 476 /* Shift left quo_s by 1 bit. */ 477 quo_s = quo_s << 1; 478 /* Try to calculate (mod - pos_b). */ 479 temp = mod - pos_b; 480 if (leftmost_mode || (UINT_C_TYPE)mod >= (UINT_C_TYPE)pos_b) 481 { 482 quo_s ++; 483 mod = temp; 484 } 485 /* Shift left s by 1 bit. */ 486 s = s << 1; 487 } 488 489#if MODE_UNSIGNED == 0 490 if (num_of_neg == 1) 491 { 492 quo_s = -quo_s; 493 if (quo_s == 0) 494 quo_r = -quo_r; 495 else 496 quo_r = ~quo_r; 497 } 498#endif 499 if (satp) 500 FIXED_SATURATE2 (&quo_r, &quo_s); 501 z = quo_s; 502#if HAVE_PADDING_BITS 503 z = z << PADDING_BITS; 504 z = z >> PADDING_BITS; 505#endif 506 memcpy (&c, &z, FIXED_SIZE); 507 return c; 508#endif 509} 510#endif /* FIXED_DIVHELPER */ 511 512#if defined(FIXED_DIV) && defined(L_div) 513FIXED_C_TYPE 514FIXED_DIV (FIXED_C_TYPE a, FIXED_C_TYPE b) 515{ 516 return FIXED_DIVHELPER (a, b, 0); 517} 518#endif /* FIXED_DIV */ 519 520 521#if defined(FIXED_UDIV) && defined(L_udiv) 522FIXED_C_TYPE 523FIXED_UDIV (FIXED_C_TYPE a, FIXED_C_TYPE b) 524{ 525 return FIXED_DIVHELPER (a, b, 0); 526} 527#endif /* FIXED_UDIV */ 528 529#if defined(FIXED_SSDIV) && defined(L_ssdiv) 530FIXED_C_TYPE 531FIXED_SSDIV (FIXED_C_TYPE a, FIXED_C_TYPE b) 532{ 533 return FIXED_DIVHELPER (a, b, 1); 534} 535#endif /* FIXED_SSDIV */ 536 537#if defined(FIXED_USDIV) && defined(L_usdiv) 538FIXED_C_TYPE 539FIXED_USDIV (FIXED_C_TYPE a, FIXED_C_TYPE b) 540{ 541 return FIXED_DIVHELPER (a, b, 1); 542} 543#endif /* FIXED_USDIV */ 544 545#if defined(FIXED_NEG) && defined(L_neg) 546FIXED_C_TYPE 547FIXED_NEG (FIXED_C_TYPE a) 548{ 549 FIXED_C_TYPE c; 550 INT_C_TYPE x, z; 551 memcpy (&x, &a, FIXED_SIZE); 552 z = -x; 553#if HAVE_PADDING_BITS 554 z = z << PADDING_BITS; 555 z = z >> PADDING_BITS; 556#endif 557 memcpy (&c, &z, FIXED_SIZE); 558 return c; 559} 560#endif /* FIXED_NEG */ 561 562#if defined(FIXED_SSNEG) && defined(L_ssneg) 563FIXED_C_TYPE 564FIXED_SSNEG (FIXED_C_TYPE a) 565{ 566 FIXED_C_TYPE c; 567 INT_C_TYPE x, y, z; 568 memcpy (&y, &a, FIXED_SIZE); 569 x = 0; 570 z = x - (UINT_C_TYPE) y; 571 if (((x ^ y) >> I_F_BITS) & 1) 572 { 573 if (((z ^ x) >> I_F_BITS) & 1) 574 z = (((UINT_C_TYPE) 1) << I_F_BITS) - 1; 575 } 576#if HAVE_PADDING_BITS 577 z = z << PADDING_BITS; 578 z = z >> PADDING_BITS; 579#endif 580 memcpy (&c, &z, FIXED_SIZE); 581 return c; 582} 583#endif /* FIXED_SSNEG */ 584 585#if defined(FIXED_USNEG) && defined(L_usneg) 586FIXED_C_TYPE 587FIXED_USNEG (FIXED_C_TYPE a __attribute__ ((__unused__))) 588{ 589 FIXED_C_TYPE c; 590 INT_C_TYPE z; 591 z = 0; 592 memcpy (&c, &z, FIXED_SIZE); 593 return c; 594} 595#endif /* FIXED_USNEG */ 596 597#if defined(FIXED_ASHLHELPER) && defined(L_ashlhelper) 598FIXED_C_TYPE 599FIXED_ASHLHELPER (FIXED_C_TYPE a, word_type b, word_type satp) 600{ 601 FIXED_C_TYPE c; 602 INT_C_TYPE x, z; 603 604#if defined (DINT_C_TYPE) 605 DINT_C_TYPE dx, dz; 606 memcpy (&x, &a, FIXED_SIZE); 607 dx = (DINT_C_TYPE) x; 608 if (b >= FIXED_WIDTH) 609 dz = dx << FIXED_WIDTH; 610 else 611 dz = dx << b; 612 if (satp) 613 FIXED_SATURATE1 (&dz); 614 z = (INT_C_TYPE) dz; 615#if HAVE_PADDING_BITS 616 z = z << PADDING_BITS; 617 z = z >> PADDING_BITS; 618#endif 619 memcpy (&c, &z, FIXED_SIZE); 620 return c; 621 622#else /* No DINT_C_TYPE */ 623 INT_C_TYPE r, s; 624 memcpy (&x, &a, FIXED_SIZE); 625 /* We need to shift left x by b bits to {r, s}. */ 626 if (b >= FIXED_WIDTH) 627 { 628 r = b; 629 s = 0; 630 } 631 else 632 { 633 s = x << b; 634 r = x >> (FIXED_WIDTH - b); 635 } 636 if (satp) 637 FIXED_SATURATE2 (&r, &s); 638 z = s; 639#if HAVE_PADDING_BITS 640 z = z << PADDING_BITS; 641 z = z >> PADDING_BITS; 642#endif 643 memcpy (&c, &z, FIXED_SIZE); 644 return c; 645#endif 646} 647#endif /* FIXED_ASHLHELPER */ 648 649#if defined(FIXED_ASHL) && defined(L_ashl) 650FIXED_C_TYPE 651FIXED_ASHL (FIXED_C_TYPE a, word_type b) 652{ 653 return FIXED_ASHLHELPER (a, b, 0); 654} 655#endif /* FIXED_ASHL */ 656 657#if defined(FIXED_ASHR) && defined(L_ashr) 658FIXED_C_TYPE 659FIXED_ASHR (FIXED_C_TYPE a, word_type b) 660{ 661 FIXED_C_TYPE c; 662 INT_C_TYPE x, z; 663 memcpy (&x, &a, FIXED_SIZE); 664 z = x >> b; 665#if HAVE_PADDING_BITS 666 z = z << PADDING_BITS; 667 z = z >> PADDING_BITS; 668#endif 669 memcpy (&c, &z, FIXED_SIZE); 670 return c; 671} 672#endif /* FIXED_ASHR */ 673 674#if defined(FIXED_LSHR) && defined(L_lshr) 675FIXED_C_TYPE 676FIXED_LSHR (FIXED_C_TYPE a, word_type b) 677{ 678 FIXED_C_TYPE c; 679 INT_C_TYPE x, z; 680 memcpy (&x, &a, FIXED_SIZE); 681 z = x >> b; 682#if HAVE_PADDING_BITS 683 z = z << PADDING_BITS; 684 z = z >> PADDING_BITS; 685#endif 686 memcpy (&c, &z, FIXED_SIZE); 687 return c; 688} 689#endif /* FIXED_LSHR */ 690 691#if defined(FIXED_SSASHL) && defined(L_ssashl) 692FIXED_C_TYPE 693FIXED_SSASHL (FIXED_C_TYPE a, word_type b) 694{ 695 return FIXED_ASHLHELPER (a, b, 1); 696} 697#endif /* FIXED_SSASHL */ 698 699#if defined(FIXED_USASHL) && defined(L_usashl) 700FIXED_C_TYPE 701FIXED_USASHL (FIXED_C_TYPE a, word_type b) 702{ 703 return FIXED_ASHLHELPER (a, b, 1); 704} 705#endif /* FIXED_USASHL */ 706 707#if defined(FIXED_CMP) && defined(L_cmp) 708word_type 709FIXED_CMP (FIXED_C_TYPE a, FIXED_C_TYPE b) 710{ 711 INT_C_TYPE x, y; 712 memcpy (&x, &a, FIXED_SIZE); 713 memcpy (&y, &b, FIXED_SIZE); 714 715 if (x < y) 716 return 0; 717 else if (x > y) 718 return 2; 719 720 return 1; 721} 722#endif /* FIXED_CMP */ 723 724/* Fixed -> Fixed. */ 725#if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 4 726TO_FIXED_C_TYPE 727FRACT (FROM_FIXED_C_TYPE a) 728{ 729 TO_FIXED_C_TYPE c; 730 FROM_INT_C_TYPE x; 731 TO_INT_C_TYPE z; 732 int shift_amount; 733 memcpy (&x, &a, FROM_FIXED_SIZE); 734#if TO_FBITS > FROM_FBITS /* Need left shift. */ 735 shift_amount = TO_FBITS - FROM_FBITS; 736 z = (TO_INT_C_TYPE) x; 737 z = z << shift_amount; 738#else /* TO_FBITS <= FROM_FBITS. Need right Shift. */ 739 shift_amount = FROM_FBITS - TO_FBITS; 740 x = x >> shift_amount; 741 z = (TO_INT_C_TYPE) x; 742#endif /* TO_FBITS > FROM_FBITS */ 743 744#if TO_HAVE_PADDING_BITS 745 z = z << TO_PADDING_BITS; 746 z = z >> TO_PADDING_BITS; 747#endif 748 memcpy (&c, &z, TO_FIXED_SIZE); 749 return c; 750} 751#endif /* FRACT && FROM_TYPE == 4 && TO_TYPE == 4 */ 752 753/* Fixed -> Fixed with saturation. */ 754#if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 4 && TO_TYPE == 4 755TO_FIXED_C_TYPE 756SATFRACT (FROM_FIXED_C_TYPE a) 757{ 758 TO_FIXED_C_TYPE c; 759 TO_INT_C_TYPE z; 760 FROM_INT_C_TYPE x; 761#if FROM_MODE_UNSIGNED == 0 762 BIG_SINT_C_TYPE high, low; 763 BIG_SINT_C_TYPE max_high, max_low; 764#if TO_MODE_UNSIGNED == 0 765 BIG_SINT_C_TYPE min_high, min_low; 766#endif 767#else 768 BIG_UINT_C_TYPE high, low; 769 BIG_UINT_C_TYPE max_high, max_low; 770#endif 771#if TO_FBITS > FROM_FBITS 772 BIG_UINT_C_TYPE utemp; 773#endif 774#if TO_MODE_UNSIGNED == 0 775 BIG_SINT_C_TYPE stemp; 776#endif 777#if TO_FBITS != FROM_FBITS 778 int shift_amount; 779#endif 780 memcpy (&x, &a, FROM_FIXED_SIZE); 781 782 /* Step 1. We need to store x to {high, low}. */ 783#if FROM_MODE_UNSIGNED == 0 784 low = (BIG_SINT_C_TYPE) x; 785 if (x < 0) 786 high = -1; 787 else 788 high = 0; 789#else 790 low = (BIG_UINT_C_TYPE) x; 791 high = 0; 792#endif 793 794 /* Step 2. We need to shift {high, low}. */ 795#if TO_FBITS > FROM_FBITS /* Left shift. */ 796 shift_amount = TO_FBITS - FROM_FBITS; 797 utemp = (BIG_UINT_C_TYPE) low; 798 utemp = utemp >> (BIG_WIDTH - shift_amount); 799 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp; 800 low = low << shift_amount; 801#elif TO_FBITS < FROM_FBITS /* Right shift. */ 802 shift_amount = FROM_FBITS - TO_FBITS; 803 low = low >> shift_amount; 804#endif 805 806 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */ 807 max_high = 0; 808#if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS 809 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS; 810 max_low = max_low - 1; 811#else 812 max_low = -1; 813#endif 814 815#if TO_MODE_UNSIGNED == 0 816 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1); 817 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS); 818#if FROM_MODE_UNSIGNED == 0 819 min_high = -1; 820 min_low = stemp; 821#endif 822#endif 823 824#if FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 0 825 /* Signed -> Signed. */ 826 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high 827 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high 828 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 829 low = max_low; /* Maximum. */ 830 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high 831 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high 832 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low)) 833 low = min_low; /* Minimum. */ 834#elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 1 835 /* Unigned -> Unsigned. */ 836 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high 837 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high 838 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 839 low = max_low; /* Maximum. */ 840#elif FROM_MODE_UNSIGNED == 0 && TO_MODE_UNSIGNED == 1 841 /* Signed -> Unsigned. */ 842 if (x < 0) 843 low = 0; /* Minimum. */ 844 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high 845 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high 846 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 847 low = max_low; /* Maximum. */ 848#elif FROM_MODE_UNSIGNED == 1 && TO_MODE_UNSIGNED == 0 849 /* Unsigned -> Signed. */ 850 if ((BIG_SINT_C_TYPE) high < 0) 851 low = max_low; /* Maximum. */ 852 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high 853 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high 854 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 855 low = max_low; /* Maximum. */ 856#endif 857 858 /* Step 4. Store the result. */ 859 z = (TO_INT_C_TYPE) low; 860#if TO_HAVE_PADDING_BITS 861 z = z << TO_PADDING_BITS; 862 z = z >> TO_PADDING_BITS; 863#endif 864 memcpy (&c, &z, TO_FIXED_SIZE); 865 return c; 866} 867#endif /* defined(SATFRACT) && FROM_TYPE == 4 && TO_TYPE == 4 */ 868 869/* Fixed -> Int. */ 870#if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 1 871TO_INT_C_TYPE 872FRACT (FROM_FIXED_C_TYPE a) 873{ 874 FROM_INT_C_TYPE x; 875 TO_INT_C_TYPE z; 876 FROM_INT_C_TYPE i = 0; 877 memcpy (&x, &a, FROM_FIXED_SIZE); 878 879#if FROM_MODE_UNSIGNED == 0 880 if (x < 0) 881 { 882#if FROM_FIXED_WIDTH == FROM_FBITS 883 if (x != 0) 884 i = 1; 885#else 886 if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0) 887 i = 1; 888#endif 889 } 890#endif 891 892#if FROM_FIXED_WIDTH == FROM_FBITS 893 x = 0; 894#else 895 x = x >> FROM_FBITS; 896#endif 897 x = x + i; 898 z = (TO_INT_C_TYPE) x; 899 return z; 900} 901#endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 1 */ 902 903/* Fixed -> Unsigned int. */ 904#if defined(FRACTUNS) && defined(L_fractuns) && FROM_TYPE == 4 && TO_TYPE == 2 905TO_INT_C_TYPE 906FRACTUNS (FROM_FIXED_C_TYPE a) 907{ 908 FROM_INT_C_TYPE x; 909 TO_INT_C_TYPE z; 910 FROM_INT_C_TYPE i = 0; 911 memcpy (&x, &a, FROM_FIXED_SIZE); 912 913#if FROM_MODE_UNSIGNED == 0 914 if (x < 0) 915 { 916#if FROM_FIXED_WIDTH == FROM_FBITS 917 if (x != 0) 918 i = 1; 919#else 920 if (((FROM_INT_C_TYPE)(x << (FROM_FIXED_WIDTH - FROM_FBITS))) != 0) 921 i = 1; 922#endif 923 } 924#endif 925 926#if FROM_FIXED_WIDTH == FROM_FBITS 927 x = 0; 928#else 929 x = x >> FROM_FBITS; 930#endif 931 x = x + i; 932 z = (TO_INT_C_TYPE) x; 933 return z; 934} 935#endif /* defined(FRACTUNS) && FROM_TYPE == 4 && TO_TYPE == 2 */ 936 937/* Int -> Fixed. */ 938#if defined(FRACT) && defined(L_fract) && FROM_TYPE == 1 && TO_TYPE == 4 939TO_FIXED_C_TYPE 940FRACT (FROM_INT_C_TYPE a) 941{ 942 TO_FIXED_C_TYPE c; 943 TO_INT_C_TYPE z; 944 z = (TO_INT_C_TYPE) a; 945#if TO_FIXED_WIDTH == TO_FBITS 946 z = 0; 947#else 948 z = z << TO_FBITS; 949#endif 950#if TO_HAVE_PADDING_BITS 951 z = z << TO_PADDING_BITS; 952 z = z >> TO_PADDING_BITS; 953#endif 954 memcpy (&c, &z, TO_FIXED_SIZE); 955 return c; 956} 957#endif /* defined(FRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */ 958 959/* Signed int -> Fixed with saturation. */ 960#if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 1 && TO_TYPE == 4 961TO_FIXED_C_TYPE 962SATFRACT (FROM_INT_C_TYPE a) 963{ 964 TO_FIXED_C_TYPE c; 965 TO_INT_C_TYPE z; 966 FROM_INT_C_TYPE x = a; 967 BIG_SINT_C_TYPE high, low; 968 BIG_SINT_C_TYPE max_high, max_low; 969#if TO_MODE_UNSIGNED == 0 970 BIG_SINT_C_TYPE min_high, min_low; 971 BIG_SINT_C_TYPE stemp; 972#endif 973#if BIG_WIDTH != TO_FBITS 974 BIG_UINT_C_TYPE utemp; 975 int shift_amount; 976#endif 977 978 /* Step 1. We need to store x to {high, low}. */ 979 low = (BIG_SINT_C_TYPE) x; 980 if (x < 0) 981 high = -1; 982 else 983 high = 0; 984 985 /* Step 2. We need to left shift {high, low}. */ 986#if BIG_WIDTH == TO_FBITS 987 high = low; 988 low = 0; 989#else 990 shift_amount = TO_FBITS; 991 utemp = (BIG_UINT_C_TYPE) low; 992 utemp = utemp >> (BIG_WIDTH - shift_amount); 993 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp; 994 low = low << shift_amount; 995#endif 996 997 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */ 998 max_high = 0; 999#if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS 1000 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS; 1001 max_low = max_low - 1; 1002#else 1003 max_low = -1; 1004#endif 1005 1006#if TO_MODE_UNSIGNED == 0 1007 min_high = -1; 1008 stemp = (BIG_SINT_C_TYPE)1 << (BIG_WIDTH - 1); 1009 stemp = stemp >> (BIG_WIDTH - 1 - TO_I_F_BITS); 1010 min_low = stemp; 1011 1012 /* Signed -> Signed. */ 1013 if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high 1014 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high 1015 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 1016 low = max_low; /* Maximum. */ 1017 else if ((BIG_SINT_C_TYPE) high < (BIG_SINT_C_TYPE) min_high 1018 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) min_high 1019 && (BIG_UINT_C_TYPE) low < (BIG_UINT_C_TYPE) min_low)) 1020 low = min_low; /* Minimum. */ 1021#else 1022 /* Signed -> Unsigned. */ 1023 if (x < 0) 1024 low = 0; /* Minimum. */ 1025 else if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high 1026 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high 1027 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 1028 low = max_low; /* Maximum. */ 1029#endif 1030 1031 /* Step 4. Store the result. */ 1032 z = (TO_INT_C_TYPE) low; 1033#if TO_HAVE_PADDING_BITS 1034 z = z << TO_PADDING_BITS; 1035 z = z >> TO_PADDING_BITS; 1036#endif 1037 memcpy (&c, &z, TO_FIXED_SIZE); 1038 return c; 1039} 1040#endif /* defined(SATFRACT) && FROM_TYPE == 1 && TO_TYPE == 4 */ 1041 1042/* Unsigned int -> Fixed. */ 1043#if defined(FRACTUNS) && defined(L_fractuns) &&FROM_TYPE == 2 && TO_TYPE == 4 1044TO_FIXED_C_TYPE 1045FRACTUNS (FROM_INT_C_TYPE a) 1046{ 1047 TO_FIXED_C_TYPE c; 1048 TO_INT_C_TYPE z; 1049 z = (TO_INT_C_TYPE) a; 1050#if TO_FIXED_WIDTH == TO_FBITS 1051 z = 0; 1052#else 1053 z = z << TO_FBITS; 1054#endif 1055#if TO_HAVE_PADDING_BITS 1056 z = z << TO_PADDING_BITS; 1057 z = z >> TO_PADDING_BITS; 1058#endif 1059 memcpy (&c, &z, TO_FIXED_SIZE); 1060 return c; 1061} 1062#endif /* defined(FRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */ 1063 1064/* Unsigned int -> Fixed with saturation. */ 1065#if defined(SATFRACTUNS) && defined(L_satfractuns) && FROM_TYPE == 2 && TO_TYPE == 4 1066TO_FIXED_C_TYPE 1067SATFRACTUNS (FROM_INT_C_TYPE a) 1068{ 1069 TO_FIXED_C_TYPE c; 1070 TO_INT_C_TYPE z; 1071 FROM_INT_C_TYPE x = a; 1072 BIG_UINT_C_TYPE high, low; 1073 BIG_UINT_C_TYPE max_high, max_low; 1074#if BIG_WIDTH != TO_FBITS 1075 BIG_UINT_C_TYPE utemp; 1076 int shift_amount; 1077#endif 1078 1079 /* Step 1. We need to store x to {high, low}. */ 1080 low = (BIG_UINT_C_TYPE) x; 1081 high = 0; 1082 1083 /* Step 2. We need to left shift {high, low}. */ 1084#if BIG_WIDTH == TO_FBITS 1085 high = low; 1086 low = 0; 1087#else 1088 shift_amount = TO_FBITS; 1089 utemp = (BIG_UINT_C_TYPE) low; 1090 utemp = utemp >> (BIG_WIDTH - shift_amount); 1091 high = ((BIG_UINT_C_TYPE)(high << shift_amount)) | utemp; 1092 low = low << shift_amount; 1093#endif 1094 1095 /* Step 3. Compare {high, low} with max and min of TO_FIXED_C_TYPE. */ 1096 max_high = 0; 1097#if BIG_WIDTH > TO_FIXED_WIDTH || TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS 1098 max_low = (BIG_UINT_C_TYPE)1 << TO_I_F_BITS; 1099 max_low = max_low - 1; 1100#else 1101 max_low = -1; 1102#endif 1103 1104#if TO_MODE_UNSIGNED == 1 1105 /* Unigned -> Unsigned. */ 1106 if ((BIG_UINT_C_TYPE) high > (BIG_UINT_C_TYPE) max_high 1107 || ((BIG_UINT_C_TYPE) high == (BIG_UINT_C_TYPE) max_high 1108 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 1109 low = max_low; /* Maximum. */ 1110#else 1111 /* Unsigned -> Signed. */ 1112 if ((BIG_SINT_C_TYPE) high < 0) 1113 low = max_low; /* Maximum. */ 1114 else if ((BIG_SINT_C_TYPE) high > (BIG_SINT_C_TYPE) max_high 1115 || ((BIG_SINT_C_TYPE) high == (BIG_SINT_C_TYPE) max_high 1116 && (BIG_UINT_C_TYPE) low > (BIG_UINT_C_TYPE) max_low)) 1117 low = max_low; /* Maximum. */ 1118#endif 1119 1120 /* Step 4. Store the result. */ 1121 z = (TO_INT_C_TYPE) low; 1122#if TO_HAVE_PADDING_BITS 1123 z = z << TO_PADDING_BITS; 1124 z = z >> TO_PADDING_BITS; 1125#endif 1126 memcpy (&c, &z, TO_FIXED_SIZE); 1127 return c; 1128} 1129#endif /* defined(SATFRACTUNS) && FROM_TYPE == 2 && TO_TYPE == 4 */ 1130 1131/* Fixed -> Float. */ 1132#if defined(FRACT) && defined(L_fract) && FROM_TYPE == 4 && TO_TYPE == 3 1133TO_FLOAT_C_TYPE 1134FRACT (FROM_FIXED_C_TYPE a) 1135{ 1136 FROM_INT_C_TYPE x; 1137 TO_FLOAT_C_TYPE z; 1138 memcpy (&x, &a, FROM_FIXED_SIZE); 1139 z = (TO_FLOAT_C_TYPE) x; 1140 z = z / BASE; 1141 return z; 1142} 1143#endif /* defined(FRACT) && FROM_TYPE == 4 && TO_TYPE == 3 */ 1144 1145/* Float -> Fixed. */ 1146#if defined(FRACT) && defined(L_fract) && FROM_TYPE == 3 && TO_TYPE == 4 1147TO_FIXED_C_TYPE 1148FRACT (FROM_FLOAT_C_TYPE a) 1149{ 1150 FROM_FLOAT_C_TYPE temp; 1151 TO_INT_C_TYPE z; 1152 TO_FIXED_C_TYPE c; 1153 1154 temp = a * BASE; 1155 z = (TO_INT_C_TYPE) temp; 1156#if TO_HAVE_PADDING_BITS 1157 z = z << TO_PADDING_BITS; 1158 z = z >> TO_PADDING_BITS; 1159#endif 1160 memcpy (&c, &z, TO_FIXED_SIZE); 1161 return c; 1162} 1163#endif /* defined(FRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */ 1164 1165/* Float -> Fixed with saturation. */ 1166#if defined(SATFRACT) && defined(L_satfract) && FROM_TYPE == 3 && TO_TYPE == 4 1167TO_FIXED_C_TYPE 1168SATFRACT (FROM_FLOAT_C_TYPE a) 1169{ 1170 FROM_FLOAT_C_TYPE temp; 1171 TO_INT_C_TYPE z; 1172 TO_FIXED_C_TYPE c; 1173 1174 if (a >= FIXED_MAX) 1175 { 1176#if TO_MODE_UNSIGNED == 0 || TO_HAVE_PADDING_BITS 1177 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS; 1178 z = z - 1; 1179#else 1180 z = -1; 1181#endif 1182 } 1183 else if (a <= FIXED_MIN) 1184 { 1185#if TO_MODE_UNSIGNED == 0 1186 z = (TO_INT_C_TYPE)1 << TO_I_F_BITS; 1187#else 1188 z = 0; 1189#endif 1190 } 1191 else 1192 { 1193 temp = a * BASE; 1194 z = (TO_INT_C_TYPE) temp; 1195 } 1196 1197#if TO_HAVE_PADDING_BITS 1198 z = z << TO_PADDING_BITS; 1199 z = z >> TO_PADDING_BITS; 1200#endif 1201 memcpy (&c, &z, TO_FIXED_SIZE); 1202 return c; 1203} 1204#endif /* defined(SATFRACT) && FROM_TYPE == 3 && TO_TYPE == 4 */ 1205 1206