diff options
Diffstat (limited to 'gcc-4.2.1-5666.3/gcc/real.c')
-rw-r--r-- | gcc-4.2.1-5666.3/gcc/real.c | 4933 |
1 files changed, 0 insertions, 4933 deletions
diff --git a/gcc-4.2.1-5666.3/gcc/real.c b/gcc-4.2.1-5666.3/gcc/real.c deleted file mode 100644 index 420a04532..000000000 --- a/gcc-4.2.1-5666.3/gcc/real.c +++ /dev/null @@ -1,4933 +0,0 @@ -/* 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, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, 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" -#include "dfp.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; - - if (r->decimal) - return; - - /* 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; - r->decimal = 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 (a->decimal || b->decimal) - return decimal_do_compare (a, b, nan_result); - - 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 (r->decimal) - { - decimal_do_fix_trunc (r, a); - return; - } - 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; - - if (op0->decimal || (op1 && op1->decimal)) - return decimal_real_arithmetic (r, icode, op0, op1); - - 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 (a->decimal != b->decimal) - return false; - 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 (r->decimal) - return decimal_real_to_integer (r); - - 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: - if (r->decimal) - { - decimal_real_to_integer2 (plow, phigh, r); - return; - } - - 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 (); - } - - if (r.decimal) - { - decimal_real_to_decimal (str, &r, buf_size, digits, crop_trailing_zeros); - return; - } - - /* 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 (r->decimal) - { - /* Hexadecimal format for decimal floats is not interesting. */ - strcpy (str, "N/A"); - return; - } - - 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; - } - else if (d) - /* Ensure correct rounding by setting last bit if there is - a subsequent nonzero digit. */ - r->sig[0] |= 1; - 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; - } - else if (d) - /* Ensure correct rounding by setting last bit if there is - a subsequent nonzero digit. */ - r->sig[0] |= 1; - str++; - } - } - - /* If the mantissa is zero, ignore the exponent. */ - if (!cmp_significand_0 (r)) - goto underflow; - - 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 the mantissa is zero, ignore the exponent. */ - if (r->cl == rvc_zero) - goto underflow; - - 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 string S and desired MODE. */ - -void -real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode) -{ - if (DECIMAL_FLOAT_MODE_P (mode)) - decimal_real_from_string (r, s); - else - real_from_string (r, s); - - if (mode != VOIDmode) - real_convert (r, mode, 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; - - 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++; - else if (*str == '+') - str++; - if (*str == '0') - { - str++; - if (*str == 'x' || *str == 'X') - { - base = 16; - str++; - } - 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); - memset (r, 0, sizeof (*r)); - - if (fmt->b == 10) - decimal_real_maxval (r, sign, mode); - else - { - r->cl = rvc_normal; - r->sign = sign; - 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); - - 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); - } -} - -/* 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; - - if (r->decimal) - { - if (fmt->b == 10) - { - decimal_round_for_format (fmt, r); - return; - } - /* FIXME. We can come here via fp_easy_constant - (e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not - investigated whether this convert needs to be here, or - something else is missing. */ - decimal_real_convert (r, DFmode, r); - } - - 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; - - gcc_assert (fmt->b != 10); - 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; - - if (a->decimal || fmt->b == 10) - decimal_real_convert (r, mode, 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) -{ - const struct real_format *fmt; - REAL_VALUE_TYPE t; - int emin2m1; - - fmt = REAL_MODE_FORMAT (mode); - gcc_assert (fmt); - - /* Don't allow conversion to denormals. */ - emin2m1 = (fmt->emin - 1) * fmt->log2_b; - if (REAL_EXP (a) <= emin2m1) - return false; - - /* After conversion to the new mode, the value must be identical. */ - 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 of the largest binary value that the - significand of MODE will hold. */ -/* ??? 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; - - if (fmt->b == 10) - { - /* Return the size in bits of the largest binary value that can be - held by the decimal coefficient for this mode. This is one more - than the number of bits required to hold the largest coefficient - of this mode. */ - double log2_10 = 3.3219281; - return fmt->p * log2_10; - } - 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, - 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, - 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, - 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, - 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)) - { - /* See above re "pseudo-infinities" and "pseudo-nans". - Short summary is that the MSB will likely always be - set, and that we don't care about it. */ - sig_hi &= 0x7fffffff; - - if (sig_hi || sig_lo) - { - r->cl = rvc_nan; - r->sign = sign; - r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set; - 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; - } - else - { - r->cl = rvc_inf; - r->sign = sign; - } - } - else - { - r->cl = rvc_normal; - r->sign = sign; - SET_REAL_EXP (r, exp - 16383 + 1); - 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; - } -} - -/* Convert from the internal format to the 12-byte Motorola format - for an IEEE extended real. */ -static void -decode_ieee_extended_motorola (const struct real_format *fmt, REAL_VALUE_TYPE *r, - const long *buf) -{ - long intermed[3]; - - /* Motorola chips are assumed always to be big-endian. Also, the - padding in a Motorola extended real goes between the exponent and - the mantissa; remove it. */ - intermed[0] = buf[2]; - intermed[1] = buf[1]; - intermed[2] = (unsigned long)buf[0] >> 16; - - decode_ieee_extended (fmt, r, intermed); -} - -/* Convert from the internal format to the 12-byte Intel format for - an IEEE extended real. */ -static void -decode_ieee_extended_intel_96 (const struct real_format *fmt, REAL_VALUE_TYPE *r, - const long *buf) -{ - 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 up 16 bits. */ - long intermed[3]; - - intermed[0] = (((unsigned long)buf[2] >> 16) | (buf[1] << 16)); - intermed[1] = (((unsigned long)buf[1] >> 16) | (buf[0] << 16)); - intermed[2] = ((unsigned long)buf[0] >> 16); - - decode_ieee_extended (fmt, r, intermed); - } - else - /* decode_ieee_extended produces what we want directly. */ - decode_ieee_extended (fmt, r, buf); -} - -/* Convert from the internal format to the 16-byte Intel format for - an IEEE extended real. */ -static void -decode_ieee_extended_intel_128 (const struct real_format *fmt, REAL_VALUE_TYPE *r, - const long *buf) -{ - /* All the padding in an Intel-format extended real goes at the high end. */ - decode_ieee_extended_intel_96 (fmt, r, buf); -} - -const struct real_format ieee_extended_motorola_format = - { - encode_ieee_extended_motorola, - decode_ieee_extended_motorola, - 2, - 1, - 64, - 64, - -16382, - 16384, - 95, - 95, - true, - true, - true, - true, - true - }; - -const struct real_format ieee_extended_intel_96_format = - { - encode_ieee_extended_intel_96, - decode_ieee_extended_intel_96, - 2, - 1, - 64, - 64, - -16381, - 16384, - 79, - 79, - true, - true, - true, - true, - true - }; - -const struct real_format ieee_extended_intel_128_format = - { - encode_ieee_extended_intel_128, - decode_ieee_extended_intel_128, - 2, - 1, - 64, - 64, - -16381, - 16384, - 79, - 79, - true, - true, - true, - true, - true - }; - -/* The following caters to i386 systems that set the rounding precision - to 53 bits instead of 64, e.g. FreeBSD. */ -const struct real_format ieee_extended_intel_96_round_53_format = - { - encode_ieee_extended_intel_96, - decode_ieee_extended_intel_96, - 2, - 1, - 53, - 53, - -16381, - 16384, - 79, - 79, - true, - true, - true, - true, - true - }; - -/* IBM 128-bit extended precision format: a pair of IEEE double precision - numbers whose sum is equal to the extended precision value. The number - with greater magnitude is first. This format has the same magnitude - range as an IEEE double precision value, but effectively 106 bits of - significand precision. Infinity and NaN are represented by their IEEE - double precision value stored in the first number, the second number is - +0.0 or -0.0 for Infinity and don't-care for NaN. */ - -static void encode_ibm_extended (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_ibm_extended (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_ibm_extended (const struct real_format *fmt, long *buf, - const REAL_VALUE_TYPE *r) -{ - REAL_VALUE_TYPE u, normr, v; - const struct real_format *base_fmt; - - base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format; - - /* Renormlize R before doing any arithmetic on it. */ - normr = *r; - if (normr.cl == rvc_normal) - normalize (&normr); - - /* u = IEEE double precision portion of significand. */ - u = normr; - round_for_format (base_fmt, &u); - encode_ieee_double (base_fmt, &buf[0], &u); - - if (u.cl == rvc_normal) - { - do_add (&v, &normr, &u, 1); - /* Call round_for_format since we might need to denormalize. */ - round_for_format (base_fmt, &v); - encode_ieee_double (base_fmt, &buf[2], &v); - } - else - { - /* Inf, NaN, 0 are all representable as doubles, so the - least-significant part can be 0.0. */ - buf[2] = 0; - buf[3] = 0; - } -} - -static void -decode_ibm_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r, - const long *buf) -{ - REAL_VALUE_TYPE u, v; - const struct real_format *base_fmt; - - base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format; - decode_ieee_double (base_fmt, &u, &buf[0]); - - if (u.cl != rvc_zero && u.cl != rvc_inf && u.cl != rvc_nan) - { - decode_ieee_double (base_fmt, &v, &buf[2]); - do_add (r, &u, &v, 0); - } - else - *r = u; -} - -const struct real_format ibm_extended_format = - { - encode_ibm_extended, - decode_ibm_extended, - 2, - 1, - 53 + 53, - 53, - -1021 + 53, - 1024, - 127, - -1, - true, - true, - true, - true, - true - }; - -const struct real_format mips_extended_format = - { - encode_ibm_extended, - decode_ibm_extended, - 2, - 1, - 53 + 53, - 53, - -1021 + 53, - 1024, - 127, - -1, - true, - true, - true, - true, - false - }; - - -/* IEEE quad precision format. */ - -static void encode_ieee_quad (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_ieee_quad (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_ieee_quad (const struct real_format *fmt, long *buf, - const REAL_VALUE_TYPE *r) -{ - unsigned long image3, image2, image1, image0, exp; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; - REAL_VALUE_TYPE u; - - image3 = r->sign << 31; - image2 = 0; - image1 = 0; - image0 = 0; - - rshift_significand (&u, r, SIGNIFICAND_BITS - 113); - - switch (r->cl) - { - case rvc_zero: - break; - - case rvc_inf: - if (fmt->has_inf) - image3 |= 32767 << 16; - else - { - image3 |= 0x7fffffff; - image2 = 0xffffffff; - image1 = 0xffffffff; - image0 = 0xffffffff; - } - break; - - case rvc_nan: - if (fmt->has_nans) - { - image3 |= 32767 << 16; - - if (r->canonical) - { - /* Don't use bits from the significand. The - initialization above is right. */ - } - else if (HOST_BITS_PER_LONG == 32) - { - image0 = u.sig[0]; - image1 = u.sig[1]; - image2 = u.sig[2]; - image3 |= u.sig[3] & 0xffff; - } - else - { - image0 = u.sig[0]; - image1 = image0 >> 31 >> 1; - image2 = u.sig[1]; - image3 |= (image2 >> 31 >> 1) & 0xffff; - image0 &= 0xffffffff; - image2 &= 0xffffffff; - } - if (r->signalling == fmt->qnan_msb_set) - image3 &= ~0x8000; - else - image3 |= 0x8000; - /* 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) - { - image3 |= 0x7fff; - image2 = image1 = image0 = 0xffffffff; - } - else if (((image3 & 0xffff) | image2 | image1 | image0) == 0) - image3 |= 0x4000; - } - else - { - image3 |= 0x7fffffff; - image2 = 0xffffffff; - image1 = 0xffffffff; - image0 = 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) + 16383 - 1; - image3 |= exp << 16; - - if (HOST_BITS_PER_LONG == 32) - { - image0 = u.sig[0]; - image1 = u.sig[1]; - image2 = u.sig[2]; - image3 |= u.sig[3] & 0xffff; - } - else - { - image0 = u.sig[0]; - image1 = image0 >> 31 >> 1; - image2 = u.sig[1]; - image3 |= (image2 >> 31 >> 1) & 0xffff; - image0 &= 0xffffffff; - image2 &= 0xffffffff; - } - break; - - default: - gcc_unreachable (); - } - - if (FLOAT_WORDS_BIG_ENDIAN) - { - buf[0] = image3; - buf[1] = image2; - buf[2] = image1; - buf[3] = image0; - } - else - { - buf[0] = image0; - buf[1] = image1; - buf[2] = image2; - buf[3] = image3; - } -} - -static void -decode_ieee_quad (const struct real_format *fmt, REAL_VALUE_TYPE *r, - const long *buf) -{ - unsigned long image3, image2, image1, image0; - bool sign; - int exp; - - if (FLOAT_WORDS_BIG_ENDIAN) - { - image3 = buf[0]; - image2 = buf[1]; - image1 = buf[2]; - image0 = buf[3]; - } - else - { - image0 = buf[0]; - image1 = buf[1]; - image2 = buf[2]; - image3 = buf[3]; - } - image0 &= 0xffffffff; - image1 &= 0xffffffff; - image2 &= 0xffffffff; - - sign = (image3 >> 31) & 1; - exp = (image3 >> 16) & 0x7fff; - image3 &= 0xffff; - - memset (r, 0, sizeof (*r)); - - if (exp == 0) - { - if ((image3 | image2 | image1 | image0) && fmt->has_denorm) - { - r->cl = rvc_normal; - r->sign = sign; - - SET_REAL_EXP (r, -16382 + (SIGNIFICAND_BITS - 112)); - if (HOST_BITS_PER_LONG == 32) - { - r->sig[0] = image0; - r->sig[1] = image1; - r->sig[2] = image2; - r->sig[3] = image3; - } - else - { - r->sig[0] = (image1 << 31 << 1) | image0; - r->sig[1] = (image3 << 31 << 1) | image2; - } - - normalize (r); - } - else if (fmt->has_signed_zero) - r->sign = sign; - } - else if (exp == 32767 && (fmt->has_nans || fmt->has_inf)) - { - if (image3 | image2 | image1 | image0) - { - r->cl = rvc_nan; - r->sign = sign; - r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set; - - if (HOST_BITS_PER_LONG == 32) - { - r->sig[0] = image0; - r->sig[1] = image1; - r->sig[2] = image2; - r->sig[3] = image3; - } - else - { - r->sig[0] = (image1 << 31 << 1) | image0; - r->sig[1] = (image3 << 31 << 1) | image2; - } - lshift_significand (r, r, SIGNIFICAND_BITS - 113); - } - else - { - r->cl = rvc_inf; - r->sign = sign; - } - } - else - { - r->cl = rvc_normal; - r->sign = sign; - SET_REAL_EXP (r, exp - 16383 + 1); - - if (HOST_BITS_PER_LONG == 32) - { - r->sig[0] = image0; - r->sig[1] = image1; - r->sig[2] = image2; - r->sig[3] = image3; - } - else - { - r->sig[0] = (image1 << 31 << 1) | image0; - r->sig[1] = (image3 << 31 << 1) | image2; - } - lshift_significand (r, r, SIGNIFICAND_BITS - 113); - r->sig[SIGSZ-1] |= SIG_MSB; - } -} - -const struct real_format ieee_quad_format = - { - encode_ieee_quad, - decode_ieee_quad, - 2, - 1, - 113, - 113, - -16381, - 16384, - 127, - 127, - true, - true, - true, - true, - true - }; - -const struct real_format mips_quad_format = - { - encode_ieee_quad, - decode_ieee_quad, - 2, - 1, - 113, - 113, - -16381, - 16384, - 127, - 127, - true, - true, - true, - true, - false - }; - -/* Descriptions of VAX floating point formats can be found beginning at - - http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_013.html#f_floating_point_format - - The thing to remember is that they're almost IEEE, except for word - order, exponent bias, and the lack of infinities, nans, and denormals. - - We don't implement the H_floating format here, simply because neither - the VAX or Alpha ports use it. */ - -static void encode_vax_f (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_vax_f (const struct real_format *, - REAL_VALUE_TYPE *, const long *); -static void encode_vax_d (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_vax_d (const struct real_format *, - REAL_VALUE_TYPE *, const long *); -static void encode_vax_g (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_vax_g (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, - const REAL_VALUE_TYPE *r) -{ - unsigned long sign, exp, sig, image; - - sign = r->sign << 15; - - switch (r->cl) - { - case rvc_zero: - image = 0; - break; - - case rvc_inf: - case rvc_nan: - image = 0xffff7fff | sign; - break; - - case rvc_normal: - sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; - exp = REAL_EXP (r) + 128; - - image = (sig << 16) & 0xffff0000; - image |= sign; - image |= exp << 7; - image |= sig >> 16; - break; - - default: - gcc_unreachable (); - } - - buf[0] = image; -} - -static void -decode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long image = buf[0] & 0xffffffff; - int exp = (image >> 7) & 0xff; - - memset (r, 0, sizeof (*r)); - - if (exp != 0) - { - r->cl = rvc_normal; - r->sign = (image >> 15) & 1; - SET_REAL_EXP (r, exp - 128); - - image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff); - r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB; - } -} - -static void -encode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, - const REAL_VALUE_TYPE *r) -{ - unsigned long image0, image1, sign = r->sign << 15; - - switch (r->cl) - { - case rvc_zero: - image0 = image1 = 0; - break; - - case rvc_inf: - case rvc_nan: - image0 = 0xffff7fff | sign; - image1 = 0xffffffff; - break; - - case rvc_normal: - /* Extract the significand into straight hi:lo. */ - if (HOST_BITS_PER_LONG == 64) - { - image0 = r->sig[SIGSZ-1]; - image1 = (image0 >> (64 - 56)) & 0xffffffff; - image0 = (image0 >> (64 - 56 + 1) >> 31) & 0x7fffff; - } - else - { - image0 = r->sig[SIGSZ-1]; - image1 = r->sig[SIGSZ-2]; - image1 = (image0 << 24) | (image1 >> 8); - image0 = (image0 >> 8) & 0xffffff; - } - - /* Rearrange the half-words of the significand to match the - external format. */ - image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f; - image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff; - - /* Add the sign and exponent. */ - image0 |= sign; - image0 |= (REAL_EXP (r) + 128) << 7; - break; - - default: - gcc_unreachable (); - } - - if (FLOAT_WORDS_BIG_ENDIAN) - buf[0] = image1, buf[1] = image0; - else - buf[0] = image0, buf[1] = image1; -} - -static void -decode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long image0, image1; - int exp; - - if (FLOAT_WORDS_BIG_ENDIAN) - image1 = buf[0], image0 = buf[1]; - else - image0 = buf[0], image1 = buf[1]; - image0 &= 0xffffffff; - image1 &= 0xffffffff; - - exp = (image0 >> 7) & 0xff; - - memset (r, 0, sizeof (*r)); - - if (exp != 0) - { - r->cl = rvc_normal; - r->sign = (image0 >> 15) & 1; - SET_REAL_EXP (r, exp - 128); - - /* Rearrange the half-words of the external format into - proper ascending order. */ - image0 = ((image0 & 0x7f) << 16) | ((image0 >> 16) & 0xffff); - image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff); - - if (HOST_BITS_PER_LONG == 64) - { - image0 = (image0 << 31 << 1) | image1; - image0 <<= 64 - 56; - image0 |= SIG_MSB; - r->sig[SIGSZ-1] = image0; - } - else - { - r->sig[SIGSZ-1] = image0; - r->sig[SIGSZ-2] = image1; - lshift_significand (r, r, 2*HOST_BITS_PER_LONG - 56); - r->sig[SIGSZ-1] |= SIG_MSB; - } - } -} - -static void -encode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, - const REAL_VALUE_TYPE *r) -{ - unsigned long image0, image1, sign = r->sign << 15; - - switch (r->cl) - { - case rvc_zero: - image0 = image1 = 0; - break; - - case rvc_inf: - case rvc_nan: - image0 = 0xffff7fff | sign; - image1 = 0xffffffff; - break; - - case rvc_normal: - /* Extract the significand into straight hi:lo. */ - if (HOST_BITS_PER_LONG == 64) - { - image0 = r->sig[SIGSZ-1]; - image1 = (image0 >> (64 - 53)) & 0xffffffff; - image0 = (image0 >> (64 - 53 + 1) >> 31) & 0xfffff; - } - else - { - image0 = r->sig[SIGSZ-1]; - image1 = r->sig[SIGSZ-2]; - image1 = (image0 << 21) | (image1 >> 11); - image0 = (image0 >> 11) & 0xfffff; - } - - /* Rearrange the half-words of the significand to match the - external format. */ - image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f; - image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff; - - /* Add the sign and exponent. */ - image0 |= sign; - image0 |= (REAL_EXP (r) + 1024) << 4; - break; - - default: - gcc_unreachable (); - } - - if (FLOAT_WORDS_BIG_ENDIAN) - buf[0] = image1, buf[1] = image0; - else - buf[0] = image0, buf[1] = image1; -} - -static void -decode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long image0, image1; - int exp; - - if (FLOAT_WORDS_BIG_ENDIAN) - image1 = buf[0], image0 = buf[1]; - else - image0 = buf[0], image1 = buf[1]; - image0 &= 0xffffffff; - image1 &= 0xffffffff; - - exp = (image0 >> 4) & 0x7ff; - - memset (r, 0, sizeof (*r)); - - if (exp != 0) - { - r->cl = rvc_normal; - r->sign = (image0 >> 15) & 1; - SET_REAL_EXP (r, exp - 1024); - - /* Rearrange the half-words of the external format into - proper ascending order. */ - image0 = ((image0 & 0xf) << 16) | ((image0 >> 16) & 0xffff); - image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff); - - if (HOST_BITS_PER_LONG == 64) - { - image0 = (image0 << 31 << 1) | image1; - image0 <<= 64 - 53; - image0 |= SIG_MSB; - r->sig[SIGSZ-1] = image0; - } - else - { - r->sig[SIGSZ-1] = image0; - r->sig[SIGSZ-2] = image1; - lshift_significand (r, r, 64 - 53); - r->sig[SIGSZ-1] |= SIG_MSB; - } - } -} - -const struct real_format vax_f_format = - { - encode_vax_f, - decode_vax_f, - 2, - 1, - 24, - 24, - -127, - 127, - 15, - 15, - false, - false, - false, - false, - false - }; - -const struct real_format vax_d_format = - { - encode_vax_d, - decode_vax_d, - 2, - 1, - 56, - 56, - -127, - 127, - 15, - 15, - false, - false, - false, - false, - false - }; - -const struct real_format vax_g_format = - { - encode_vax_g, - decode_vax_g, - 2, - 1, - 53, - 53, - -1023, - 1023, - 15, - 15, - false, - false, - false, - false, - false - }; - -/* A good reference for these can be found in chapter 9 of - "ESA/390 Principles of Operation", IBM document number SA22-7201-01. - An on-line version can be found here: - - http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613 -*/ - -static void encode_i370_single (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_i370_single (const struct real_format *, - REAL_VALUE_TYPE *, const long *); -static void encode_i370_double (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_i370_double (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) -{ - unsigned long sign, exp, sig, image; - - sign = r->sign << 31; - - switch (r->cl) - { - case rvc_zero: - image = 0; - break; - - case rvc_inf: - case rvc_nan: - image = 0x7fffffff | sign; - break; - - case rvc_normal: - sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff; - exp = ((REAL_EXP (r) / 4) + 64) << 24; - image = sign | exp | sig; - break; - - default: - gcc_unreachable (); - } - - buf[0] = image; -} - -static void -decode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long sign, sig, image = buf[0]; - int exp; - - sign = (image >> 31) & 1; - exp = (image >> 24) & 0x7f; - sig = image & 0xffffff; - - memset (r, 0, sizeof (*r)); - - if (exp || sig) - { - r->cl = rvc_normal; - r->sign = sign; - SET_REAL_EXP (r, (exp - 64) * 4); - r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24); - normalize (r); - } -} - -static void -encode_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) -{ - unsigned long sign, exp, image_hi, image_lo; - - sign = r->sign << 31; - - switch (r->cl) - { - case rvc_zero: - image_hi = image_lo = 0; - break; - - case rvc_inf: - case rvc_nan: - image_hi = 0x7fffffff | sign; - image_lo = 0xffffffff; - break; - - case rvc_normal: - if (HOST_BITS_PER_LONG == 64) - { - image_hi = r->sig[SIGSZ-1]; - image_lo = (image_hi >> (64 - 56)) & 0xffffffff; - image_hi = (image_hi >> (64 - 56 + 1) >> 31) & 0xffffff; - } - else - { - image_hi = r->sig[SIGSZ-1]; - image_lo = r->sig[SIGSZ-2]; - image_lo = (image_lo >> 8) | (image_hi << 24); - image_hi >>= 8; - } - - exp = ((REAL_EXP (r) / 4) + 64) << 24; - image_hi |= sign | exp; - 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_i370_double (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long sign, image_hi, image_lo; - int exp; - - if (FLOAT_WORDS_BIG_ENDIAN) - image_hi = buf[0], image_lo = buf[1]; - else - image_lo = buf[0], image_hi = buf[1]; - - sign = (image_hi >> 31) & 1; - exp = (image_hi >> 24) & 0x7f; - image_hi &= 0xffffff; - image_lo &= 0xffffffff; - - memset (r, 0, sizeof (*r)); - - if (exp || image_hi || image_lo) - { - r->cl = rvc_normal; - r->sign = sign; - SET_REAL_EXP (r, (exp - 64) * 4 + (SIGNIFICAND_BITS - 56)); - - if (HOST_BITS_PER_LONG == 32) - { - r->sig[0] = image_lo; - r->sig[1] = image_hi; - } - else - r->sig[0] = image_lo | (image_hi << 31 << 1); - - normalize (r); - } -} - -const struct real_format i370_single_format = - { - encode_i370_single, - decode_i370_single, - 16, - 4, - 6, - 6, - -64, - 63, - 31, - 31, - false, - false, - false, /* ??? The encoding does allow for "unnormals". */ - false, /* ??? The encoding does allow for "unnormals". */ - false - }; - -const struct real_format i370_double_format = - { - encode_i370_double, - decode_i370_double, - 16, - 4, - 14, - 14, - -64, - 63, - 63, - 63, - false, - false, - false, /* ??? The encoding does allow for "unnormals". */ - false, /* ??? The encoding does allow for "unnormals". */ - false - }; - -/* Encode real R into a single precision DFP value in BUF. */ -static void -encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf ATTRIBUTE_UNUSED, - const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) -{ - encode_decimal32 (fmt, buf, r); -} - -/* Decode a single precision DFP value in BUF into a real R. */ -static void -decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, - const long *buf ATTRIBUTE_UNUSED) -{ - decode_decimal32 (fmt, r, buf); -} - -/* Encode real R into a double precision DFP value in BUF. */ -static void -encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf ATTRIBUTE_UNUSED, - const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) -{ - encode_decimal64 (fmt, buf, r); -} - -/* Decode a double precision DFP value in BUF into a real R. */ -static void -decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, - const long *buf ATTRIBUTE_UNUSED) -{ - decode_decimal64 (fmt, r, buf); -} - -/* Encode real R into a quad precision DFP value in BUF. */ -static void -encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf ATTRIBUTE_UNUSED, - const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) -{ - encode_decimal128 (fmt, buf, r); -} - -/* Decode a quad precision DFP value in BUF into a real R. */ -static void -decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, - const long *buf ATTRIBUTE_UNUSED) -{ - decode_decimal128 (fmt, r, buf); -} - -/* Single precision decimal floating point (IEEE 754R). */ -const struct real_format decimal_single_format = - { - encode_decimal_single, - decode_decimal_single, - 10, - 1, /* log10 */ - 7, - 7, - -95, - 96, - 31, - 31, - true, - true, - true, - true, - true - }; - -/* Double precision decimal floating point (IEEE 754R). */ -const struct real_format decimal_double_format = - { - encode_decimal_double, - decode_decimal_double, - 10, - 1, /* log10 */ - 16, - 16, - -383, - 384, - 63, - 63, - true, - true, - true, - true, - true - }; - -/* Quad precision decimal floating point (IEEE 754R). */ -const struct real_format decimal_quad_format = - { - encode_decimal_quad, - decode_decimal_quad, - 10, - 1, /* log10 */ - 34, - 34, - -6143, - 6144, - 127, - 127, - true, - true, - true, - true, - true - }; - -/* The "twos-complement" c4x format is officially defined as - - x = s(~s).f * 2**e - - This is rather misleading. One must remember that F is signed. - A better description would be - - x = -1**s * ((s + 1 + .f) * 2**e - - So if we have a (4 bit) fraction of .1000 with a sign bit of 1, - that's -1 * (1+1+(-.5)) == -1.5. I think. - - The constructions here are taken from Tables 5-1 and 5-2 of the - TMS320C4x User's Guide wherein step-by-step instructions for - conversion from IEEE are presented. That's close enough to our - internal representation so as to make things easy. - - See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf */ - -static void encode_c4x_single (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_c4x_single (const struct real_format *, - REAL_VALUE_TYPE *, const long *); -static void encode_c4x_extended (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_c4x_extended (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) -{ - unsigned long image, exp, sig; - - switch (r->cl) - { - case rvc_zero: - exp = -128; - sig = 0; - break; - - case rvc_inf: - case rvc_nan: - exp = 127; - sig = 0x800000 - r->sign; - break; - - case rvc_normal: - exp = REAL_EXP (r) - 1; - sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; - if (r->sign) - { - if (sig) - sig = -sig; - else - exp--; - sig |= 0x800000; - } - break; - - default: - gcc_unreachable (); - } - - image = ((exp & 0xff) << 24) | (sig & 0xffffff); - buf[0] = image; -} - -static void -decode_c4x_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long image = buf[0]; - unsigned long sig; - int exp, sf; - - exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80; - sf = ((image & 0xffffff) ^ 0x800000) - 0x800000; - - memset (r, 0, sizeof (*r)); - - if (exp != -128) - { - r->cl = rvc_normal; - - sig = sf & 0x7fffff; - if (sf < 0) - { - r->sign = 1; - if (sig) - sig = -sig; - else - exp++; - } - sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB; - - SET_REAL_EXP (r, exp + 1); - r->sig[SIGSZ-1] = sig; - } -} - -static void -encode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) -{ - unsigned long exp, sig; - - switch (r->cl) - { - case rvc_zero: - exp = -128; - sig = 0; - break; - - case rvc_inf: - case rvc_nan: - exp = 127; - sig = 0x80000000 - r->sign; - break; - - case rvc_normal: - exp = REAL_EXP (r) - 1; - - sig = r->sig[SIGSZ-1]; - if (HOST_BITS_PER_LONG == 64) - sig = sig >> 1 >> 31; - sig &= 0x7fffffff; - - if (r->sign) - { - if (sig) - sig = -sig; - else - exp--; - sig |= 0x80000000; - } - break; - - default: - gcc_unreachable (); - } - - exp = (exp & 0xff) << 24; - sig &= 0xffffffff; - - if (FLOAT_WORDS_BIG_ENDIAN) - buf[0] = exp, buf[1] = sig; - else - buf[0] = sig, buf[0] = exp; -} - -static void -decode_c4x_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - unsigned long sig; - int exp, sf; - - if (FLOAT_WORDS_BIG_ENDIAN) - exp = buf[0], sf = buf[1]; - else - sf = buf[0], exp = buf[1]; - - exp = (((exp >> 24) & 0xff) & 0x80) - 0x80; - sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000; - - memset (r, 0, sizeof (*r)); - - if (exp != -128) - { - r->cl = rvc_normal; - - sig = sf & 0x7fffffff; - if (sf < 0) - { - r->sign = 1; - if (sig) - sig = -sig; - else - exp++; - } - if (HOST_BITS_PER_LONG == 64) - sig = sig << 1 << 31; - sig |= SIG_MSB; - - SET_REAL_EXP (r, exp + 1); - r->sig[SIGSZ-1] = sig; - } -} - -const struct real_format c4x_single_format = - { - encode_c4x_single, - decode_c4x_single, - 2, - 1, - 24, - 24, - -126, - 128, - 23, - -1, - false, - false, - false, - false, - false - }; - -const struct real_format c4x_extended_format = - { - encode_c4x_extended, - decode_c4x_extended, - 2, - 1, - 32, - 32, - -126, - 128, - 31, - -1, - false, - false, - false, - false, - false - }; - - -/* A synthetic "format" for internal arithmetic. It's the size of the - internal significand minus the two bits needed for proper rounding. - The encode and decode routines exist only to satisfy our paranoia - harness. */ - -static void encode_internal (const struct real_format *fmt, - long *, const REAL_VALUE_TYPE *); -static void decode_internal (const struct real_format *, - REAL_VALUE_TYPE *, const long *); - -static void -encode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, - const REAL_VALUE_TYPE *r) -{ - memcpy (buf, r, sizeof (*r)); -} - -static void -decode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED, - REAL_VALUE_TYPE *r, const long *buf) -{ - memcpy (r, buf, sizeof (*r)); -} - -const struct real_format real_internal_format = - { - encode_internal, - decode_internal, - 2, - 1, - SIGNIFICAND_BITS - 2, - SIGNIFICAND_BITS - 2, - -MAX_EXP, - MAX_EXP, - -1, - -1, - true, - true, - false, - true, - true - }; - -/* Calculate the square root of X in mode MODE, and store the result - in R. Return TRUE if the operation does not raise an exception. - For details see "High Precision Division and Square Root", - Alan H. Karp and Peter Markstein, HP Lab Report 93-93-42, June - 1993. http://www.hpl.hp.com/techreports/93/HPL-93-42.pdf. */ - -bool -real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode, - const REAL_VALUE_TYPE *x) -{ - static REAL_VALUE_TYPE halfthree; - static bool init = false; - REAL_VALUE_TYPE h, t, i; - int iter, exp; - - /* sqrt(-0.0) is -0.0. */ - if (real_isnegzero (x)) - { - *r = *x; - return false; - } - - /* Negative arguments return NaN. */ - if (real_isneg (x)) - { - get_canonical_qnan (r, 0); - return false; - } - - /* Infinity and NaN return themselves. */ - if (real_isinf (x) || real_isnan (x)) - { - *r = *x; - return false; - } - - if (!init) - { - do_add (&halfthree, &dconst1, &dconsthalf, 0); - init = true; - } - - /* Initial guess for reciprocal sqrt, i. */ - exp = real_exponent (x); - real_ldexp (&i, &dconst1, -exp/2); - - /* Newton's iteration for reciprocal sqrt, i. */ - for (iter = 0; iter < 16; iter++) - { - /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x). */ - do_multiply (&t, x, &i); - do_multiply (&h, &t, &i); - do_multiply (&t, &h, &dconsthalf); - do_add (&h, &halfthree, &t, 1); - do_multiply (&t, &i, &h); - - /* Check for early convergence. */ - if (iter >= 6 && real_identical (&i, &t)) - break; - - /* ??? Unroll loop to avoid copying. */ - i = t; - } - - /* Final iteration: r = i*x + 0.5*i*x*(1.0 - i*(i*x)). */ - do_multiply (&t, x, &i); - do_multiply (&h, &t, &i); - do_add (&i, &dconst1, &h, 1); - do_multiply (&h, &t, &i); - do_multiply (&i, &dconsthalf, &h); - do_add (&h, &t, &i, 0); - - /* ??? We need a Tuckerman test to get the last bit. */ - - real_convert (r, mode, &h); - return true; -} - -/* Calculate X raised to the integer exponent N in mode MODE and store - the result in R. Return true if the result may be inexact due to - loss of precision. The algorithm is the classic "left-to-right binary - method" described in section 4.6.3 of Donald Knuth's "Seminumerical - Algorithms", "The Art of Computer Programming", Volume 2. */ - -bool -real_powi (REAL_VALUE_TYPE *r, enum machine_mode mode, - const REAL_VALUE_TYPE *x, HOST_WIDE_INT n) -{ - unsigned HOST_WIDE_INT bit; - REAL_VALUE_TYPE t; - bool inexact = false; - bool init = false; - bool neg; - int i; - - if (n == 0) - { - *r = dconst1; - return false; - } - else if (n < 0) - { - /* Don't worry about overflow, from now on n is unsigned. */ - neg = true; - n = -n; - } - else - neg = false; - - t = *x; - bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); - for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++) - { - if (init) - { - inexact |= do_multiply (&t, &t, &t); - if (n & bit) - inexact |= do_multiply (&t, &t, x); - } - else if (n & bit) - init = true; - bit >>= 1; - } - - if (neg) - inexact |= do_divide (&t, &dconst1, &t); - - real_convert (r, mode, &t); - return inexact; -} - -/* Round X to the nearest integer not larger in absolute value, i.e. - towards zero, placing the result in R in mode MODE. */ - -void -real_trunc (REAL_VALUE_TYPE *r, enum machine_mode mode, - const REAL_VALUE_TYPE *x) -{ - do_fix_trunc (r, x); - if (mode != VOIDmode) - real_convert (r, mode, r); -} - -/* Round X to the largest integer not greater in value, i.e. round - down, placing the result in R in mode MODE. */ - -void -real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode, - const REAL_VALUE_TYPE *x) -{ - REAL_VALUE_TYPE t; - - do_fix_trunc (&t, x); - if (! real_identical (&t, x) && x->sign) - do_add (&t, &t, &dconstm1, 0); - if (mode != VOIDmode) - real_convert (r, mode, &t); - else - *r = t; -} - -/* Round X to the smallest integer not less then argument, i.e. round - up, placing the result in R in mode MODE. */ - -void -real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode, - const REAL_VALUE_TYPE *x) -{ - REAL_VALUE_TYPE t; - - do_fix_trunc (&t, x); - if (! real_identical (&t, x) && ! x->sign) - do_add (&t, &t, &dconst1, 0); - if (mode != VOIDmode) - real_convert (r, mode, &t); - else - *r = t; -} - -/* Round X to the nearest integer, but round halfway cases away from - zero. */ - -void -real_round (REAL_VALUE_TYPE *r, enum machine_mode mode, - const REAL_VALUE_TYPE *x) -{ - do_add (r, x, &dconsthalf, x->sign); - do_fix_trunc (r, r); - if (mode != VOIDmode) - real_convert (r, mode, r); -} - -/* Set the sign of R to the sign of X. */ - -void -real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x) -{ - r->sign = x->sign; -} - |