1 /* Fixed-point arithmetic support. 2 Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "tm.h" 24 #include "tree.h" 25 #include "toplev.h" 26 #include "fixed-value.h" 27 28 /* Compare two fixed objects for bitwise identity. */ 29 30 bool 31 fixed_identical (const FIXED_VALUE_TYPE *a, const FIXED_VALUE_TYPE *b) 32 { 33 return (a->mode == b->mode 34 && a->data.high == b->data.high 35 && a->data.low == b->data.low); 36 } 37 38 /* Calculate a hash value. */ 39 40 unsigned int 41 fixed_hash (const FIXED_VALUE_TYPE *f) 42 { 43 return (unsigned int) (f->data.low ^ f->data.high); 44 } 45 46 /* Define the enum code for the range of the fixed-point value. */ 47 enum fixed_value_range_code { 48 FIXED_OK, /* The value is within the range. */ 49 FIXED_UNDERFLOW, /* The value is less than the minimum. */ 50 FIXED_GT_MAX_EPS, /* The value is greater than the maximum, but not equal 51 to the maximum plus the epsilon. */ 52 FIXED_MAX_EPS /* The value equals the maximum plus the epsilon. */ 53 }; 54 55 /* Check REAL_VALUE against the range of the fixed-point mode. 56 Return FIXED_OK, if it is within the range. 57 FIXED_UNDERFLOW, if it is less than the minimum. 58 FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to 59 the maximum plus the epsilon. 60 FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon. */ 61 62 static enum fixed_value_range_code 63 check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, enum machine_mode mode) 64 { 65 REAL_VALUE_TYPE max_value, min_value, epsilon_value; 66 67 real_2expN (&max_value, GET_MODE_IBIT (mode), mode); 68 real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), mode); 69 70 if (SIGNED_FIXED_POINT_MODE_P (mode)) 71 min_value = REAL_VALUE_NEGATE (max_value); 72 else 73 real_from_string (&min_value, "0.0"); 74 75 if (real_compare (LT_EXPR, real_value, &min_value)) 76 return FIXED_UNDERFLOW; 77 if (real_compare (EQ_EXPR, real_value, &max_value)) 78 return FIXED_MAX_EPS; 79 real_arithmetic (&max_value, MINUS_EXPR, &max_value, &epsilon_value); 80 if (real_compare (GT_EXPR, real_value, &max_value)) 81 return FIXED_GT_MAX_EPS; 82 return FIXED_OK; 83 } 84 85 /* Initialize from a decimal or hexadecimal string. */ 86 87 void 88 fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode) 89 { 90 REAL_VALUE_TYPE real_value, fixed_value, base_value; 91 unsigned int fbit; 92 enum fixed_value_range_code temp; 93 94 f->mode = mode; 95 fbit = GET_MODE_FBIT (mode); 96 97 real_from_string (&real_value, str); 98 temp = check_real_for_fixed_mode (&real_value, f->mode); 99 /* We don't want to warn the case when the _Fract value is 1.0. */ 100 if (temp == FIXED_UNDERFLOW 101 || temp == FIXED_GT_MAX_EPS 102 || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode))) 103 warning (OPT_Woverflow, 104 "large fixed-point constant implicitly truncated to fixed-point type"); 105 real_2expN (&base_value, fbit, mode); 106 real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); 107 real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, 108 &fixed_value); 109 110 if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode)) 111 { 112 /* From the spec, we need to evaluate 1 to the maximal value. */ 113 f->data.low = -1; 114 f->data.high = -1; 115 f->data = double_int_ext (f->data, 116 GET_MODE_FBIT (f->mode) 117 + GET_MODE_IBIT (f->mode), 1); 118 } 119 else 120 f->data = double_int_ext (f->data, 121 SIGNED_FIXED_POINT_MODE_P (f->mode) 122 + GET_MODE_FBIT (f->mode) 123 + GET_MODE_IBIT (f->mode), 124 UNSIGNED_FIXED_POINT_MODE_P (f->mode)); 125 } 126 127 /* Render F as a decimal floating point constant. */ 128 129 void 130 fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig, 131 size_t buf_size) 132 { 133 REAL_VALUE_TYPE real_value, base_value, fixed_value; 134 135 real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode); 136 real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high, 137 UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode)); 138 real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value); 139 real_to_decimal (str, &fixed_value, buf_size, 0, 1); 140 } 141 142 /* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on 143 the machine mode MODE. 144 Do not modify *F otherwise. 145 This function assumes the width of double_int is greater than the width 146 of the fixed-point value (the sum of a possible sign bit, possible ibits, 147 and fbits). 148 Return true, if !SAT_P and overflow. */ 149 150 static bool 151 fixed_saturate1 (enum machine_mode mode, double_int a, double_int *f, 152 bool sat_p) 153 { 154 bool overflow_p = false; 155 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode); 156 int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode); 157 158 if (unsigned_p) /* Unsigned type. */ 159 { 160 double_int max; 161 max.low = -1; 162 max.high = -1; 163 max = double_int_ext (max, i_f_bits, 1); 164 if (double_int_cmp (a, max, 1) == 1) 165 { 166 if (sat_p) 167 *f = max; 168 else 169 overflow_p = true; 170 } 171 } 172 else /* Signed type. */ 173 { 174 double_int max, min; 175 max.high = -1; 176 max.low = -1; 177 max = double_int_ext (max, i_f_bits, 1); 178 min.high = 0; 179 min.low = 1; 180 lshift_double (min.low, min.high, i_f_bits, 181 2 * HOST_BITS_PER_WIDE_INT, 182 &min.low, &min.high, 1); 183 min = double_int_ext (min, 1 + i_f_bits, 0); 184 if (double_int_cmp (a, max, 0) == 1) 185 { 186 if (sat_p) 187 *f = max; 188 else 189 overflow_p = true; 190 } 191 else if (double_int_cmp (a, min, 0) == -1) 192 { 193 if (sat_p) 194 *f = min; 195 else 196 overflow_p = true; 197 } 198 } 199 return overflow_p; 200 } 201 202 /* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and 203 save to *F based on the machine mode MODE. 204 Do not modify *F otherwise. 205 This function assumes the width of two double_int is greater than the width 206 of the fixed-point value (the sum of a possible sign bit, possible ibits, 207 and fbits). 208 Return true, if !SAT_P and overflow. */ 209 210 static bool 211 fixed_saturate2 (enum machine_mode mode, double_int a_high, double_int a_low, 212 double_int *f, bool sat_p) 213 { 214 bool overflow_p = false; 215 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode); 216 int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode); 217 218 if (unsigned_p) /* Unsigned type. */ 219 { 220 double_int max_r, max_s; 221 max_r.high = 0; 222 max_r.low = 0; 223 max_s.high = -1; 224 max_s.low = -1; 225 max_s = double_int_ext (max_s, i_f_bits, 1); 226 if (double_int_cmp (a_high, max_r, 1) == 1 227 || (double_int_equal_p (a_high, max_r) && 228 double_int_cmp (a_low, max_s, 1) == 1)) 229 { 230 if (sat_p) 231 *f = max_s; 232 else 233 overflow_p = true; 234 } 235 } 236 else /* Signed type. */ 237 { 238 double_int max_r, max_s, min_r, min_s; 239 max_r.high = 0; 240 max_r.low = 0; 241 max_s.high = -1; 242 max_s.low = -1; 243 max_s = double_int_ext (max_s, i_f_bits, 1); 244 min_r.high = -1; 245 min_r.low = -1; 246 min_s.high = 0; 247 min_s.low = 1; 248 lshift_double (min_s.low, min_s.high, i_f_bits, 249 2 * HOST_BITS_PER_WIDE_INT, 250 &min_s.low, &min_s.high, 1); 251 min_s = double_int_ext (min_s, 1 + i_f_bits, 0); 252 if (double_int_cmp (a_high, max_r, 0) == 1 253 || (double_int_equal_p (a_high, max_r) && 254 double_int_cmp (a_low, max_s, 1) == 1)) 255 { 256 if (sat_p) 257 *f = max_s; 258 else 259 overflow_p = true; 260 } 261 else if (double_int_cmp (a_high, min_r, 0) == -1 262 || (double_int_equal_p (a_high, min_r) && 263 double_int_cmp (a_low, min_s, 1) == -1)) 264 { 265 if (sat_p) 266 *f = min_s; 267 else 268 overflow_p = true; 269 } 270 } 271 return overflow_p; 272 } 273 274 /* Return the sign bit based on I_F_BITS. */ 275 276 static inline int 277 get_fixed_sign_bit (double_int a, int i_f_bits) 278 { 279 if (i_f_bits < HOST_BITS_PER_WIDE_INT) 280 return (a.low >> i_f_bits) & 1; 281 else 282 return (a.high >> (i_f_bits - HOST_BITS_PER_WIDE_INT)) & 1; 283 } 284 285 /* Calculate F = A + (SUBTRACT_P ? -B : B). 286 If SAT_P, saturate the result to the max or the min. 287 Return true, if !SAT_P and overflow. */ 288 289 static bool 290 do_fixed_add (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, 291 const FIXED_VALUE_TYPE *b, bool subtract_p, bool sat_p) 292 { 293 bool overflow_p = false; 294 bool unsigned_p; 295 double_int temp; 296 int i_f_bits; 297 298 /* This was a conditional expression but it triggered a bug in 299 Sun C 5.5. */ 300 if (subtract_p) 301 temp = double_int_neg (b->data); 302 else 303 temp = b->data; 304 305 unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); 306 i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); 307 f->mode = a->mode; 308 f->data = double_int_add (a->data, temp); 309 if (unsigned_p) /* Unsigned type. */ 310 { 311 if (subtract_p) /* Unsigned subtraction. */ 312 { 313 if (double_int_cmp (a->data, b->data, 1) == -1) 314 { 315 if (sat_p) 316 { 317 f->data.high = 0; 318 f->data.low = 0; 319 } 320 else 321 overflow_p = true; 322 } 323 } 324 else /* Unsigned addition. */ 325 { 326 f->data = double_int_ext (f->data, i_f_bits, 1); 327 if (double_int_cmp (f->data, a->data, 1) == -1 328 || double_int_cmp (f->data, b->data, 1) == -1) 329 { 330 if (sat_p) 331 { 332 f->data.high = -1; 333 f->data.low = -1; 334 } 335 else 336 overflow_p = true; 337 } 338 } 339 } 340 else /* Signed type. */ 341 { 342 if ((!subtract_p 343 && (get_fixed_sign_bit (a->data, i_f_bits) 344 == get_fixed_sign_bit (b->data, i_f_bits)) 345 && (get_fixed_sign_bit (a->data, i_f_bits) 346 != get_fixed_sign_bit (f->data, i_f_bits))) 347 || (subtract_p 348 && (get_fixed_sign_bit (a->data, i_f_bits) 349 != get_fixed_sign_bit (b->data, i_f_bits)) 350 && (get_fixed_sign_bit (a->data, i_f_bits) 351 != get_fixed_sign_bit (f->data, i_f_bits)))) 352 { 353 if (sat_p) 354 { 355 f->data.low = 1; 356 f->data.high = 0; 357 lshift_double (f->data.low, f->data.high, i_f_bits, 358 2 * HOST_BITS_PER_WIDE_INT, 359 &f->data.low, &f->data.high, 1); 360 if (get_fixed_sign_bit (a->data, i_f_bits) == 0) 361 { 362 double_int one; 363 one.low = 1; 364 one.high = 0; 365 f->data = double_int_add (f->data, double_int_neg (one)); 366 } 367 } 368 else 369 overflow_p = true; 370 } 371 } 372 f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p); 373 return overflow_p; 374 } 375 376 /* Calculate F = A * B. 377 If SAT_P, saturate the result to the max or the min. 378 Return true, if !SAT_P and overflow. */ 379 380 static bool 381 do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, 382 const FIXED_VALUE_TYPE *b, bool sat_p) 383 { 384 bool overflow_p = false; 385 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); 386 int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); 387 f->mode = a->mode; 388 if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT) 389 { 390 f->data = double_int_mul (a->data, b->data); 391 lshift_double (f->data.low, f->data.high, 392 (-GET_MODE_FBIT (f->mode)), 393 2 * HOST_BITS_PER_WIDE_INT, 394 &f->data.low, &f->data.high, !unsigned_p); 395 overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); 396 } 397 else 398 { 399 /* The result of multiplication expands to two double_int. */ 400 double_int a_high, a_low, b_high, b_low; 401 double_int high_high, high_low, low_high, low_low; 402 double_int r, s, temp1, temp2; 403 int carry = 0; 404 405 /* Decompose a and b to four double_int. */ 406 a_high.low = a->data.high; 407 a_high.high = 0; 408 a_low.low = a->data.low; 409 a_low.high = 0; 410 b_high.low = b->data.high; 411 b_high.high = 0; 412 b_low.low = b->data.low; 413 b_low.high = 0; 414 415 /* Perform four multiplications. */ 416 low_low = double_int_mul (a_low, b_low); 417 low_high = double_int_mul (a_low, b_high); 418 high_low = double_int_mul (a_high, b_low); 419 high_high = double_int_mul (a_high, b_high); 420 421 /* Accumulate four results to {r, s}. */ 422 temp1.high = high_low.low; 423 temp1.low = 0; 424 s = double_int_add (low_low, temp1); 425 if (double_int_cmp (s, low_low, 1) == -1 426 || double_int_cmp (s, temp1, 1) == -1) 427 carry ++; /* Carry */ 428 temp1.high = s.high; 429 temp1.low = s.low; 430 temp2.high = low_high.low; 431 temp2.low = 0; 432 s = double_int_add (temp1, temp2); 433 if (double_int_cmp (s, temp1, 1) == -1 434 || double_int_cmp (s, temp2, 1) == -1) 435 carry ++; /* Carry */ 436 437 temp1.low = high_low.high; 438 temp1.high = 0; 439 r = double_int_add (high_high, temp1); 440 temp1.low = low_high.high; 441 temp1.high = 0; 442 r = double_int_add (r, temp1); 443 temp1.low = carry; 444 temp1.high = 0; 445 r = double_int_add (r, temp1); 446 447 /* We need to add neg(b) to r, if a < 0. */ 448 if (!unsigned_p && a->data.high < 0) 449 r = double_int_add (r, double_int_neg (b->data)); 450 /* We need to add neg(a) to r, if b < 0. */ 451 if (!unsigned_p && b->data.high < 0) 452 r = double_int_add (r, double_int_neg (a->data)); 453 454 /* Shift right the result by FBIT. */ 455 if (GET_MODE_FBIT (f->mode) == 2 * HOST_BITS_PER_WIDE_INT) 456 { 457 s.low = r.low; 458 s.high = r.high; 459 if (unsigned_p) 460 { 461 r.low = 0; 462 r.high = 0; 463 } 464 else 465 { 466 r.low = -1; 467 r.high = -1; 468 } 469 f->data.low = s.low; 470 f->data.high = s.high; 471 } 472 else 473 { 474 lshift_double (s.low, s.high, 475 (-GET_MODE_FBIT (f->mode)), 476 2 * HOST_BITS_PER_WIDE_INT, 477 &s.low, &s.high, 0); 478 lshift_double (r.low, r.high, 479 (2 * HOST_BITS_PER_WIDE_INT 480 - GET_MODE_FBIT (f->mode)), 481 2 * HOST_BITS_PER_WIDE_INT, 482 &f->data.low, &f->data.high, 0); 483 f->data.low = f->data.low | s.low; 484 f->data.high = f->data.high | s.high; 485 s.low = f->data.low; 486 s.high = f->data.high; 487 lshift_double (r.low, r.high, 488 (-GET_MODE_FBIT (f->mode)), 489 2 * HOST_BITS_PER_WIDE_INT, 490 &r.low, &r.high, !unsigned_p); 491 } 492 493 overflow_p = fixed_saturate2 (f->mode, r, s, &f->data, sat_p); 494 } 495 496 f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p); 497 return overflow_p; 498 } 499 500 /* Calculate F = A / B. 501 If SAT_P, saturate the result to the max or the min. 502 Return true, if !SAT_P and overflow. */ 503 504 static bool 505 do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, 506 const FIXED_VALUE_TYPE *b, bool sat_p) 507 { 508 bool overflow_p = false; 509 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); 510 int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); 511 f->mode = a->mode; 512 if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT) 513 { 514 lshift_double (a->data.low, a->data.high, 515 GET_MODE_FBIT (f->mode), 516 2 * HOST_BITS_PER_WIDE_INT, 517 &f->data.low, &f->data.high, !unsigned_p); 518 f->data = double_int_div (f->data, b->data, unsigned_p, TRUNC_DIV_EXPR); 519 overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); 520 } 521 else 522 { 523 double_int pos_a, pos_b, r, s; 524 double_int quo_r, quo_s, mod, temp; 525 int num_of_neg = 0; 526 int i; 527 528 /* If a < 0, negate a. */ 529 if (!unsigned_p && a->data.high < 0) 530 { 531 pos_a = double_int_neg (a->data); 532 num_of_neg ++; 533 } 534 else 535 pos_a = a->data; 536 537 /* If b < 0, negate b. */ 538 if (!unsigned_p && b->data.high < 0) 539 { 540 pos_b = double_int_neg (b->data); 541 num_of_neg ++; 542 } 543 else 544 pos_b = b->data; 545 546 /* Left shift pos_a to {r, s} by FBIT. */ 547 if (GET_MODE_FBIT (f->mode) == 2 * HOST_BITS_PER_WIDE_INT) 548 { 549 r = pos_a; 550 s.high = 0; 551 s.low = 0; 552 } 553 else 554 { 555 lshift_double (pos_a.low, pos_a.high, 556 GET_MODE_FBIT (f->mode), 557 2 * HOST_BITS_PER_WIDE_INT, 558 &s.low, &s.high, 0); 559 lshift_double (pos_a.low, pos_a.high, 560 - (2 * HOST_BITS_PER_WIDE_INT 561 - GET_MODE_FBIT (f->mode)), 562 2 * HOST_BITS_PER_WIDE_INT, 563 &r.low, &r.high, 0); 564 } 565 566 /* Divide r by pos_b to quo_r. The remainder is in mod. */ 567 div_and_round_double (TRUNC_DIV_EXPR, 1, r.low, r.high, pos_b.low, 568 pos_b.high, &quo_r.low, &quo_r.high, &mod.low, 569 &mod.high); 570 571 quo_s.high = 0; 572 quo_s.low = 0; 573 574 for (i = 0; i < 2 * HOST_BITS_PER_WIDE_INT; i++) 575 { 576 /* Record the leftmost bit of mod. */ 577 int leftmost_mod = (mod.high < 0); 578 579 /* Shift left mod by 1 bit. */ 580 lshift_double (mod.low, mod.high, 1, 2 * HOST_BITS_PER_WIDE_INT, 581 &mod.low, &mod.high, 0); 582 583 /* Test the leftmost bit of s to add to mod. */ 584 if (s.high < 0) 585 mod.low += 1; 586 587 /* Shift left quo_s by 1 bit. */ 588 lshift_double (quo_s.low, quo_s.high, 1, 2 * HOST_BITS_PER_WIDE_INT, 589 &quo_s.low, &quo_s.high, 0); 590 591 /* Try to calculate (mod - pos_b). */ 592 temp = double_int_add (mod, double_int_neg (pos_b)); 593 594 if (leftmost_mod == 1 || double_int_cmp (mod, pos_b, 1) != -1) 595 { 596 quo_s.low += 1; 597 mod = temp; 598 } 599 600 /* Shift left s by 1 bit. */ 601 lshift_double (s.low, s.high, 1, 2 * HOST_BITS_PER_WIDE_INT, 602 &s.low, &s.high, 0); 603 604 } 605 606 if (num_of_neg == 1) 607 { 608 quo_s = double_int_neg (quo_s); 609 if (quo_s.high == 0 && quo_s.low == 0) 610 quo_r = double_int_neg (quo_r); 611 else 612 { 613 quo_r.low = ~quo_r.low; 614 quo_r.high = ~quo_r.high; 615 } 616 } 617 618 f->data = quo_s; 619 overflow_p = fixed_saturate2 (f->mode, quo_r, quo_s, &f->data, sat_p); 620 } 621 622 f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p); 623 return overflow_p; 624 } 625 626 /* Calculate F = A << B if LEFT_P. Otherwise, F = A >> B. 627 If SAT_P, saturate the result to the max or the min. 628 Return true, if !SAT_P and overflow. */ 629 630 static bool 631 do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, 632 const FIXED_VALUE_TYPE *b, bool left_p, bool sat_p) 633 { 634 bool overflow_p = false; 635 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); 636 int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); 637 f->mode = a->mode; 638 639 if (b->data.low == 0) 640 { 641 f->data = a->data; 642 return overflow_p; 643 } 644 645 if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT || (!left_p)) 646 { 647 lshift_double (a->data.low, a->data.high, 648 left_p ? b->data.low : (-b->data.low), 649 2 * HOST_BITS_PER_WIDE_INT, 650 &f->data.low, &f->data.high, !unsigned_p); 651 if (left_p) /* Only left shift saturates. */ 652 overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); 653 } 654 else /* We need two double_int to store the left-shift result. */ 655 { 656 double_int temp_high, temp_low; 657 if (b->data.low == 2 * HOST_BITS_PER_WIDE_INT) 658 { 659 temp_high = a->data; 660 temp_low.high = 0; 661 temp_low.low = 0; 662 } 663 else 664 { 665 lshift_double (a->data.low, a->data.high, 666 b->data.low, 667 2 * HOST_BITS_PER_WIDE_INT, 668 &temp_low.low, &temp_low.high, !unsigned_p); 669 /* Logical shift right to temp_high. */ 670 lshift_double (a->data.low, a->data.high, 671 b->data.low - 2 * HOST_BITS_PER_WIDE_INT, 672 2 * HOST_BITS_PER_WIDE_INT, 673 &temp_high.low, &temp_high.high, 0); 674 } 675 if (!unsigned_p && a->data.high < 0) /* Signed-extend temp_high. */ 676 temp_high = double_int_ext (temp_high, b->data.low, unsigned_p); 677 f->data = temp_low; 678 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data, 679 sat_p); 680 } 681 f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p); 682 return overflow_p; 683 } 684 685 /* Calculate F = -A. 686 If SAT_P, saturate the result to the max or the min. 687 Return true, if !SAT_P and overflow. */ 688 689 static bool 690 do_fixed_neg (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, bool sat_p) 691 { 692 bool overflow_p = false; 693 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode); 694 int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode); 695 f->mode = a->mode; 696 f->data = double_int_neg (a->data); 697 f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p); 698 699 if (unsigned_p) /* Unsigned type. */ 700 { 701 if (f->data.low != 0 || f->data.high != 0) 702 { 703 if (sat_p) 704 { 705 f->data.low = 0; 706 f->data.high = 0; 707 } 708 else 709 overflow_p = true; 710 } 711 } 712 else /* Signed type. */ 713 { 714 if (!(f->data.high == 0 && f->data.low == 0) 715 && f->data.high == a->data.high && f->data.low == a->data.low ) 716 { 717 if (sat_p) 718 { 719 /* Saturate to the maximum by subtracting f->data by one. */ 720 f->data.low = -1; 721 f->data.high = -1; 722 f->data = double_int_ext (f->data, i_f_bits, 1); 723 } 724 else 725 overflow_p = true; 726 } 727 } 728 return overflow_p; 729 } 730 731 /* Perform the binary or unary operation described by CODE. 732 Note that OP0 and OP1 must have the same mode for binary operators. 733 For a unary operation, leave OP1 NULL. 734 Return true, if !SAT_P and overflow. */ 735 736 bool 737 fixed_arithmetic (FIXED_VALUE_TYPE *f, int icode, const FIXED_VALUE_TYPE *op0, 738 const FIXED_VALUE_TYPE *op1, bool sat_p) 739 { 740 switch (icode) 741 { 742 case NEGATE_EXPR: 743 return do_fixed_neg (f, op0, sat_p); 744 break; 745 746 case PLUS_EXPR: 747 gcc_assert (op0->mode == op1->mode); 748 return do_fixed_add (f, op0, op1, false, sat_p); 749 break; 750 751 case MINUS_EXPR: 752 gcc_assert (op0->mode == op1->mode); 753 return do_fixed_add (f, op0, op1, true, sat_p); 754 break; 755 756 case MULT_EXPR: 757 gcc_assert (op0->mode == op1->mode); 758 return do_fixed_multiply (f, op0, op1, sat_p); 759 break; 760 761 case TRUNC_DIV_EXPR: 762 gcc_assert (op0->mode == op1->mode); 763 return do_fixed_divide (f, op0, op1, sat_p); 764 break; 765 766 case LSHIFT_EXPR: 767 return do_fixed_shift (f, op0, op1, true, sat_p); 768 break; 769 770 case RSHIFT_EXPR: 771 return do_fixed_shift (f, op0, op1, false, sat_p); 772 break; 773 774 default: 775 gcc_unreachable (); 776 } 777 return false; 778 } 779 780 /* Compare fixed-point values by tree_code. 781 Note that OP0 and OP1 must have the same mode. */ 782 783 bool 784 fixed_compare (int icode, const FIXED_VALUE_TYPE *op0, 785 const FIXED_VALUE_TYPE *op1) 786 { 787 enum tree_code code = (enum tree_code) icode; 788 gcc_assert (op0->mode == op1->mode); 789 790 switch (code) 791 { 792 case NE_EXPR: 793 return !double_int_equal_p (op0->data, op1->data); 794 795 case EQ_EXPR: 796 return double_int_equal_p (op0->data, op1->data); 797 798 case LT_EXPR: 799 return double_int_cmp (op0->data, op1->data, 800 UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == -1; 801 802 case LE_EXPR: 803 return double_int_cmp (op0->data, op1->data, 804 UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != 1; 805 806 case GT_EXPR: 807 return double_int_cmp (op0->data, op1->data, 808 UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == 1; 809 810 case GE_EXPR: 811 return double_int_cmp (op0->data, op1->data, 812 UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != -1; 813 814 default: 815 gcc_unreachable (); 816 } 817 } 818 819 /* Extend or truncate to a new mode. 820 If SAT_P, saturate the result to the max or the min. 821 Return true, if !SAT_P and overflow. */ 822 823 bool 824 fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode, 825 const FIXED_VALUE_TYPE *a, bool sat_p) 826 { 827 bool overflow_p = false; 828 if (mode == a->mode) 829 { 830 *f = *a; 831 return overflow_p; 832 } 833 834 if (GET_MODE_FBIT (mode) > GET_MODE_FBIT (a->mode)) 835 { 836 /* Left shift a to temp_high, temp_low based on a->mode. */ 837 double_int temp_high, temp_low; 838 int amount = GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode); 839 lshift_double (a->data.low, a->data.high, 840 amount, 841 2 * HOST_BITS_PER_WIDE_INT, 842 &temp_low.low, &temp_low.high, 843 SIGNED_FIXED_POINT_MODE_P (a->mode)); 844 /* Logical shift right to temp_high. */ 845 lshift_double (a->data.low, a->data.high, 846 amount - 2 * HOST_BITS_PER_WIDE_INT, 847 2 * HOST_BITS_PER_WIDE_INT, 848 &temp_high.low, &temp_high.high, 0); 849 if (SIGNED_FIXED_POINT_MODE_P (a->mode) 850 && a->data.high < 0) /* Signed-extend temp_high. */ 851 temp_high = double_int_ext (temp_high, amount, 0); 852 f->mode = mode; 853 f->data = temp_low; 854 if (SIGNED_FIXED_POINT_MODE_P (a->mode) == 855 SIGNED_FIXED_POINT_MODE_P (f->mode)) 856 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data, 857 sat_p); 858 else 859 { 860 /* Take care of the cases when converting between signed and 861 unsigned. */ 862 if (SIGNED_FIXED_POINT_MODE_P (a->mode)) 863 { 864 /* Signed -> Unsigned. */ 865 if (a->data.high < 0) 866 { 867 if (sat_p) 868 { 869 f->data.low = 0; /* Set to zero. */ 870 f->data.high = 0; /* Set to zero. */ 871 } 872 else 873 overflow_p = true; 874 } 875 else 876 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, 877 &f->data, sat_p); 878 } 879 else 880 { 881 /* Unsigned -> Signed. */ 882 if (temp_high.high < 0) 883 { 884 if (sat_p) 885 { 886 /* Set to maximum. */ 887 f->data.low = -1; /* Set to all ones. */ 888 f->data.high = -1; /* Set to all ones. */ 889 f->data = double_int_ext (f->data, 890 GET_MODE_FBIT (f->mode) 891 + GET_MODE_IBIT (f->mode), 892 1); /* Clear the sign. */ 893 } 894 else 895 overflow_p = true; 896 } 897 else 898 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, 899 &f->data, sat_p); 900 } 901 } 902 } 903 else 904 { 905 /* Right shift a to temp based on a->mode. */ 906 double_int temp; 907 lshift_double (a->data.low, a->data.high, 908 GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode), 909 2 * HOST_BITS_PER_WIDE_INT, 910 &temp.low, &temp.high, 911 SIGNED_FIXED_POINT_MODE_P (a->mode)); 912 f->mode = mode; 913 f->data = temp; 914 if (SIGNED_FIXED_POINT_MODE_P (a->mode) == 915 SIGNED_FIXED_POINT_MODE_P (f->mode)) 916 overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p); 917 else 918 { 919 /* Take care of the cases when converting between signed and 920 unsigned. */ 921 if (SIGNED_FIXED_POINT_MODE_P (a->mode)) 922 { 923 /* Signed -> Unsigned. */ 924 if (a->data.high < 0) 925 { 926 if (sat_p) 927 { 928 f->data.low = 0; /* Set to zero. */ 929 f->data.high = 0; /* Set to zero. */ 930 } 931 else 932 overflow_p = true; 933 } 934 else 935 overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, 936 sat_p); 937 } 938 else 939 { 940 /* Unsigned -> Signed. */ 941 if (temp.high < 0) 942 { 943 if (sat_p) 944 { 945 /* Set to maximum. */ 946 f->data.low = -1; /* Set to all ones. */ 947 f->data.high = -1; /* Set to all ones. */ 948 f->data = double_int_ext (f->data, 949 GET_MODE_FBIT (f->mode) 950 + GET_MODE_IBIT (f->mode), 951 1); /* Clear the sign. */ 952 } 953 else 954 overflow_p = true; 955 } 956 else 957 overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, 958 sat_p); 959 } 960 } 961 } 962 963 f->data = double_int_ext (f->data, 964 SIGNED_FIXED_POINT_MODE_P (f->mode) 965 + GET_MODE_FBIT (f->mode) 966 + GET_MODE_IBIT (f->mode), 967 UNSIGNED_FIXED_POINT_MODE_P (f->mode)); 968 return overflow_p; 969 } 970 971 /* Convert to a new fixed-point mode from an integer. 972 If UNSIGNED_P, this integer is unsigned. 973 If SAT_P, saturate the result to the max or the min. 974 Return true, if !SAT_P and overflow. */ 975 976 bool 977 fixed_convert_from_int (FIXED_VALUE_TYPE *f, enum machine_mode mode, 978 double_int a, bool unsigned_p, bool sat_p) 979 { 980 bool overflow_p = false; 981 /* Left shift a to temp_high, temp_low. */ 982 double_int temp_high, temp_low; 983 int amount = GET_MODE_FBIT (mode); 984 if (amount == 2 * HOST_BITS_PER_WIDE_INT) 985 { 986 temp_high = a; 987 temp_low.low = 0; 988 temp_low.high = 0; 989 } 990 else 991 { 992 lshift_double (a.low, a.high, 993 amount, 994 2 * HOST_BITS_PER_WIDE_INT, 995 &temp_low.low, &temp_low.high, 0); 996 997 /* Logical shift right to temp_high. */ 998 lshift_double (a.low, a.high, 999 amount - 2 * HOST_BITS_PER_WIDE_INT, 1000 2 * HOST_BITS_PER_WIDE_INT, 1001 &temp_high.low, &temp_high.high, 0); 1002 } 1003 if (!unsigned_p && a.high < 0) /* Signed-extend temp_high. */ 1004 temp_high = double_int_ext (temp_high, amount, 0); 1005 1006 f->mode = mode; 1007 f->data = temp_low; 1008 1009 if (unsigned_p == UNSIGNED_FIXED_POINT_MODE_P (f->mode)) 1010 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data, 1011 sat_p); 1012 else 1013 { 1014 /* Take care of the cases when converting between signed and unsigned. */ 1015 if (!unsigned_p) 1016 { 1017 /* Signed -> Unsigned. */ 1018 if (a.high < 0) 1019 { 1020 if (sat_p) 1021 { 1022 f->data.low = 0; /* Set to zero. */ 1023 f->data.high = 0; /* Set to zero. */ 1024 } 1025 else 1026 overflow_p = true; 1027 } 1028 else 1029 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, 1030 &f->data, sat_p); 1031 } 1032 else 1033 { 1034 /* Unsigned -> Signed. */ 1035 if (temp_high.high < 0) 1036 { 1037 if (sat_p) 1038 { 1039 /* Set to maximum. */ 1040 f->data.low = -1; /* Set to all ones. */ 1041 f->data.high = -1; /* Set to all ones. */ 1042 f->data = double_int_ext (f->data, 1043 GET_MODE_FBIT (f->mode) 1044 + GET_MODE_IBIT (f->mode), 1045 1); /* Clear the sign. */ 1046 } 1047 else 1048 overflow_p = true; 1049 } 1050 else 1051 overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, 1052 &f->data, sat_p); 1053 } 1054 } 1055 f->data = double_int_ext (f->data, 1056 SIGNED_FIXED_POINT_MODE_P (f->mode) 1057 + GET_MODE_FBIT (f->mode) 1058 + GET_MODE_IBIT (f->mode), 1059 UNSIGNED_FIXED_POINT_MODE_P (f->mode)); 1060 return overflow_p; 1061 } 1062 1063 /* Convert to a new fixed-point mode from a real. 1064 If SAT_P, saturate the result to the max or the min. 1065 Return true, if !SAT_P and overflow. */ 1066 1067 bool 1068 fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode, 1069 const REAL_VALUE_TYPE *a, bool sat_p) 1070 { 1071 bool overflow_p = false; 1072 REAL_VALUE_TYPE real_value, fixed_value, base_value; 1073 bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode); 1074 int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode); 1075 unsigned int fbit = GET_MODE_FBIT (mode); 1076 enum fixed_value_range_code temp; 1077 1078 real_value = *a; 1079 f->mode = mode; 1080 real_2expN (&base_value, fbit, mode); 1081 real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value); 1082 real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value); 1083 temp = check_real_for_fixed_mode (&real_value, mode); 1084 if (temp == FIXED_UNDERFLOW) /* Minimum. */ 1085 { 1086 if (sat_p) 1087 { 1088 if (unsigned_p) 1089 { 1090 f->data.low = 0; 1091 f->data.high = 0; 1092 } 1093 else 1094 { 1095 f->data.low = 1; 1096 f->data.high = 0; 1097 lshift_double (f->data.low, f->data.high, i_f_bits, 1098 2 * HOST_BITS_PER_WIDE_INT, 1099 &f->data.low, &f->data.high, 1); 1100 f->data = double_int_ext (f->data, 1 + i_f_bits, 0); 1101 } 1102 } 1103 else 1104 overflow_p = true; 1105 } 1106 else if (temp == FIXED_GT_MAX_EPS || temp == FIXED_MAX_EPS) /* Maximum. */ 1107 { 1108 if (sat_p) 1109 { 1110 f->data.low = -1; 1111 f->data.high = -1; 1112 f->data = double_int_ext (f->data, i_f_bits, 1); 1113 } 1114 else 1115 overflow_p = true; 1116 } 1117 f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p); 1118 return overflow_p; 1119 } 1120 1121 /* Convert to a new real mode from a fixed-point. */ 1122 1123 void 1124 real_convert_from_fixed (REAL_VALUE_TYPE *r, enum machine_mode mode, 1125 const FIXED_VALUE_TYPE *f) 1126 { 1127 REAL_VALUE_TYPE base_value, fixed_value, real_value; 1128 1129 real_2expN (&base_value, GET_MODE_FBIT (f->mode), f->mode); 1130 real_from_integer (&fixed_value, VOIDmode, f->data.low, f->data.high, 1131 UNSIGNED_FIXED_POINT_MODE_P (f->mode)); 1132 real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value); 1133 real_convert (r, mode, &real_value); 1134 } 1135 1136 /* Determine whether a fixed-point value F is negative. */ 1137 1138 bool 1139 fixed_isneg (const FIXED_VALUE_TYPE *f) 1140 { 1141 if (SIGNED_FIXED_POINT_MODE_P (f->mode)) 1142 { 1143 int i_f_bits = GET_MODE_IBIT (f->mode) + GET_MODE_FBIT (f->mode); 1144 int sign_bit = get_fixed_sign_bit (f->data, i_f_bits); 1145 if (sign_bit == 1) 1146 return true; 1147 } 1148 1149 return false; 1150 } 1151