| /* real.c - software floating point emulation. |
| Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
| 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
| Contributed by Stephen L. Moshier (moshier@world.std.com). |
| Re-written by Richard Henderson <rth@redhat.com> |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 2, or (at your option) any later |
| version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING. If not, write to the Free |
| Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
| 02111-1307, USA. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tm.h" |
| #include "tree.h" |
| #include "toplev.h" |
| #include "real.h" |
| #include "tm_p.h" |
| |
| /* The floating point model used internally is not exactly IEEE 754 |
| compliant, and close to the description in the ISO C99 standard, |
| section 5.2.4.2.2 Characteristics of floating types. |
| |
| Specifically |
| |
| x = s * b^e * \sum_{k=1}^p f_k * b^{-k} |
| |
| where |
| s = sign (+- 1) |
| b = base or radix, here always 2 |
| e = exponent |
| p = precision (the number of base-b digits in the significand) |
| f_k = the digits of the significand. |
| |
| We differ from typical IEEE 754 encodings in that the entire |
| significand is fractional. Normalized significands are in the |
| range [0.5, 1.0). |
| |
| A requirement of the model is that P be larger than the largest |
| supported target floating-point type by at least 2 bits. This gives |
| us proper rounding when we truncate to the target type. In addition, |
| E must be large enough to hold the smallest supported denormal number |
| in a normalized form. |
| |
| Both of these requirements are easily satisfied. The largest target |
| significand is 113 bits; we store at least 160. The smallest |
| denormal number fits in 17 exponent bits; we store 27. |
| |
| Note that the decimal string conversion routines are sensitive to |
| rounding errors. Since the raw arithmetic routines do not themselves |
| have guard digits or rounding, the computation of 10**exp can |
| accumulate more than a few digits of error. The previous incarnation |
| of real.c successfully used a 144-bit fraction; given the current |
| layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits. |
| |
| Target floating point models that use base 16 instead of base 2 |
| (i.e. IBM 370), are handled during round_for_format, in which we |
| canonicalize the exponent to be a multiple of 4 (log2(16)), and |
| adjust the significand to match. */ |
| |
| |
| /* Used to classify two numbers simultaneously. */ |
| #define CLASS2(A, B) ((A) << 2 | (B)) |
| |
| #if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32 |
| #error "Some constant folding done by hand to avoid shift count warnings" |
| #endif |
| |
| static void get_zero (REAL_VALUE_TYPE *, int); |
| static void get_canonical_qnan (REAL_VALUE_TYPE *, int); |
| static void get_canonical_snan (REAL_VALUE_TYPE *, int); |
| static void get_inf (REAL_VALUE_TYPE *, int); |
| static bool sticky_rshift_significand (REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *, unsigned int); |
| static void rshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| unsigned int); |
| static void lshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| unsigned int); |
| static void lshift_significand_1 (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| static bool add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static bool sub_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *, int); |
| static void neg_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| static int cmp_significands (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| static int cmp_significand_0 (const REAL_VALUE_TYPE *); |
| static void set_significand_bit (REAL_VALUE_TYPE *, unsigned int); |
| static void clear_significand_bit (REAL_VALUE_TYPE *, unsigned int); |
| static bool test_significand_bit (REAL_VALUE_TYPE *, unsigned int); |
| static void clear_significand_below (REAL_VALUE_TYPE *, unsigned int); |
| static bool div_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static void normalize (REAL_VALUE_TYPE *); |
| |
| static bool do_add (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *, int); |
| static bool do_multiply (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static bool do_divide (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, |
| const REAL_VALUE_TYPE *); |
| static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int); |
| static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); |
| |
| static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *); |
| |
| static const REAL_VALUE_TYPE * ten_to_ptwo (int); |
| static const REAL_VALUE_TYPE * ten_to_mptwo (int); |
| static const REAL_VALUE_TYPE * real_digit (int); |
| static void times_pten (REAL_VALUE_TYPE *, int); |
| |
| static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *); |
| |
| /* Initialize R with a positive zero. */ |
| |
| static inline void |
| get_zero (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->sign = sign; |
| } |
| |
| /* Initialize R with the canonical quiet NaN. */ |
| |
| static inline void |
| get_canonical_qnan (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->canonical = 1; |
| } |
| |
| static inline void |
| get_canonical_snan (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->signalling = 1; |
| r->canonical = 1; |
| } |
| |
| static inline void |
| get_inf (REAL_VALUE_TYPE *r, int sign) |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_inf; |
| r->sign = sign; |
| } |
| |
| |
| /* Right-shift the significand of A by N bits; put the result in the |
| significand of R. If any one bits are shifted out, return true. */ |
| |
| static bool |
| sticky_rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| unsigned int n) |
| { |
| unsigned long sticky = 0; |
| unsigned int i, ofs = 0; |
| |
| if (n >= HOST_BITS_PER_LONG) |
| { |
| for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i) |
| sticky |= a->sig[i]; |
| n &= HOST_BITS_PER_LONG - 1; |
| } |
| |
| if (n != 0) |
| { |
| sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1); |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| r->sig[i] |
| = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n) |
| | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1]) |
| << (HOST_BITS_PER_LONG - n))); |
| } |
| } |
| else |
| { |
| for (i = 0; ofs + i < SIGSZ; ++i) |
| r->sig[i] = a->sig[ofs + i]; |
| for (; i < SIGSZ; ++i) |
| r->sig[i] = 0; |
| } |
| |
| return sticky != 0; |
| } |
| |
| /* Right-shift the significand of A by N bits; put the result in the |
| significand of R. */ |
| |
| static void |
| rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| unsigned int n) |
| { |
| unsigned int i, ofs = n / HOST_BITS_PER_LONG; |
| |
| n &= HOST_BITS_PER_LONG - 1; |
| if (n != 0) |
| { |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| r->sig[i] |
| = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n) |
| | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1]) |
| << (HOST_BITS_PER_LONG - n))); |
| } |
| } |
| else |
| { |
| for (i = 0; ofs + i < SIGSZ; ++i) |
| r->sig[i] = a->sig[ofs + i]; |
| for (; i < SIGSZ; ++i) |
| r->sig[i] = 0; |
| } |
| } |
| |
| /* Left-shift the significand of A by N bits; put the result in the |
| significand of R. */ |
| |
| static void |
| lshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| unsigned int n) |
| { |
| unsigned int i, ofs = n / HOST_BITS_PER_LONG; |
| |
| n &= HOST_BITS_PER_LONG - 1; |
| if (n == 0) |
| { |
| for (i = 0; ofs + i < SIGSZ; ++i) |
| r->sig[SIGSZ-1-i] = a->sig[SIGSZ-1-i-ofs]; |
| for (; i < SIGSZ; ++i) |
| r->sig[SIGSZ-1-i] = 0; |
| } |
| else |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| r->sig[SIGSZ-1-i] |
| = (((ofs + i >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs]) << n) |
| | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs-1]) |
| >> (HOST_BITS_PER_LONG - n))); |
| } |
| } |
| |
| /* Likewise, but N is specialized to 1. */ |
| |
| static inline void |
| lshift_significand_1 (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |
| { |
| unsigned int i; |
| |
| for (i = SIGSZ - 1; i > 0; --i) |
| r->sig[i] = (a->sig[i] << 1) | (a->sig[i-1] >> (HOST_BITS_PER_LONG - 1)); |
| r->sig[0] = a->sig[0] << 1; |
| } |
| |
| /* Add the significands of A and B, placing the result in R. Return |
| true if there was carry out of the most significant word. */ |
| |
| static inline bool |
| add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| bool carry = false; |
| int i; |
| |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long ai = a->sig[i]; |
| unsigned long ri = ai + b->sig[i]; |
| |
| if (carry) |
| { |
| carry = ri < ai; |
| carry |= ++ri == 0; |
| } |
| else |
| carry = ri < ai; |
| |
| r->sig[i] = ri; |
| } |
| |
| return carry; |
| } |
| |
| /* Subtract the significands of A and B, placing the result in R. CARRY is |
| true if there's a borrow incoming to the least significant word. |
| Return true if there was borrow out of the most significant word. */ |
| |
| static inline bool |
| sub_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b, int carry) |
| { |
| int i; |
| |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long ai = a->sig[i]; |
| unsigned long ri = ai - b->sig[i]; |
| |
| if (carry) |
| { |
| carry = ri > ai; |
| carry |= ~--ri == 0; |
| } |
| else |
| carry = ri > ai; |
| |
| r->sig[i] = ri; |
| } |
| |
| return carry; |
| } |
| |
| /* Negate the significand A, placing the result in R. */ |
| |
| static inline void |
| neg_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |
| { |
| bool carry = true; |
| int i; |
| |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long ri, ai = a->sig[i]; |
| |
| if (carry) |
| { |
| if (ai) |
| { |
| ri = -ai; |
| carry = false; |
| } |
| else |
| ri = ai; |
| } |
| else |
| ri = ~ai; |
| |
| r->sig[i] = ri; |
| } |
| } |
| |
| /* Compare significands. Return tri-state vs zero. */ |
| |
| static inline int |
| cmp_significands (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b) |
| { |
| int i; |
| |
| for (i = SIGSZ - 1; i >= 0; --i) |
| { |
| unsigned long ai = a->sig[i]; |
| unsigned long bi = b->sig[i]; |
| |
| if (ai > bi) |
| return 1; |
| if (ai < bi) |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /* Return true if A is nonzero. */ |
| |
| static inline int |
| cmp_significand_0 (const REAL_VALUE_TYPE *a) |
| { |
| int i; |
| |
| for (i = SIGSZ - 1; i >= 0; --i) |
| if (a->sig[i]) |
| return 1; |
| |
| return 0; |
| } |
| |
| /* Set bit N of the significand of R. */ |
| |
| static inline void |
| set_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| r->sig[n / HOST_BITS_PER_LONG] |
| |= (unsigned long)1 << (n % HOST_BITS_PER_LONG); |
| } |
| |
| /* Clear bit N of the significand of R. */ |
| |
| static inline void |
| clear_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| r->sig[n / HOST_BITS_PER_LONG] |
| &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG)); |
| } |
| |
| /* Test bit N of the significand of R. */ |
| |
| static inline bool |
| test_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| /* ??? Compiler bug here if we return this expression directly. |
| The conversion to bool strips the "&1" and we wind up testing |
| e.g. 2 != 0 -> true. Seen in gcc version 3.2 20020520. */ |
| int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1; |
| return t; |
| } |
| |
| /* Clear bits 0..N-1 of the significand of R. */ |
| |
| static void |
| clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n) |
| { |
| int i, w = n / HOST_BITS_PER_LONG; |
| |
| for (i = 0; i < w; ++i) |
| r->sig[i] = 0; |
| |
| r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1); |
| } |
| |
| /* Divide the significands of A and B, placing the result in R. Return |
| true if the division was inexact. */ |
| |
| static inline bool |
| div_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| REAL_VALUE_TYPE u; |
| int i, bit = SIGNIFICAND_BITS - 1; |
| unsigned long msb, inexact; |
| |
| u = *a; |
| memset (r->sig, 0, sizeof (r->sig)); |
| |
| msb = 0; |
| goto start; |
| do |
| { |
| msb = u.sig[SIGSZ-1] & SIG_MSB; |
| lshift_significand_1 (&u, &u); |
| start: |
| if (msb || cmp_significands (&u, b) >= 0) |
| { |
| sub_significands (&u, &u, b, 0); |
| set_significand_bit (r, bit); |
| } |
| } |
| while (--bit >= 0); |
| |
| for (i = 0, inexact = 0; i < SIGSZ; i++) |
| inexact |= u.sig[i]; |
| |
| return inexact != 0; |
| } |
| |
| /* Adjust the exponent and significand of R such that the most |
| significant bit is set. We underflow to zero and overflow to |
| infinity here, without denormals. (The intermediate representation |
| exponent is large enough to handle target denormals normalized.) */ |
| |
| static void |
| normalize (REAL_VALUE_TYPE *r) |
| { |
| int shift = 0, exp; |
| int i, j; |
| |
| /* Find the first word that is nonzero. */ |
| for (i = SIGSZ - 1; i >= 0; i--) |
| if (r->sig[i] == 0) |
| shift += HOST_BITS_PER_LONG; |
| else |
| break; |
| |
| /* Zero significand flushes to zero. */ |
| if (i < 0) |
| { |
| r->cl = rvc_zero; |
| SET_REAL_EXP (r, 0); |
| return; |
| } |
| |
| /* Find the first bit that is nonzero. */ |
| for (j = 0; ; j++) |
| if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j))) |
| break; |
| shift += j; |
| |
| if (shift > 0) |
| { |
| exp = REAL_EXP (r) - shift; |
| if (exp > MAX_EXP) |
| get_inf (r, r->sign); |
| else if (exp < -MAX_EXP) |
| get_zero (r, r->sign); |
| else |
| { |
| SET_REAL_EXP (r, exp); |
| lshift_significand (r, r, shift); |
| } |
| } |
| } |
| |
| /* Calculate R = A + (SUBTRACT_P ? -B : B). Return true if the |
| result may be inexact due to a loss of precision. */ |
| |
| static bool |
| do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b, int subtract_p) |
| { |
| int dexp, sign, exp; |
| REAL_VALUE_TYPE t; |
| bool inexact = false; |
| |
| /* Determine if we need to add or subtract. */ |
| sign = a->sign; |
| subtract_p = (sign ^ b->sign) ^ subtract_p; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0. */ |
| get_zero (r, sign & !subtract_p); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_zero, rvc_inf): |
| case CLASS2 (rvc_zero, rvc_nan): |
| /* 0 + ANY = ANY. */ |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| /* ANY + NaN = NaN. */ |
| case CLASS2 (rvc_normal, rvc_inf): |
| /* R + Inf = Inf. */ |
| *r = *b; |
| r->sign = sign ^ subtract_p; |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_zero): |
| case CLASS2 (rvc_inf, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_zero): |
| /* ANY + 0 = ANY. */ |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| /* NaN + ANY = NaN. */ |
| case CLASS2 (rvc_inf, rvc_normal): |
| /* Inf + R = Inf. */ |
| *r = *a; |
| return false; |
| |
| case CLASS2 (rvc_inf, rvc_inf): |
| if (subtract_p) |
| /* Inf - Inf = NaN. */ |
| get_canonical_qnan (r, 0); |
| else |
| /* Inf + Inf = Inf. */ |
| *r = *a; |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* Swap the arguments such that A has the larger exponent. */ |
| dexp = REAL_EXP (a) - REAL_EXP (b); |
| if (dexp < 0) |
| { |
| const REAL_VALUE_TYPE *t; |
| t = a, a = b, b = t; |
| dexp = -dexp; |
| sign ^= subtract_p; |
| } |
| exp = REAL_EXP (a); |
| |
| /* If the exponents are not identical, we need to shift the |
| significand of B down. */ |
| if (dexp > 0) |
| { |
| /* If the exponents are too far apart, the significands |
| do not overlap, which makes the subtraction a noop. */ |
| if (dexp >= SIGNIFICAND_BITS) |
| { |
| *r = *a; |
| r->sign = sign; |
| return true; |
| } |
| |
| inexact |= sticky_rshift_significand (&t, b, dexp); |
| b = &t; |
| } |
| |
| if (subtract_p) |
| { |
| if (sub_significands (r, a, b, inexact)) |
| { |
| /* We got a borrow out of the subtraction. That means that |
| A and B had the same exponent, and B had the larger |
| significand. We need to swap the sign and negate the |
| significand. */ |
| sign ^= 1; |
| neg_significand (r, r); |
| } |
| } |
| else |
| { |
| if (add_significands (r, a, b)) |
| { |
| /* We got carry out of the addition. This means we need to |
| shift the significand back down one bit and increase the |
| exponent. */ |
| inexact |= sticky_rshift_significand (r, r, 1); |
| r->sig[SIGSZ-1] |= SIG_MSB; |
| if (++exp > MAX_EXP) |
| { |
| get_inf (r, sign); |
| return true; |
| } |
| } |
| } |
| |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, exp); |
| /* Zero out the remaining fields. */ |
| r->signalling = 0; |
| r->canonical = 0; |
| |
| /* Re-normalize the result. */ |
| normalize (r); |
| |
| /* Special case: if the subtraction results in zero, the result |
| is positive. */ |
| if (r->cl == rvc_zero) |
| r->sign = 0; |
| else |
| r->sig[0] |= inexact; |
| |
| return inexact; |
| } |
| |
| /* Calculate R = A * B. Return true if the result may be inexact. */ |
| |
| static bool |
| do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| REAL_VALUE_TYPE u, t, *rr; |
| unsigned int i, j, k; |
| int sign = a->sign ^ b->sign; |
| bool inexact = false; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_normal, rvc_zero): |
| /* +-0 * ANY = 0 with appropriate sign. */ |
| get_zero (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_nan): |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| /* ANY * NaN = NaN. */ |
| *r = *b; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_nan, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| /* NaN * ANY = NaN. */ |
| *r = *a; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_inf): |
| case CLASS2 (rvc_inf, rvc_zero): |
| /* 0 * Inf = NaN */ |
| get_canonical_qnan (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_inf, rvc_inf): |
| case CLASS2 (rvc_normal, rvc_inf): |
| case CLASS2 (rvc_inf, rvc_normal): |
| /* Inf * Inf = Inf, R * Inf = Inf */ |
| get_inf (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (r == a || r == b) |
| rr = &t; |
| else |
| rr = r; |
| get_zero (rr, 0); |
| |
| /* Collect all the partial products. Since we don't have sure access |
| to a widening multiply, we split each long into two half-words. |
| |
| Consider the long-hand form of a four half-word multiplication: |
| |
| A B C D |
| * E F G H |
| -------------- |
| DE DF DG DH |
| CE CF CG CH |
| BE BF BG BH |
| AE AF AG AH |
| |
| We construct partial products of the widened half-word products |
| that are known to not overlap, e.g. DF+DH. Each such partial |
| product is given its proper exponent, which allows us to sum them |
| and obtain the finished product. */ |
| |
| for (i = 0; i < SIGSZ * 2; ++i) |
| { |
| unsigned long ai = a->sig[i / 2]; |
| if (i & 1) |
| ai >>= HOST_BITS_PER_LONG / 2; |
| else |
| ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1; |
| |
| if (ai == 0) |
| continue; |
| |
| for (j = 0; j < 2; ++j) |
| { |
| int exp = (REAL_EXP (a) - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2) |
| + (REAL_EXP (b) - (1-j)*(HOST_BITS_PER_LONG/2))); |
| |
| if (exp > MAX_EXP) |
| { |
| get_inf (r, sign); |
| return true; |
| } |
| if (exp < -MAX_EXP) |
| { |
| /* Would underflow to zero, which we shouldn't bother adding. */ |
| inexact = true; |
| continue; |
| } |
| |
| memset (&u, 0, sizeof (u)); |
| u.cl = rvc_normal; |
| SET_REAL_EXP (&u, exp); |
| |
| for (k = j; k < SIGSZ * 2; k += 2) |
| { |
| unsigned long bi = b->sig[k / 2]; |
| if (k & 1) |
| bi >>= HOST_BITS_PER_LONG / 2; |
| else |
| bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1; |
| |
| u.sig[k / 2] = ai * bi; |
| } |
| |
| normalize (&u); |
| inexact |= do_add (rr, rr, &u, 0); |
| } |
| } |
| |
| rr->sign = sign; |
| if (rr != r) |
| *r = t; |
| |
| return inexact; |
| } |
| |
| /* Calculate R = A / B. Return true if the result may be inexact. */ |
| |
| static bool |
| do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, |
| const REAL_VALUE_TYPE *b) |
| { |
| int exp, sign = a->sign ^ b->sign; |
| REAL_VALUE_TYPE t, *rr; |
| bool inexact; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| /* 0 / 0 = NaN. */ |
| case CLASS2 (rvc_inf, rvc_inf): |
| /* Inf / Inf = NaN. */ |
| get_canonical_qnan (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_zero, rvc_inf): |
| /* 0 / ANY = 0. */ |
| case CLASS2 (rvc_normal, rvc_inf): |
| /* R / Inf = 0. */ |
| get_zero (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_zero): |
| /* R / 0 = Inf. */ |
| case CLASS2 (rvc_inf, rvc_zero): |
| /* Inf / 0 = Inf. */ |
| get_inf (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_zero, rvc_nan): |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| /* ANY / NaN = NaN. */ |
| *r = *b; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_nan, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| /* NaN / ANY = NaN. */ |
| *r = *a; |
| r->sign = sign; |
| return false; |
| |
| case CLASS2 (rvc_inf, rvc_normal): |
| /* Inf / R = Inf. */ |
| get_inf (r, sign); |
| return false; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (r == a || r == b) |
| rr = &t; |
| else |
| rr = r; |
| |
| /* Make sure all fields in the result are initialized. */ |
| get_zero (rr, 0); |
| rr->cl = rvc_normal; |
| rr->sign = sign; |
| |
| exp = REAL_EXP (a) - REAL_EXP (b) + 1; |
| if (exp > MAX_EXP) |
| { |
| get_inf (r, sign); |
| return true; |
| } |
| if (exp < -MAX_EXP) |
| { |
| get_zero (r, sign); |
| return true; |
| } |
| SET_REAL_EXP (rr, exp); |
| |
| inexact = div_significands (rr, a, b); |
| |
| /* Re-normalize the result. */ |
| normalize (rr); |
| rr->sig[0] |= inexact; |
| |
| if (rr != r) |
| *r = t; |
| |
| return inexact; |
| } |
| |
| /* Return a tri-state comparison of A vs B. Return NAN_RESULT if |
| one of the two operands is a NaN. */ |
| |
| static int |
| do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, |
| int nan_result) |
| { |
| int ret; |
| |
| switch (CLASS2 (a->cl, b->cl)) |
| { |
| case CLASS2 (rvc_zero, rvc_zero): |
| /* Sign of zero doesn't matter for compares. */ |
| return 0; |
| |
| case CLASS2 (rvc_inf, rvc_zero): |
| case CLASS2 (rvc_inf, rvc_normal): |
| case CLASS2 (rvc_normal, rvc_zero): |
| return (a->sign ? -1 : 1); |
| |
| case CLASS2 (rvc_inf, rvc_inf): |
| return -a->sign - -b->sign; |
| |
| case CLASS2 (rvc_zero, rvc_normal): |
| case CLASS2 (rvc_zero, rvc_inf): |
| case CLASS2 (rvc_normal, rvc_inf): |
| return (b->sign ? 1 : -1); |
| |
| case CLASS2 (rvc_zero, rvc_nan): |
| case CLASS2 (rvc_normal, rvc_nan): |
| case CLASS2 (rvc_inf, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_nan): |
| case CLASS2 (rvc_nan, rvc_zero): |
| case CLASS2 (rvc_nan, rvc_normal): |
| case CLASS2 (rvc_nan, rvc_inf): |
| return nan_result; |
| |
| case CLASS2 (rvc_normal, rvc_normal): |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (a->sign != b->sign) |
| return -a->sign - -b->sign; |
| |
| if (REAL_EXP (a) > REAL_EXP (b)) |
| ret = 1; |
| else if (REAL_EXP (a) < REAL_EXP (b)) |
| ret = -1; |
| else |
| ret = cmp_significands (a, b); |
| |
| return (a->sign ? -ret : ret); |
| } |
| |
| /* Return A truncated to an integral value toward zero. */ |
| |
| static void |
| do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) |
| { |
| *r = *a; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| case rvc_nan: |
| break; |
| |
| case rvc_normal: |
| if (REAL_EXP (r) <= 0) |
| get_zero (r, r->sign); |
| else if (REAL_EXP (r) < SIGNIFICAND_BITS) |
| clear_significand_below (r, SIGNIFICAND_BITS - REAL_EXP (r)); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Perform the binary or unary operation described by CODE. |
| For a unary operation, leave OP1 NULL. This function returns |
| true if the result may be inexact due to loss of precision. */ |
| |
| bool |
| real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0, |
| const REAL_VALUE_TYPE *op1) |
| { |
| enum tree_code code = icode; |
| |
| switch (code) |
| { |
| case PLUS_EXPR: |
| return do_add (r, op0, op1, 0); |
| |
| case MINUS_EXPR: |
| return do_add (r, op0, op1, 1); |
| |
| case MULT_EXPR: |
| return do_multiply (r, op0, op1); |
| |
| case RDIV_EXPR: |
| return do_divide (r, op0, op1); |
| |
| case MIN_EXPR: |
| if (op1->cl == rvc_nan) |
| *r = *op1; |
| else if (do_compare (op0, op1, -1) < 0) |
| *r = *op0; |
| else |
| *r = *op1; |
| break; |
| |
| case MAX_EXPR: |
| if (op1->cl == rvc_nan) |
| *r = *op1; |
| else if (do_compare (op0, op1, 1) < 0) |
| *r = *op1; |
| else |
| *r = *op0; |
| break; |
| |
| case NEGATE_EXPR: |
| *r = *op0; |
| r->sign ^= 1; |
| break; |
| |
| case ABS_EXPR: |
| *r = *op0; |
| r->sign = 0; |
| break; |
| |
| case FIX_TRUNC_EXPR: |
| do_fix_trunc (r, op0); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| return false; |
| } |
| |
| /* Legacy. Similar, but return the result directly. */ |
| |
| REAL_VALUE_TYPE |
| real_arithmetic2 (int icode, const REAL_VALUE_TYPE *op0, |
| const REAL_VALUE_TYPE *op1) |
| { |
| REAL_VALUE_TYPE r; |
| real_arithmetic (&r, icode, op0, op1); |
| return r; |
| } |
| |
| bool |
| real_compare (int icode, const REAL_VALUE_TYPE *op0, |
| const REAL_VALUE_TYPE *op1) |
| { |
| enum tree_code code = icode; |
| |
| switch (code) |
| { |
| case LT_EXPR: |
| return do_compare (op0, op1, 1) < 0; |
| case LE_EXPR: |
| return do_compare (op0, op1, 1) <= 0; |
| case GT_EXPR: |
| return do_compare (op0, op1, -1) > 0; |
| case GE_EXPR: |
| return do_compare (op0, op1, -1) >= 0; |
| case EQ_EXPR: |
| return do_compare (op0, op1, -1) == 0; |
| case NE_EXPR: |
| return do_compare (op0, op1, -1) != 0; |
| case UNORDERED_EXPR: |
| return op0->cl == rvc_nan || op1->cl == rvc_nan; |
| case ORDERED_EXPR: |
| return op0->cl != rvc_nan && op1->cl != rvc_nan; |
| case UNLT_EXPR: |
| return do_compare (op0, op1, -1) < 0; |
| case UNLE_EXPR: |
| return do_compare (op0, op1, -1) <= 0; |
| case UNGT_EXPR: |
| return do_compare (op0, op1, 1) > 0; |
| case UNGE_EXPR: |
| return do_compare (op0, op1, 1) >= 0; |
| case UNEQ_EXPR: |
| return do_compare (op0, op1, 0) == 0; |
| case LTGT_EXPR: |
| return do_compare (op0, op1, 0) != 0; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Return floor log2(R). */ |
| |
| int |
| real_exponent (const REAL_VALUE_TYPE *r) |
| { |
| switch (r->cl) |
| { |
| case rvc_zero: |
| return 0; |
| case rvc_inf: |
| case rvc_nan: |
| return (unsigned int)-1 >> 1; |
| case rvc_normal: |
| return REAL_EXP (r); |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* R = OP0 * 2**EXP. */ |
| |
| void |
| real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp) |
| { |
| *r = *op0; |
| switch (r->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| case rvc_nan: |
| break; |
| |
| case rvc_normal: |
| exp += REAL_EXP (op0); |
| if (exp > MAX_EXP) |
| get_inf (r, r->sign); |
| else if (exp < -MAX_EXP) |
| get_zero (r, r->sign); |
| else |
| SET_REAL_EXP (r, exp); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Determine whether a floating-point value X is infinite. */ |
| |
| bool |
| real_isinf (const REAL_VALUE_TYPE *r) |
| { |
| return (r->cl == rvc_inf); |
| } |
| |
| /* Determine whether a floating-point value X is a NaN. */ |
| |
| bool |
| real_isnan (const REAL_VALUE_TYPE *r) |
| { |
| return (r->cl == rvc_nan); |
| } |
| |
| /* Determine whether a floating-point value X is negative. */ |
| |
| bool |
| real_isneg (const REAL_VALUE_TYPE *r) |
| { |
| return r->sign; |
| } |
| |
| /* Determine whether a floating-point value X is minus zero. */ |
| |
| bool |
| real_isnegzero (const REAL_VALUE_TYPE *r) |
| { |
| return r->sign && r->cl == rvc_zero; |
| } |
| |
| /* Compare two floating-point objects for bitwise identity. */ |
| |
| bool |
| real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b) |
| { |
| int i; |
| |
| if (a->cl != b->cl) |
| return false; |
| if (a->sign != b->sign) |
| return false; |
| |
| switch (a->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| return true; |
| |
| case rvc_normal: |
| if (REAL_EXP (a) != REAL_EXP (b)) |
| return false; |
| break; |
| |
| case rvc_nan: |
| if (a->signalling != b->signalling) |
| return false; |
| /* The significand is ignored for canonical NaNs. */ |
| if (a->canonical || b->canonical) |
| return a->canonical == b->canonical; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| for (i = 0; i < SIGSZ; ++i) |
| if (a->sig[i] != b->sig[i]) |
| return false; |
| |
| return true; |
| } |
| |
| /* Try to change R into its exact multiplicative inverse in machine |
| mode MODE. Return true if successful. */ |
| |
| bool |
| exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r) |
| { |
| const REAL_VALUE_TYPE *one = real_digit (1); |
| REAL_VALUE_TYPE u; |
| int i; |
| |
| if (r->cl != rvc_normal) |
| return false; |
| |
| /* Check for a power of two: all significand bits zero except the MSB. */ |
| for (i = 0; i < SIGSZ-1; ++i) |
| if (r->sig[i] != 0) |
| return false; |
| if (r->sig[SIGSZ-1] != SIG_MSB) |
| return false; |
| |
| /* Find the inverse and truncate to the required mode. */ |
| do_divide (&u, one, r); |
| real_convert (&u, mode, &u); |
| |
| /* The rounding may have overflowed. */ |
| if (u.cl != rvc_normal) |
| return false; |
| for (i = 0; i < SIGSZ-1; ++i) |
| if (u.sig[i] != 0) |
| return false; |
| if (u.sig[SIGSZ-1] != SIG_MSB) |
| return false; |
| |
| *r = u; |
| return true; |
| } |
| |
| /* Render R as an integer. */ |
| |
| HOST_WIDE_INT |
| real_to_integer (const REAL_VALUE_TYPE *r) |
| { |
| unsigned HOST_WIDE_INT i; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| underflow: |
| return 0; |
| |
| case rvc_inf: |
| case rvc_nan: |
| overflow: |
| i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); |
| if (!r->sign) |
| i--; |
| return i; |
| |
| case rvc_normal: |
| if (REAL_EXP (r) <= 0) |
| goto underflow; |
| /* Only force overflow for unsigned overflow. Signed overflow is |
| undefined, so it doesn't matter what we return, and some callers |
| expect to be able to use this routine for both signed and |
| unsigned conversions. */ |
| if (REAL_EXP (r) > HOST_BITS_PER_WIDE_INT) |
| goto overflow; |
| |
| if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) |
| i = r->sig[SIGSZ-1]; |
| else |
| { |
| gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG); |
| i = r->sig[SIGSZ-1]; |
| i = i << (HOST_BITS_PER_LONG - 1) << 1; |
| i |= r->sig[SIGSZ-2]; |
| } |
| |
| i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r); |
| |
| if (r->sign) |
| i = -i; |
| return i; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| |
| /* Likewise, but to an integer pair, HI+LOW. */ |
| |
| void |
| real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, |
| const REAL_VALUE_TYPE *r) |
| { |
| REAL_VALUE_TYPE t; |
| HOST_WIDE_INT low, high; |
| int exp; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| underflow: |
| low = high = 0; |
| break; |
| |
| case rvc_inf: |
| case rvc_nan: |
| overflow: |
| high = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); |
| if (r->sign) |
| low = 0; |
| else |
| { |
| high--; |
| low = -1; |
| } |
| break; |
| |
| case rvc_normal: |
| exp = REAL_EXP (r); |
| if (exp <= 0) |
| goto underflow; |
| /* Only force overflow for unsigned overflow. Signed overflow is |
| undefined, so it doesn't matter what we return, and some callers |
| expect to be able to use this routine for both signed and |
| unsigned conversions. */ |
| if (exp > 2*HOST_BITS_PER_WIDE_INT) |
| goto overflow; |
| |
| rshift_significand (&t, r, 2*HOST_BITS_PER_WIDE_INT - exp); |
| if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) |
| { |
| high = t.sig[SIGSZ-1]; |
| low = t.sig[SIGSZ-2]; |
| } |
| else |
| { |
| gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG); |
| high = t.sig[SIGSZ-1]; |
| high = high << (HOST_BITS_PER_LONG - 1) << 1; |
| high |= t.sig[SIGSZ-2]; |
| |
| low = t.sig[SIGSZ-3]; |
| low = low << (HOST_BITS_PER_LONG - 1) << 1; |
| low |= t.sig[SIGSZ-4]; |
| } |
| |
| if (r->sign) |
| { |
| if (low == 0) |
| high = -high; |
| else |
| low = -low, high = ~high; |
| } |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| *plow = low; |
| *phigh = high; |
| } |
| |
| /* A subroutine of real_to_decimal. Compute the quotient and remainder |
| of NUM / DEN. Return the quotient and place the remainder in NUM. |
| It is expected that NUM / DEN are close enough that the quotient is |
| small. */ |
| |
| static unsigned long |
| rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den) |
| { |
| unsigned long q, msb; |
| int expn = REAL_EXP (num), expd = REAL_EXP (den); |
| |
| if (expn < expd) |
| return 0; |
| |
| q = msb = 0; |
| goto start; |
| do |
| { |
| msb = num->sig[SIGSZ-1] & SIG_MSB; |
| q <<= 1; |
| lshift_significand_1 (num, num); |
| start: |
| if (msb || cmp_significands (num, den) >= 0) |
| { |
| sub_significands (num, num, den, 0); |
| q |= 1; |
| } |
| } |
| while (--expn >= expd); |
| |
| SET_REAL_EXP (num, expd); |
| normalize (num); |
| |
| return q; |
| } |
| |
| /* Render R as a decimal floating point constant. Emit DIGITS significant |
| digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the |
| maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing |
| zeros. */ |
| |
| #define M_LOG10_2 0.30102999566398119521 |
| |
| void |
| real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, |
| size_t digits, int crop_trailing_zeros) |
| { |
| const REAL_VALUE_TYPE *one, *ten; |
| REAL_VALUE_TYPE r, pten, u, v; |
| int dec_exp, cmp_one, digit; |
| size_t max_digits; |
| char *p, *first, *last; |
| bool sign; |
| |
| r = *r_orig; |
| switch (r.cl) |
| { |
| case rvc_zero: |
| strcpy (str, (r.sign ? "-0.0" : "0.0")); |
| return; |
| case rvc_normal: |
| break; |
| case rvc_inf: |
| strcpy (str, (r.sign ? "-Inf" : "+Inf")); |
| return; |
| case rvc_nan: |
| /* ??? Print the significand as well, if not canonical? */ |
| strcpy (str, (r.sign ? "-NaN" : "+NaN")); |
| return; |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* Bound the number of digits printed by the size of the representation. */ |
| max_digits = SIGNIFICAND_BITS * M_LOG10_2; |
| if (digits == 0 || digits > max_digits) |
| digits = max_digits; |
| |
| /* Estimate the decimal exponent, and compute the length of the string it |
| will print as. Be conservative and add one to account for possible |
| overflow or rounding error. */ |
| dec_exp = REAL_EXP (&r) * M_LOG10_2; |
| for (max_digits = 1; dec_exp ; max_digits++) |
| dec_exp /= 10; |
| |
| /* Bound the number of digits printed by the size of the output buffer. */ |
| max_digits = buf_size - 1 - 1 - 2 - max_digits - 1; |
| gcc_assert (max_digits <= buf_size); |
| if (digits > max_digits) |
| digits = max_digits; |
| |
| one = real_digit (1); |
| ten = ten_to_ptwo (0); |
| |
| sign = r.sign; |
| r.sign = 0; |
| |
| dec_exp = 0; |
| pten = *one; |
| |
| cmp_one = do_compare (&r, one, 0); |
| if (cmp_one > 0) |
| { |
| int m; |
| |
| /* Number is greater than one. Convert significand to an integer |
| and strip trailing decimal zeros. */ |
| |
| u = r; |
| SET_REAL_EXP (&u, SIGNIFICAND_BITS - 1); |
| |
| /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS. */ |
| m = floor_log2 (max_digits); |
| |
| /* Iterate over the bits of the possible powers of 10 that might |
| be present in U and eliminate them. That is, if we find that |
| 10**2**M divides U evenly, keep the division and increase |
| DEC_EXP by 2**M. */ |
| do |
| { |
| REAL_VALUE_TYPE t; |
| |
| do_divide (&t, &u, ten_to_ptwo (m)); |
| do_fix_trunc (&v, &t); |
| if (cmp_significands (&v, &t) == 0) |
| { |
| u = t; |
| dec_exp += 1 << m; |
| } |
| } |
| while (--m >= 0); |
| |
| /* Revert the scaling to integer that we performed earlier. */ |
| SET_REAL_EXP (&u, REAL_EXP (&u) + REAL_EXP (&r) |
| - (SIGNIFICAND_BITS - 1)); |
| r = u; |
| |
| /* Find power of 10. Do this by dividing out 10**2**M when |
| this is larger than the current remainder. Fill PTEN with |
| the power of 10 that we compute. */ |
| if (REAL_EXP (&r) > 0) |
| { |
| m = floor_log2 ((int)(REAL_EXP (&r) * M_LOG10_2)) + 1; |
| do |
| { |
| const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m); |
| if (do_compare (&u, ptentwo, 0) >= 0) |
| { |
| do_divide (&u, &u, ptentwo); |
| do_multiply (&pten, &pten, ptentwo); |
| dec_exp += 1 << m; |
| } |
| } |
| while (--m >= 0); |
| } |
| else |
| /* We managed to divide off enough tens in the above reduction |
| loop that we've now got a negative exponent. Fall into the |
| less-than-one code to compute the proper value for PTEN. */ |
| cmp_one = -1; |
| } |
| if (cmp_one < 0) |
| { |
| int m; |
| |
| /* Number is less than one. Pad significand with leading |
| decimal zeros. */ |
| |
| v = r; |
| while (1) |
| { |
| /* Stop if we'd shift bits off the bottom. */ |
| if (v.sig[0] & 7) |
| break; |
| |
| do_multiply (&u, &v, ten); |
| |
| /* Stop if we're now >= 1. */ |
| if (REAL_EXP (&u) > 0) |
| break; |
| |
| v = u; |
| dec_exp -= 1; |
| } |
| r = v; |
| |
| /* Find power of 10. Do this by multiplying in P=10**2**M when |
| the current remainder is smaller than 1/P. Fill PTEN with the |
| power of 10 that we compute. */ |
| m = floor_log2 ((int)(-REAL_EXP (&r) * M_LOG10_2)) + 1; |
| do |
| { |
| const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m); |
| const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m); |
| |
| if (do_compare (&v, ptenmtwo, 0) <= 0) |
| { |
| do_multiply (&v, &v, ptentwo); |
| do_multiply (&pten, &pten, ptentwo); |
| dec_exp -= 1 << m; |
| } |
| } |
| while (--m >= 0); |
| |
| /* Invert the positive power of 10 that we've collected so far. */ |
| do_divide (&pten, one, &pten); |
| } |
| |
| p = str; |
| if (sign) |
| *p++ = '-'; |
| first = p++; |
| |
| /* At this point, PTEN should contain the nearest power of 10 smaller |
| than R, such that this division produces the first digit. |
| |
| Using a divide-step primitive that returns the complete integral |
| remainder avoids the rounding error that would be produced if |
| we were to use do_divide here and then simply multiply by 10 for |
| each subsequent digit. */ |
| |
| digit = rtd_divmod (&r, &pten); |
| |
| /* Be prepared for error in that division via underflow ... */ |
| if (digit == 0 && cmp_significand_0 (&r)) |
| { |
| /* Multiply by 10 and try again. */ |
| do_multiply (&r, &r, ten); |
| digit = rtd_divmod (&r, &pten); |
| dec_exp -= 1; |
| gcc_assert (digit != 0); |
| } |
| |
| /* ... or overflow. */ |
| if (digit == 10) |
| { |
| *p++ = '1'; |
| if (--digits > 0) |
| *p++ = '0'; |
| dec_exp += 1; |
| } |
| else |
| { |
| gcc_assert (digit <= 10); |
| *p++ = digit + '0'; |
| } |
| |
| /* Generate subsequent digits. */ |
| while (--digits > 0) |
| { |
| do_multiply (&r, &r, ten); |
| digit = rtd_divmod (&r, &pten); |
| *p++ = digit + '0'; |
| } |
| last = p; |
| |
| /* Generate one more digit with which to do rounding. */ |
| do_multiply (&r, &r, ten); |
| digit = rtd_divmod (&r, &pten); |
| |
| /* Round the result. */ |
| if (digit == 5) |
| { |
| /* Round to nearest. If R is nonzero there are additional |
| nonzero digits to be extracted. */ |
| if (cmp_significand_0 (&r)) |
| digit++; |
| /* Round to even. */ |
| else if ((p[-1] - '0') & 1) |
| digit++; |
| } |
| if (digit > 5) |
| { |
| while (p > first) |
| { |
| digit = *--p; |
| if (digit == '9') |
| *p = '0'; |
| else |
| { |
| *p = digit + 1; |
| break; |
| } |
| } |
| |
| /* Carry out of the first digit. This means we had all 9's and |
| now have all 0's. "Prepend" a 1 by overwriting the first 0. */ |
| if (p == first) |
| { |
| first[1] = '1'; |
| dec_exp++; |
| } |
| } |
| |
| /* Insert the decimal point. */ |
| first[0] = first[1]; |
| first[1] = '.'; |
| |
| /* If requested, drop trailing zeros. Never crop past "1.0". */ |
| if (crop_trailing_zeros) |
| while (last > first + 3 && last[-1] == '0') |
| last--; |
| |
| /* Append the exponent. */ |
| sprintf (last, "e%+d", dec_exp); |
| } |
| |
| /* Render R as a hexadecimal floating point constant. Emit DIGITS |
| significant digits in the result, bounded by BUF_SIZE. If DIGITS is 0, |
| choose the maximum for the representation. If CROP_TRAILING_ZEROS, |
| strip trailing zeros. */ |
| |
| void |
| real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size, |
| size_t digits, int crop_trailing_zeros) |
| { |
| int i, j, exp = REAL_EXP (r); |
| char *p, *first; |
| char exp_buf[16]; |
| size_t max_digits; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| exp = 0; |
| break; |
| case rvc_normal: |
| break; |
| case rvc_inf: |
| strcpy (str, (r->sign ? "-Inf" : "+Inf")); |
| return; |
| case rvc_nan: |
| /* ??? Print the significand as well, if not canonical? */ |
| strcpy (str, (r->sign ? "-NaN" : "+NaN")); |
| return; |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (digits == 0) |
| digits = SIGNIFICAND_BITS / 4; |
| |
| /* Bound the number of digits printed by the size of the output buffer. */ |
| |
| sprintf (exp_buf, "p%+d", exp); |
| max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1; |
| gcc_assert (max_digits <= buf_size); |
| if (digits > max_digits) |
| digits = max_digits; |
| |
| p = str; |
| if (r->sign) |
| *p++ = '-'; |
| *p++ = '0'; |
| *p++ = 'x'; |
| *p++ = '0'; |
| *p++ = '.'; |
| first = p; |
| |
| for (i = SIGSZ - 1; i >= 0; --i) |
| for (j = HOST_BITS_PER_LONG - 4; j >= 0; j -= 4) |
| { |
| *p++ = "0123456789abcdef"[(r->sig[i] >> j) & 15]; |
| if (--digits == 0) |
| goto out; |
| } |
| |
| out: |
| if (crop_trailing_zeros) |
| while (p > first + 1 && p[-1] == '0') |
| p--; |
| |
| sprintf (p, "p%+d", exp); |
| } |
| |
| /* Initialize R from a decimal or hexadecimal string. The string is |
| assumed to have been syntax checked already. */ |
| |
| void |
| real_from_string (REAL_VALUE_TYPE *r, const char *str) |
| { |
| int exp = 0; |
| bool sign = false; |
| |
| get_zero (r, 0); |
| |
| if (*str == '-') |
| { |
| sign = true; |
| str++; |
| } |
| else if (*str == '+') |
| str++; |
| |
| if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) |
| { |
| /* Hexadecimal floating point. */ |
| int pos = SIGNIFICAND_BITS - 4, d; |
| |
| str += 2; |
| |
| while (*str == '0') |
| str++; |
| while (1) |
| { |
| d = hex_value (*str); |
| if (d == _hex_bad) |
| break; |
| if (pos >= 0) |
| { |
| r->sig[pos / HOST_BITS_PER_LONG] |
| |= (unsigned long) d << (pos % HOST_BITS_PER_LONG); |
| pos -= 4; |
| } |
| exp += 4; |
| str++; |
| } |
| if (*str == '.') |
| { |
| str++; |
| if (pos == SIGNIFICAND_BITS - 4) |
| { |
| while (*str == '0') |
| str++, exp -= 4; |
| } |
| while (1) |
| { |
| d = hex_value (*str); |
| if (d == _hex_bad) |
| break; |
| if (pos >= 0) |
| { |
| r->sig[pos / HOST_BITS_PER_LONG] |
| |= (unsigned long) d << (pos % HOST_BITS_PER_LONG); |
| pos -= 4; |
| } |
| str++; |
| } |
| } |
| if (*str == 'p' || *str == 'P') |
| { |
| bool exp_neg = false; |
| |
| str++; |
| if (*str == '-') |
| { |
| exp_neg = true; |
| str++; |
| } |
| else if (*str == '+') |
| str++; |
| |
| d = 0; |
| while (ISDIGIT (*str)) |
| { |
| d *= 10; |
| d += *str - '0'; |
| if (d > MAX_EXP) |
| { |
| /* Overflowed the exponent. */ |
| if (exp_neg) |
| goto underflow; |
| else |
| goto overflow; |
| } |
| str++; |
| } |
| if (exp_neg) |
| d = -d; |
| |
| exp += d; |
| } |
| |
| r->cl = rvc_normal; |
| SET_REAL_EXP (r, exp); |
| |
| normalize (r); |
| } |
| else |
| { |
| /* Decimal floating point. */ |
| const REAL_VALUE_TYPE *ten = ten_to_ptwo (0); |
| int d; |
| |
| while (*str == '0') |
| str++; |
| while (ISDIGIT (*str)) |
| { |
| d = *str++ - '0'; |
| do_multiply (r, r, ten); |
| if (d) |
| do_add (r, r, real_digit (d), 0); |
| } |
| if (*str == '.') |
| { |
| str++; |
| if (r->cl == rvc_zero) |
| { |
| while (*str == '0') |
| str++, exp--; |
| } |
| while (ISDIGIT (*str)) |
| { |
| d = *str++ - '0'; |
| do_multiply (r, r, ten); |
| if (d) |
| do_add (r, r, real_digit (d), 0); |
| exp--; |
| } |
| } |
| |
| if (*str == 'e' || *str == 'E') |
| { |
| bool exp_neg = false; |
| |
| str++; |
| if (*str == '-') |
| { |
| exp_neg = true; |
| str++; |
| } |
| else if (*str == '+') |
| str++; |
| |
| d = 0; |
| while (ISDIGIT (*str)) |
| { |
| d *= 10; |
| d += *str - '0'; |
| if (d > MAX_EXP) |
| { |
| /* Overflowed the exponent. */ |
| if (exp_neg) |
| goto underflow; |
| else |
| goto overflow; |
| } |
| str++; |
| } |
| if (exp_neg) |
| d = -d; |
| exp += d; |
| } |
| |
| if (exp) |
| times_pten (r, exp); |
| } |
| |
| r->sign = sign; |
| return; |
| |
| underflow: |
| get_zero (r, sign); |
| return; |
| |
| overflow: |
| get_inf (r, sign); |
| return; |
| } |
| |
| /* Legacy. Similar, but return the result directly. */ |
| |
| REAL_VALUE_TYPE |
| real_from_string2 (const char *s, enum machine_mode mode) |
| { |
| REAL_VALUE_TYPE r; |
| |
| real_from_string (&r, s); |
| if (mode != VOIDmode) |
| real_convert (&r, mode, &r); |
| |
| return r; |
| } |
| |
| /* Initialize R from the integer pair HIGH+LOW. */ |
| |
| void |
| real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode, |
| unsigned HOST_WIDE_INT low, HOST_WIDE_INT high, |
| int unsigned_p) |
| { |
| if (low == 0 && high == 0) |
| get_zero (r, 0); |
| else |
| { |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_normal; |
| r->sign = high < 0 && !unsigned_p; |
| SET_REAL_EXP (r, 2 * HOST_BITS_PER_WIDE_INT); |
| |
| if (r->sign) |
| { |
| high = ~high; |
| if (low == 0) |
| high += 1; |
| else |
| low = -low; |
| } |
| |
| if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT) |
| { |
| r->sig[SIGSZ-1] = high; |
| r->sig[SIGSZ-2] = low; |
| } |
| else |
| { |
| gcc_assert (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT); |
| r->sig[SIGSZ-1] = high >> (HOST_BITS_PER_LONG - 1) >> 1; |
| r->sig[SIGSZ-2] = high; |
| r->sig[SIGSZ-3] = low >> (HOST_BITS_PER_LONG - 1) >> 1; |
| r->sig[SIGSZ-4] = low; |
| } |
| |
| normalize (r); |
| } |
| |
| if (mode != VOIDmode) |
| real_convert (r, mode, r); |
| } |
| |
| /* Returns 10**2**N. */ |
| |
| static const REAL_VALUE_TYPE * |
| ten_to_ptwo (int n) |
| { |
| static REAL_VALUE_TYPE tens[EXP_BITS]; |
| |
| gcc_assert (n >= 0); |
| gcc_assert (n < EXP_BITS); |
| |
| if (tens[n].cl == rvc_zero) |
| { |
| if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4)) |
| { |
| HOST_WIDE_INT t = 10; |
| int i; |
| |
| for (i = 0; i < n; ++i) |
| t *= t; |
| |
| real_from_integer (&tens[n], VOIDmode, t, 0, 1); |
| } |
| else |
| { |
| const REAL_VALUE_TYPE *t = ten_to_ptwo (n - 1); |
| do_multiply (&tens[n], t, t); |
| } |
| } |
| |
| return &tens[n]; |
| } |
| |
| /* Returns 10**(-2**N). */ |
| |
| static const REAL_VALUE_TYPE * |
| ten_to_mptwo (int n) |
| { |
| static REAL_VALUE_TYPE tens[EXP_BITS]; |
| |
| gcc_assert (n >= 0); |
| gcc_assert (n < EXP_BITS); |
| |
| if (tens[n].cl == rvc_zero) |
| do_divide (&tens[n], real_digit (1), ten_to_ptwo (n)); |
| |
| return &tens[n]; |
| } |
| |
| /* Returns N. */ |
| |
| static const REAL_VALUE_TYPE * |
| real_digit (int n) |
| { |
| static REAL_VALUE_TYPE num[10]; |
| |
| gcc_assert (n >= 0); |
| gcc_assert (n <= 9); |
| |
| if (n > 0 && num[n].cl == rvc_zero) |
| real_from_integer (&num[n], VOIDmode, n, 0, 1); |
| |
| return &num[n]; |
| } |
| |
| /* Multiply R by 10**EXP. */ |
| |
| static void |
| times_pten (REAL_VALUE_TYPE *r, int exp) |
| { |
| REAL_VALUE_TYPE pten, *rr; |
| bool negative = (exp < 0); |
| int i; |
| |
| if (negative) |
| { |
| exp = -exp; |
| pten = *real_digit (1); |
| rr = &pten; |
| } |
| else |
| rr = r; |
| |
| for (i = 0; exp > 0; ++i, exp >>= 1) |
| if (exp & 1) |
| do_multiply (rr, rr, ten_to_ptwo (i)); |
| |
| if (negative) |
| do_divide (r, r, &pten); |
| } |
| |
| /* Fills R with +Inf. */ |
| |
| void |
| real_inf (REAL_VALUE_TYPE *r) |
| { |
| get_inf (r, 0); |
| } |
| |
| /* Fills R with a NaN whose significand is described by STR. If QUIET, |
| we force a QNaN, else we force an SNaN. The string, if not empty, |
| is parsed as a number and placed in the significand. Return true |
| if the string was successfully parsed. */ |
| |
| bool |
| real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet, |
| enum machine_mode mode) |
| { |
| const struct real_format *fmt; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| |
| if (*str == 0) |
| { |
| if (quiet) |
| get_canonical_qnan (r, 0); |
| else |
| get_canonical_snan (r, 0); |
| } |
| else |
| { |
| int base = 10, d; |
| bool neg = false; |
| |
| memset (r, 0, sizeof (*r)); |
| r->cl = rvc_nan; |
| |
| /* Parse akin to strtol into the significand of R. */ |
| |
| while (ISSPACE (*str)) |
| str++; |
| if (*str == '-') |
| str++, neg = true; |
| else if (*str == '+') |
| str++; |
| if (*str == '0') |
| { |
| if (*++str == 'x') |
| str++, base = 16; |
| else |
| base = 8; |
| } |
| |
| while ((d = hex_value (*str)) < base) |
| { |
| REAL_VALUE_TYPE u; |
| |
| switch (base) |
| { |
| case 8: |
| lshift_significand (r, r, 3); |
| break; |
| case 16: |
| lshift_significand (r, r, 4); |
| break; |
| case 10: |
| lshift_significand_1 (&u, r); |
| lshift_significand (r, r, 3); |
| add_significands (r, r, &u); |
| break; |
| default: |
| gcc_unreachable (); |
| } |
| |
| get_zero (&u, 0); |
| u.sig[0] = d; |
| add_significands (r, r, &u); |
| |
| str++; |
| } |
| |
| /* Must have consumed the entire string for success. */ |
| if (*str != 0) |
| return false; |
| |
| /* Shift the significand into place such that the bits |
| are in the most significant bits for the format. */ |
| lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan); |
| |
| /* Our MSB is always unset for NaNs. */ |
| r->sig[SIGSZ-1] &= ~SIG_MSB; |
| |
| /* Force quiet or signalling NaN. */ |
| r->signalling = !quiet; |
| } |
| |
| return true; |
| } |
| |
| /* Fills R with the largest finite value representable in mode MODE. |
| If SIGN is nonzero, R is set to the most negative finite value. */ |
| |
| void |
| real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) |
| { |
| const struct real_format *fmt; |
| int np2; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| |
| r->cl = rvc_normal; |
| r->sign = sign; |
| r->signalling = 0; |
| r->canonical = 0; |
| SET_REAL_EXP (r, fmt->emax * fmt->log2_b); |
| |
| np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b; |
| memset (r->sig, -1, SIGSZ * sizeof (unsigned long)); |
| clear_significand_below (r, np2); |
| /* APPLE LOCAL begin mainline */ |
| |
| if (fmt->pnan < fmt->p) |
| /* This is an IBM extended double format made up of two IEEE |
| doubles. The value of the long double is the sum of the |
| values of the two parts. The most significant part is |
| required to be the value of the long double rounded to the |
| nearest double. Rounding means we need a slightly smaller |
| value for LDBL_MAX. */ |
| clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan); |
| /* APPLE LOCAL end mainline */ |
| } |
| |
| /* Fills R with 2**N. */ |
| |
| void |
| real_2expN (REAL_VALUE_TYPE *r, int n) |
| { |
| memset (r, 0, sizeof (*r)); |
| |
| n++; |
| if (n > MAX_EXP) |
| r->cl = rvc_inf; |
| else if (n < -MAX_EXP) |
| ; |
| else |
| { |
| r->cl = rvc_normal; |
| SET_REAL_EXP (r, n); |
| r->sig[SIGSZ-1] = SIG_MSB; |
| } |
| } |
| |
| |
| static void |
| round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) |
| { |
| int p2, np2, i, w; |
| unsigned long sticky; |
| bool guard, lsb; |
| int emin2m1, emax2; |
| |
| p2 = fmt->p * fmt->log2_b; |
| emin2m1 = (fmt->emin - 1) * fmt->log2_b; |
| emax2 = fmt->emax * fmt->log2_b; |
| |
| np2 = SIGNIFICAND_BITS - p2; |
| switch (r->cl) |
| { |
| underflow: |
| get_zero (r, r->sign); |
| case rvc_zero: |
| if (!fmt->has_signed_zero) |
| r->sign = 0; |
| return; |
| |
| overflow: |
| get_inf (r, r->sign); |
| case rvc_inf: |
| return; |
| |
| case rvc_nan: |
| clear_significand_below (r, np2); |
| return; |
| |
| case rvc_normal: |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| /* If we're not base2, normalize the exponent to a multiple of |
| the true base. */ |
| if (fmt->log2_b != 1) |
| { |
| int shift = REAL_EXP (r) & (fmt->log2_b - 1); |
| if (shift) |
| { |
| shift = fmt->log2_b - shift; |
| r->sig[0] |= sticky_rshift_significand (r, r, shift); |
| SET_REAL_EXP (r, REAL_EXP (r) + shift); |
| } |
| } |
| |
| /* Check the range of the exponent. If we're out of range, |
| either underflow or overflow. */ |
| if (REAL_EXP (r) > emax2) |
| goto overflow; |
| else if (REAL_EXP (r) <= emin2m1) |
| { |
| int diff; |
| |
| if (!fmt->has_denorm) |
| { |
| /* Don't underflow completely until we've had a chance to round. */ |
| if (REAL_EXP (r) < emin2m1) |
| goto underflow; |
| } |
| else |
| { |
| diff = emin2m1 - REAL_EXP (r) + 1; |
| if (diff > p2) |
| goto underflow; |
| |
| /* De-normalize the significand. */ |
| r->sig[0] |= sticky_rshift_significand (r, r, diff); |
| SET_REAL_EXP (r, REAL_EXP (r) + diff); |
| } |
| } |
| |
| /* There are P2 true significand bits, followed by one guard bit, |
| followed by one sticky bit, followed by stuff. Fold nonzero |
| stuff into the sticky bit. */ |
| |
| sticky = 0; |
| for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i) |
| sticky |= r->sig[i]; |
| sticky |= |
| r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1); |
| |
| guard = test_significand_bit (r, np2 - 1); |
| lsb = test_significand_bit (r, np2); |
| |
| /* Round to even. */ |
| if (guard && (sticky || lsb)) |
| { |
| REAL_VALUE_TYPE u; |
| get_zero (&u, 0); |
| set_significand_bit (&u, np2); |
| |
| if (add_significands (r, r, &u)) |
| { |
| /* Overflow. Means the significand had been all ones, and |
| is now all zeros. Need to increase the exponent, and |
| possibly re-normalize it. */ |
| SET_REAL_EXP (r, REAL_EXP (r) + 1); |
| if (REAL_EXP (r) > emax2) |
| goto overflow; |
| r->sig[SIGSZ-1] = SIG_MSB; |
| |
| if (fmt->log2_b != 1) |
| { |
| int shift = REAL_EXP (r) & (fmt->log2_b - 1); |
| if (shift) |
| { |
| shift = fmt->log2_b - shift; |
| rshift_significand (r, r, shift); |
| SET_REAL_EXP (r, REAL_EXP (r) + shift); |
| if (REAL_EXP (r) > emax2) |
| goto overflow; |
| } |
| } |
| } |
| } |
| |
| /* Catch underflow that we deferred until after rounding. */ |
| if (REAL_EXP (r) <= emin2m1) |
| goto underflow; |
| |
| /* Clear out trailing garbage. */ |
| clear_significand_below (r, np2); |
| } |
| |
| /* Extend or truncate to a new mode. */ |
| |
| void |
| real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode, |
| const REAL_VALUE_TYPE *a) |
| { |
| const struct real_format *fmt; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| |
| *r = *a; |
| round_for_format (fmt, r); |
| |
| /* round_for_format de-normalizes denormals. Undo just that part. */ |
| if (r->cl == rvc_normal) |
| normalize (r); |
| } |
| |
| /* Legacy. Likewise, except return the struct directly. */ |
| |
| REAL_VALUE_TYPE |
| real_value_truncate (enum machine_mode mode, REAL_VALUE_TYPE a) |
| { |
| REAL_VALUE_TYPE r; |
| real_convert (&r, mode, &a); |
| return r; |
| } |
| |
| /* Return true if truncating to MODE is exact. */ |
| |
| bool |
| exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a) |
| { |
| REAL_VALUE_TYPE t; |
| real_convert (&t, mode, a); |
| return real_identical (&t, a); |
| } |
| |
| /* Write R to the given target format. Place the words of the result |
| in target word order in BUF. There are always 32 bits in each |
| long, no matter the size of the host long. |
| |
| Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */ |
| |
| long |
| real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig, |
| const struct real_format *fmt) |
| { |
| REAL_VALUE_TYPE r; |
| long buf1; |
| |
| r = *r_orig; |
| round_for_format (fmt, &r); |
| |
| if (!buf) |
| buf = &buf1; |
| (*fmt->encode) (fmt, buf, &r); |
| |
| return *buf; |
| } |
| |
| /* Similar, but look up the format from MODE. */ |
| |
| long |
| real_to_target (long *buf, const REAL_VALUE_TYPE *r, enum machine_mode mode) |
| { |
| const struct real_format *fmt; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| |
| return real_to_target_fmt (buf, r, fmt); |
| } |
| |
| /* Read R from the given target format. Read the words of the result |
| in target word order in BUF. There are always 32 bits in each |
| long, no matter the size of the host long. */ |
| |
| void |
| real_from_target_fmt (REAL_VALUE_TYPE *r, const long *buf, |
| const struct real_format *fmt) |
| { |
| (*fmt->decode) (fmt, r, buf); |
| } |
| |
| /* Similar, but look up the format from MODE. */ |
| |
| void |
| real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode) |
| { |
| const struct real_format *fmt; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| gcc_assert (fmt); |
| |
| (*fmt->decode) (fmt, r, buf); |
| } |
| |
| /* Return the number of bits in the significand for MODE. */ |
| /* ??? Legacy. Should get access to real_format directly. */ |
| |
| int |
| significand_size (enum machine_mode mode) |
| { |
| const struct real_format *fmt; |
| |
| fmt = REAL_MODE_FORMAT (mode); |
| if (fmt == NULL) |
| return 0; |
| |
| return fmt->p * fmt->log2_b; |
| } |
| |
| /* Return a hash value for the given real value. */ |
| /* ??? The "unsigned int" return value is intended to be hashval_t, |
| but I didn't want to pull hashtab.h into real.h. */ |
| |
| unsigned int |
| real_hash (const REAL_VALUE_TYPE *r) |
| { |
| unsigned int h; |
| size_t i; |
| |
| h = r->cl | (r->sign << 2); |
| switch (r->cl) |
| { |
| case rvc_zero: |
| case rvc_inf: |
| return h; |
| |
| case rvc_normal: |
| h |= REAL_EXP (r) << 3; |
| break; |
| |
| case rvc_nan: |
| if (r->signalling) |
| h ^= (unsigned int)-1; |
| if (r->canonical) |
| return h; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (sizeof(unsigned long) > sizeof(unsigned int)) |
| for (i = 0; i < SIGSZ; ++i) |
| { |
| unsigned long s = r->sig[i]; |
| h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2)); |
| } |
| else |
| for (i = 0; i < SIGSZ; ++i) |
| h ^= r->sig[i]; |
| |
| return h; |
| } |
| |
| /* IEEE single-precision format. */ |
| |
| static void encode_ieee_single (const struct real_format *fmt, |
| long *, const REAL_VALUE_TYPE *); |
| static void decode_ieee_single (const struct real_format *, |
| REAL_VALUE_TYPE *, const long *); |
| |
| static void |
| encode_ieee_single (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| unsigned long image, sig, exp; |
| unsigned long sign = r->sign; |
| bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; |
| |
| image = sign << 31; |
| sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| break; |
| |
| case rvc_inf: |
| if (fmt->has_inf) |
| image |= 255 << 23; |
| else |
| image |= 0x7fffffff; |
| break; |
| |
| case rvc_nan: |
| if (fmt->has_nans) |
| { |
| if (r->canonical) |
| sig = 0; |
| if (r->signalling == fmt->qnan_msb_set) |
| sig &= ~(1 << 22); |
| else |
| sig |= 1 << 22; |
| /* We overload qnan_msb_set here: it's only clear for |
| mips_ieee_single, which wants all mantissa bits but the |
| quiet/signalling one set in canonical NaNs (at least |
| Quiet ones). */ |
| if (r->canonical && !fmt->qnan_msb_set) |
| sig |= (1 << 22) - 1; |
| else if (sig == 0) |
| sig = 1 << 21; |
| |
| image |= 255 << 23; |
| image |= sig; |
| } |
| else |
| image |= 0x7fffffff; |
| break; |
| |
| case rvc_normal: |
| /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, |
| whereas the intermediate representation is 0.F x 2**exp. |
| Which means we're off by one. */ |
| if (denormal) |
| exp = 0; |
| else |
| exp = REAL_EXP (r) + 127 - 1; |
| image |= exp << 23; |
| image |= sig; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| buf[0] = image; |
| } |
| |
| static void |
| decode_ieee_single (const struct real_format *fmt, REAL_VALUE_TYPE *r, |
| const long *buf) |
| { |
| unsigned long image = buf[0] & 0xffffffff; |
| bool sign = (image >> 31) & 1; |
| int exp = (image >> 23) & 0xff; |
| |
| memset (r, 0, sizeof (*r)); |
| image <<= HOST_BITS_PER_LONG - 24; |
| image &= ~SIG_MSB; |
| |
| if (exp == 0) |
| { |
| if (image && fmt->has_denorm) |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, -126); |
| r->sig[SIGSZ-1] = image << 1; |
| normalize (r); |
| } |
| else if (fmt->has_signed_zero) |
| r->sign = sign; |
| } |
| else if (exp == 255 && (fmt->has_nans || fmt->has_inf)) |
| { |
| if (image) |
| { |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1) |
| ^ fmt->qnan_msb_set); |
| r->sig[SIGSZ-1] = image; |
| } |
| else |
| { |
| r->cl = rvc_inf; |
| r->sign = sign; |
| } |
| } |
| else |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, exp - 127 + 1); |
| r->sig[SIGSZ-1] = image | SIG_MSB; |
| } |
| } |
| |
| const struct real_format ieee_single_format = |
| { |
| encode_ieee_single, |
| decode_ieee_single, |
| 2, |
| 1, |
| 24, |
| 24, |
| -125, |
| 128, |
| 31, |
| true, |
| true, |
| true, |
| true, |
| true |
| }; |
| |
| const struct real_format mips_single_format = |
| { |
| encode_ieee_single, |
| decode_ieee_single, |
| 2, |
| 1, |
| 24, |
| 24, |
| -125, |
| 128, |
| 31, |
| true, |
| true, |
| true, |
| true, |
| false |
| }; |
| |
| |
| /* IEEE double-precision format. */ |
| |
| static void encode_ieee_double (const struct real_format *fmt, |
| long *, const REAL_VALUE_TYPE *); |
| static void decode_ieee_double (const struct real_format *, |
| REAL_VALUE_TYPE *, const long *); |
| |
| static void |
| encode_ieee_double (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| unsigned long image_lo, image_hi, sig_lo, sig_hi, exp; |
| bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; |
| |
| image_hi = r->sign << 31; |
| image_lo = 0; |
| |
| if (HOST_BITS_PER_LONG == 64) |
| { |
| sig_hi = r->sig[SIGSZ-1]; |
| sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff; |
| sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff; |
| } |
| else |
| { |
| sig_hi = r->sig[SIGSZ-1]; |
| sig_lo = r->sig[SIGSZ-2]; |
| sig_lo = (sig_hi << 21) | (sig_lo >> 11); |
| sig_hi = (sig_hi >> 11) & 0xfffff; |
| } |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| break; |
| |
| case rvc_inf: |
| if (fmt->has_inf) |
| image_hi |= 2047 << 20; |
| else |
| { |
| image_hi |= 0x7fffffff; |
| image_lo = 0xffffffff; |
| } |
| break; |
| |
| case rvc_nan: |
| if (fmt->has_nans) |
| { |
| if (r->canonical) |
| sig_hi = sig_lo = 0; |
| if (r->signalling == fmt->qnan_msb_set) |
| sig_hi &= ~(1 << 19); |
| else |
| sig_hi |= 1 << 19; |
| /* We overload qnan_msb_set here: it's only clear for |
| mips_ieee_single, which wants all mantissa bits but the |
| quiet/signalling one set in canonical NaNs (at least |
| Quiet ones). */ |
| if (r->canonical && !fmt->qnan_msb_set) |
| { |
| sig_hi |= (1 << 19) - 1; |
| sig_lo = 0xffffffff; |
| } |
| else if (sig_hi == 0 && sig_lo == 0) |
| sig_hi = 1 << 18; |
| |
| image_hi |= 2047 << 20; |
| image_hi |= sig_hi; |
| image_lo = sig_lo; |
| } |
| else |
| { |
| image_hi |= 0x7fffffff; |
| image_lo = 0xffffffff; |
| } |
| break; |
| |
| case rvc_normal: |
| /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, |
| whereas the intermediate representation is 0.F x 2**exp. |
| Which means we're off by one. */ |
| if (denormal) |
| exp = 0; |
| else |
| exp = REAL_EXP (r) + 1023 - 1; |
| image_hi |= exp << 20; |
| image_hi |= sig_hi; |
| image_lo = sig_lo; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if (FLOAT_WORDS_BIG_ENDIAN) |
| buf[0] = image_hi, buf[1] = image_lo; |
| else |
| buf[0] = image_lo, buf[1] = image_hi; |
| } |
| |
| static void |
| decode_ieee_double (const struct real_format *fmt, REAL_VALUE_TYPE *r, |
| const long *buf) |
| { |
| unsigned long image_hi, image_lo; |
| bool sign; |
| int exp; |
| |
| if (FLOAT_WORDS_BIG_ENDIAN) |
| image_hi = buf[0], image_lo = buf[1]; |
| else |
| image_lo = buf[0], image_hi = buf[1]; |
| image_lo &= 0xffffffff; |
| image_hi &= 0xffffffff; |
| |
| sign = (image_hi >> 31) & 1; |
| exp = (image_hi >> 20) & 0x7ff; |
| |
| memset (r, 0, sizeof (*r)); |
| |
| image_hi <<= 32 - 21; |
| image_hi |= image_lo >> 21; |
| image_hi &= 0x7fffffff; |
| image_lo <<= 32 - 21; |
| |
| if (exp == 0) |
| { |
| if ((image_hi || image_lo) && fmt->has_denorm) |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, -1022); |
| if (HOST_BITS_PER_LONG == 32) |
| { |
| image_hi = (image_hi << 1) | (image_lo >> 31); |
| image_lo <<= 1; |
| r->sig[SIGSZ-1] = image_hi; |
| r->sig[SIGSZ-2] = image_lo; |
| } |
| else |
| { |
| image_hi = (image_hi << 31 << 2) | (image_lo << 1); |
| r->sig[SIGSZ-1] = image_hi; |
| } |
| normalize (r); |
| } |
| else if (fmt->has_signed_zero) |
| r->sign = sign; |
| } |
| else if (exp == 2047 && (fmt->has_nans || fmt->has_inf)) |
| { |
| if (image_hi || image_lo) |
| { |
| r->cl = rvc_nan; |
| r->sign = sign; |
| r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set; |
| if (HOST_BITS_PER_LONG == 32) |
| { |
| r->sig[SIGSZ-1] = image_hi; |
| r->sig[SIGSZ-2] = image_lo; |
| } |
| else |
| r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo; |
| } |
| else |
| { |
| r->cl = rvc_inf; |
| r->sign = sign; |
| } |
| } |
| else |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| SET_REAL_EXP (r, exp - 1023 + 1); |
| if (HOST_BITS_PER_LONG == 32) |
| { |
| r->sig[SIGSZ-1] = image_hi | SIG_MSB; |
| r->sig[SIGSZ-2] = image_lo; |
| } |
| else |
| r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo | SIG_MSB; |
| } |
| } |
| |
| const struct real_format ieee_double_format = |
| { |
| encode_ieee_double, |
| decode_ieee_double, |
| 2, |
| 1, |
| 53, |
| 53, |
| -1021, |
| 1024, |
| 63, |
| true, |
| true, |
| true, |
| true, |
| true |
| }; |
| |
| const struct real_format mips_double_format = |
| { |
| encode_ieee_double, |
| decode_ieee_double, |
| 2, |
| 1, |
| 53, |
| 53, |
| -1021, |
| 1024, |
| 63, |
| true, |
| true, |
| true, |
| true, |
| false |
| }; |
| |
| |
| /* IEEE extended real format. This comes in three flavors: Intel's as |
| a 12 byte image, Intel's as a 16 byte image, and Motorola's. Intel |
| 12- and 16-byte images may be big- or little endian; Motorola's is |
| always big endian. */ |
| |
| /* Helper subroutine which converts from the internal format to the |
| 12-byte little-endian Intel format. Functions below adjust this |
| for the other possible formats. */ |
| static void |
| encode_ieee_extended (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| unsigned long image_hi, sig_hi, sig_lo; |
| bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; |
| |
| image_hi = r->sign << 15; |
| sig_hi = sig_lo = 0; |
| |
| switch (r->cl) |
| { |
| case rvc_zero: |
| break; |
| |
| case rvc_inf: |
| if (fmt->has_inf) |
| { |
| image_hi |= 32767; |
| |
| /* Intel requires the explicit integer bit to be set, otherwise |
| it considers the value a "pseudo-infinity". Motorola docs |
| say it doesn't care. */ |
| sig_hi = 0x80000000; |
| } |
| else |
| { |
| image_hi |= 32767; |
| sig_lo = sig_hi = 0xffffffff; |
| } |
| break; |
| |
| case rvc_nan: |
| if (fmt->has_nans) |
| { |
| image_hi |= 32767; |
| if (HOST_BITS_PER_LONG == 32) |
| { |
| sig_hi = r->sig[SIGSZ-1]; |
| sig_lo = r->sig[SIGSZ-2]; |
| } |
| else |
| { |
| sig_lo = r->sig[SIGSZ-1]; |
| sig_hi = sig_lo >> 31 >> 1; |
| sig_lo &= 0xffffffff; |
| } |
| if (r->signalling == fmt->qnan_msb_set) |
| sig_hi &= ~(1 << 30); |
| else |
| sig_hi |= 1 << 30; |
| if ((sig_hi & 0x7fffffff) == 0 && sig_lo == 0) |
| sig_hi = 1 << 29; |
| |
| /* Intel requires the explicit integer bit to be set, otherwise |
| it considers the value a "pseudo-nan". Motorola docs say it |
| doesn't care. */ |
| sig_hi |= 0x80000000; |
| } |
| else |
| { |
| image_hi |= 32767; |
| sig_lo = sig_hi = 0xffffffff; |
| } |
| break; |
| |
| case rvc_normal: |
| { |
| int exp = REAL_EXP (r); |
| |
| /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, |
| whereas the intermediate representation is 0.F x 2**exp. |
| Which means we're off by one. |
| |
| Except for Motorola, which consider exp=0 and explicit |
| integer bit set to continue to be normalized. In theory |
| this discrepancy has been taken care of by the difference |
| in fmt->emin in round_for_format. */ |
| |
| if (denormal) |
| exp = 0; |
| else |
| { |
| exp += 16383 - 1; |
| gcc_assert (exp >= 0); |
| } |
| image_hi |= exp; |
| |
| if (HOST_BITS_PER_LONG == 32) |
| { |
| sig_hi = r->sig[SIGSZ-1]; |
| sig_lo = r->sig[SIGSZ-2]; |
| } |
| else |
| { |
| sig_lo = r->sig[SIGSZ-1]; |
| sig_hi = sig_lo >> 31 >> 1; |
| sig_lo &= 0xffffffff; |
| } |
| } |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi; |
| } |
| |
| /* Convert from the internal format to the 12-byte Motorola format |
| for an IEEE extended real. */ |
| static void |
| encode_ieee_extended_motorola (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| long intermed[3]; |
| encode_ieee_extended (fmt, intermed, r); |
| |
| /* Motorola chips are assumed always to be big-endian. Also, the |
| padding in a Motorola extended real goes between the exponent and |
| the mantissa. At this point the mantissa is entirely within |
| elements 0 and 1 of intermed, and the exponent entirely within |
| element 2, so all we have to do is swap the order around, and |
| shift element 2 left 16 bits. */ |
| buf[0] = intermed[2] << 16; |
| buf[1] = intermed[1]; |
| buf[2] = intermed[0]; |
| } |
| |
| /* Convert from the internal format to the 12-byte Intel format for |
| an IEEE extended real. */ |
| static void |
| encode_ieee_extended_intel_96 (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| if (FLOAT_WORDS_BIG_ENDIAN) |
| { |
| /* All the padding in an Intel-format extended real goes at the high |
| end, which in this case is after the mantissa, not the exponent. |
| Therefore we must shift everything down 16 bits. */ |
| long intermed[3]; |
| encode_ieee_extended (fmt, intermed, r); |
| buf[0] = ((intermed[2] << 16) | ((unsigned long)(intermed[1] & 0xFFFF0000) >> 16)); |
| buf[1] = ((intermed[1] << 16) | ((unsigned long)(intermed[0] & 0xFFFF0000) >> 16)); |
| buf[2] = (intermed[0] << 16); |
| } |
| else |
| /* encode_ieee_extended produces what we want directly. */ |
| encode_ieee_extended (fmt, buf, r); |
| } |
| |
| /* Convert from the internal format to the 16-byte Intel format for |
| an IEEE extended real. */ |
| static void |
| encode_ieee_extended_intel_128 (const struct real_format *fmt, long *buf, |
| const REAL_VALUE_TYPE *r) |
| { |
| /* All the padding in an Intel-format extended real goes at the high end. */ |
| encode_ieee_extended_intel_96 (fmt, buf, r); |
| buf[3] = 0; |
| } |
| |
| /* As above, we have a helper function which converts from 12-byte |
| little-endian Intel format to internal format. Functions below |
| adjust for the other possible formats. */ |
| static void |
| decode_ieee_extended (const struct real_format *fmt, REAL_VALUE_TYPE *r, |
| const long *buf) |
| { |
| unsigned long image_hi, sig_hi, sig_lo; |
| bool sign; |
| int exp; |
| |
| sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2]; |
| sig_lo &= 0xffffffff; |
| sig_hi &= 0xffffffff; |
| image_hi &= 0xffffffff; |
| |
| sign = (image_hi >> 15) & 1; |
| exp = image_hi & 0x7fff; |
| |
| memset (r, 0, sizeof (*r)); |
| |
| if (exp == 0) |
| { |
| if ((sig_hi || sig_lo) && fmt->has_denorm) |
| { |
| r->cl = rvc_normal; |
| r->sign = sign; |
| |
| /* When the IEEE format contains a hidden bit, we know that |
| it's zero at this point, and so shift up the significand |
| and decrease the exponent to match. In this case, Motorola |
| defines the explicit integer bit to be valid, so we don't |
| know whether the msb is set or not. */ |
| SET_REAL_EXP (r, fmt->emin); |
| if (HOST_BITS_PER_LONG == 32) |
| { |
| r->sig[SIGSZ-1] = sig_hi; |
| r->sig[SIGSZ-2] = sig_lo; |
| } |
| else |
| r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo; |
| |
| normalize (r); |
| } |
| else if (fmt->has_signed_zero) |
| r->sign = sign; |
| } |
| else if (exp == 32767 && (fmt->has_nans || fmt->has_inf)) |
| |