X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Freal.c;h=dc6d7483e998824e509e72953becec5c610e3de1;hb=a55e30dca65991b3c45bbf3d9515bf97cc1a3e9b;hp=b6e5ed6ee3e9a5a3f79bc1223b47c5925667f21b;hpb=b044deec88e847736d4bf49f2ac1978518d81a68;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/real.c b/gcc/real.c index b6e5ed6ee3e..dc6d7483e99 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1,6 +1,6 @@ /* real.c - software floating point emulation. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. Contributed by Stephen L. Moshier (moshier@world.std.com). Re-written by Richard Henderson @@ -8,7 +8,7 @@ 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 + Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -17,9 +17,8 @@ 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. */ + along with GCC; see the file COPYING3. If not see + . */ #include "config.h" #include "system.h" @@ -65,12 +64,7 @@ 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. */ + layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits. */ /* Used to classify two numbers simultaneously. */ @@ -1168,6 +1162,14 @@ real_isnan (const REAL_VALUE_TYPE *r) return (r->cl == rvc_nan); } +/* Determine whether a floating-point value X is finite. */ + +bool +real_isfinite (const REAL_VALUE_TYPE *r) +{ + return (r->cl != rvc_nan) && (r->cl != rvc_inf); +} + /* Determine whether a floating-point value X is negative. */ bool @@ -1441,20 +1443,30 @@ rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den) /* 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. */ + zeros. If MODE is VOIDmode, round to nearest value. Otherwise, round + to a string that, when parsed back in mode MODE, yields the same value. */ #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) +real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig, + size_t buf_size, size_t digits, + int crop_trailing_zeros, enum machine_mode mode) { + const struct real_format *fmt = NULL; 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; + bool round_up; + + if (mode != VOIDmode) + { + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); + } r = *r_orig; switch (r.cl) @@ -1469,7 +1481,8 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, return; case rvc_nan: /* ??? Print the significand as well, if not canonical? */ - strcpy (str, (r.sign ? "-NaN" : "+NaN")); + sprintf (str, "%c%cNaN", (r_orig->sign ? '-' : '+'), + (r_orig->signalling ? 'S' : 'Q')); return; default: gcc_unreachable (); @@ -1669,17 +1682,31 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, digit = rtd_divmod (&r, &pten); /* Round the result. */ - if (digit == 5) + if (fmt && fmt->round_towards_zero) { - /* Round to nearest. If R is nonzero there are additional - nonzero digits to be extracted. */ + /* If the format uses round towards zero when parsing the string + back in, we need to always round away from zero here. */ if (cmp_significand_0 (&r)) digit++; - /* Round to even. */ - else if ((p[-1] - '0') & 1) - digit++; + round_up = digit > 0; + } + else + { + 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++; + } + + round_up = digit > 5; } - if (digit > 5) + + if (round_up) { while (p > first) { @@ -1713,6 +1740,26 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, /* Append the exponent. */ sprintf (last, "e%+d", dec_exp); + +#ifdef ENABLE_CHECKING + /* Verify that we can read the original value back in. */ + if (mode != VOIDmode) + { + real_from_string (&r, str); + real_convert (&r, mode, &r); + gcc_assert (real_identical (&r, r_orig)); + } +#endif +} + +/* Likewise, except always uses round-to-nearest. */ + +void +real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, + size_t digits, int crop_trailing_zeros) +{ + real_to_decimal_for_mode (str, r_orig, buf_size, + digits, crop_trailing_zeros, VOIDmode); } /* Render R as a hexadecimal floating point constant. Emit DIGITS @@ -1741,7 +1788,8 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size, return; case rvc_nan: /* ??? Print the significand as well, if not canonical? */ - strcpy (str, (r->sign ? "-NaN" : "+NaN")); + sprintf (str, "%c%cNaN", (r->sign ? '-' : '+'), + (r->signalling ? 'S' : 'Q')); return; default: gcc_unreachable (); @@ -1791,9 +1839,10 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size, } /* Initialize R from a decimal or hexadecimal string. The string is - assumed to have been syntax checked already. */ + assumed to have been syntax checked already. Return -1 if the + value underflows, +1 if overflows, and 0 otherwise. */ -void +int real_from_string (REAL_VALUE_TYPE *r, const char *str) { int exp = 0; @@ -1809,6 +1858,22 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str) else if (*str == '+') str++; + if (!strncmp (str, "QNaN", 4)) + { + get_canonical_qnan (r, sign); + return 0; + } + else if (!strncmp (str, "SNaN", 4)) + { + get_canonical_snan (r, sign); + return 0; + } + else if (!strncmp (str, "Inf", 3)) + { + get_inf (r, sign); + return 0; + } + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { /* Hexadecimal floating point. */ @@ -1865,7 +1930,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str) /* If the mantissa is zero, ignore the exponent. */ if (!cmp_significand_0 (r)) - goto underflow; + goto is_a_zero; if (*str == 'p' || *str == 'P') { @@ -1941,7 +2006,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str) /* If the mantissa is zero, ignore the exponent. */ if (r->cl == rvc_zero) - goto underflow; + goto is_a_zero; if (*str == 'e' || *str == 'E') { @@ -1981,15 +2046,19 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str) } r->sign = sign; - return; + return 0; + + is_a_zero: + get_zero (r, sign); + return 0; underflow: get_zero (r, sign); - return; + return -1; overflow: get_inf (r, sign); - return; + return 1; } /* Legacy. Similar, but return the result directly. */ @@ -2156,6 +2225,64 @@ times_pten (REAL_VALUE_TYPE *r, int exp) do_divide (r, r, &pten); } +/* Returns the special REAL_VALUE_TYPE corresponding to 'e'. */ + +const REAL_VALUE_TYPE * +dconst_e_ptr (void) +{ + static REAL_VALUE_TYPE value; + + /* Initialize mathematical constants for constant folding builtins. + These constants need to be given to at least 160 bits precision. */ + if (value.cl == rvc_zero) + { + mpfr_t m; + mpfr_init2 (m, SIGNIFICAND_BITS); + mpfr_set_ui (m, 1, GMP_RNDN); + mpfr_exp (m, m, GMP_RNDN); + real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN); + mpfr_clear (m); + + } + return &value; +} + +/* Returns the special REAL_VALUE_TYPE corresponding to 1/3. */ + +const REAL_VALUE_TYPE * +dconst_third_ptr (void) +{ + static REAL_VALUE_TYPE value; + + /* Initialize mathematical constants for constant folding builtins. + These constants need to be given to at least 160 bits precision. */ + if (value.cl == rvc_zero) + { + real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3)); + } + return &value; +} + +/* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2). */ + +const REAL_VALUE_TYPE * +dconst_sqrt2_ptr (void) +{ + static REAL_VALUE_TYPE value; + + /* Initialize mathematical constants for constant folding builtins. + These constants need to be given to at least 160 bits precision. */ + if (value.cl == rvc_zero) + { + mpfr_t m; + mpfr_init2 (m, SIGNIFICAND_BITS); + mpfr_sqrt_ui (m, 2, GMP_RNDN); + real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN); + mpfr_clear (m); + } + return &value; +} + /* Fills R with +Inf. */ void @@ -2277,9 +2404,9 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) { r->cl = rvc_normal; r->sign = sign; - SET_REAL_EXP (r, fmt->emax * fmt->log2_b); + SET_REAL_EXP (r, fmt->emax); - np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b; + np2 = SIGNIFICAND_BITS - fmt->p; memset (r->sig, -1, SIGSZ * sizeof (unsigned long)); clear_significand_below (r, np2); @@ -2290,14 +2417,14 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) 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); + clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1); } } /* Fills R with 2**N. */ void -real_2expN (REAL_VALUE_TYPE *r, int n) +real_2expN (REAL_VALUE_TYPE *r, int n, enum machine_mode fmode) { memset (r, 0, sizeof (*r)); @@ -2312,6 +2439,8 @@ real_2expN (REAL_VALUE_TYPE *r, int n) SET_REAL_EXP (r, n); r->sig[SIGSZ-1] = SIG_MSB; } + if (DECIMAL_FLOAT_MODE_P (fmode)) + decimal_real_convert (r, fmode, r); } @@ -2319,9 +2448,8 @@ 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; + bool round_up = false; if (r->decimal) { @@ -2337,9 +2465,9 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) 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; + p2 = fmt->p; + emin2m1 = fmt->emin - 1; + emax2 = fmt->emax; np2 = SIGNIFICAND_BITS - p2; switch (r->cl) @@ -2367,22 +2495,6 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) 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) @@ -2409,21 +2521,28 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) } } - /* 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. */ + if (!fmt->round_towards_zero) + { + /* 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. */ + unsigned long sticky; + bool guard, lsb; + + 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); - 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); - guard = test_significand_bit (r, np2 - 1); - lsb = test_significand_bit (r, np2); + /* Round to even. */ + round_up = guard && (sticky || lsb); + } - /* Round to even. */ - if (guard && (sticky || lsb)) + if (round_up) { REAL_VALUE_TYPE u; get_zero (&u, 0); @@ -2438,19 +2557,6 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) 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; - } - } } } @@ -2508,7 +2614,7 @@ exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a) gcc_assert (fmt); /* Don't allow conversion to denormals. */ - emin2m1 = (fmt->emin - 1) * fmt->log2_b; + emin2m1 = fmt->emin - 1; if (REAL_EXP (a) <= emin2m1) return false; @@ -2599,7 +2705,7 @@ significand_size (enum machine_mode mode) double log2_10 = 3.3219281; return fmt->p * log2_10; } - return fmt->p * fmt->log2_b; + return fmt->p; } /* Return a hash value for the given real value. */ @@ -2681,18 +2787,12 @@ encode_ieee_single (const struct real_format *fmt, long *buf, if (fmt->has_nans) { if (r->canonical) - sig = 0; + sig = (fmt->canonical_nan_lsbs_set ? (1 << 22) - 1 : 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) + if (sig == 0) sig = 1 << 21; image |= 255 << 23; @@ -2776,18 +2876,20 @@ const struct real_format ieee_single_format = encode_ieee_single, decode_ieee_single, 2, - 1, 24, 24, -125, 128, 31, 31, + false, true, true, true, true, - true + true, + true, + false }; const struct real_format mips_single_format = @@ -2795,20 +2897,74 @@ const struct real_format mips_single_format = encode_ieee_single, decode_ieee_single, 2, - 1, 24, 24, -125, 128, 31, 31, + false, true, true, true, true, - false + true, + false, + true + }; + +const struct real_format motorola_single_format = + { + encode_ieee_single, + decode_ieee_single, + 2, + 24, + 24, + -125, + 128, + 31, + 31, + false, + true, + true, + true, + true, + true, + true, + true }; +/* SPU Single Precision (Extended-Range Mode) format is the same as IEEE + single precision with the following differences: + - Infinities are not supported. Instead MAX_FLOAT or MIN_FLOAT + are generated. + - NaNs are not supported. + - The range of non-zero numbers in binary is + (001)[1.]000...000 to (255)[1.]111...111. + - Denormals can be represented, but are treated as +0.0 when + used as an operand and are never generated as a result. + - -0.0 can be represented, but a zero result is always +0.0. + - the only supported rounding mode is trunction (towards zero). */ +const struct real_format spu_single_format = + { + encode_ieee_single, + decode_ieee_single, + 2, + 24, + 24, + -125, + 129, + 31, + 31, + true, + false, + false, + false, + true, + true, + false, + false + }; /* IEEE double-precision format. */ @@ -2860,21 +3016,23 @@ encode_ieee_double (const struct real_format *fmt, long *buf, if (fmt->has_nans) { if (r->canonical) - sig_hi = sig_lo = 0; + { + if (fmt->canonical_nan_lsbs_set) + { + sig_hi = (1 << 19) - 1; + sig_lo = 0xffffffff; + } + else + { + sig_hi = 0; + 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) + if (sig_hi == 0 && sig_lo == 0) sig_hi = 1 << 18; image_hi |= 2047 << 20; @@ -3001,18 +3159,20 @@ const struct real_format ieee_double_format = encode_ieee_double, decode_ieee_double, 2, - 1, 53, 53, -1021, 1024, 63, 63, + false, true, true, true, true, - true + true, + true, + false }; const struct real_format mips_double_format = @@ -3020,20 +3180,42 @@ const struct real_format mips_double_format = encode_ieee_double, decode_ieee_double, 2, - 1, 53, 53, -1021, 1024, 63, 63, + false, true, true, true, true, - false + true, + false, + true }; +const struct real_format motorola_double_format = + { + encode_ieee_double, + decode_ieee_double, + 2, + 53, + 53, + -1021, + 1024, + 63, + 63, + false, + true, + true, + true, + true, + true, + true, + true + }; /* 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 @@ -3079,7 +3261,15 @@ encode_ieee_extended (const struct real_format *fmt, long *buf, if (fmt->has_nans) { image_hi |= 32767; - if (HOST_BITS_PER_LONG == 32) + if (r->canonical) + { + if (fmt->canonical_nan_lsbs_set) + { + sig_hi = (1 << 30) - 1; + sig_lo = 0xffffffff; + } + } + else if (HOST_BITS_PER_LONG == 32) { sig_hi = r->sig[SIGSZ-1]; sig_lo = r->sig[SIGSZ-2]; @@ -3350,13 +3540,15 @@ const struct real_format ieee_extended_motorola_format = encode_ieee_extended_motorola, decode_ieee_extended_motorola, 2, - 1, 64, 64, -16382, 16384, 95, 95, + false, + true, + true, true, true, true, @@ -3369,18 +3561,20 @@ 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, + false, true, true, true, true, - true + true, + true, + false }; const struct real_format ieee_extended_intel_128_format = @@ -3388,18 +3582,20 @@ 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, + false, true, true, true, true, - true + true, + true, + false }; /* The following caters to i386 systems that set the rounding precision @@ -3409,18 +3605,20 @@ 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, + false, true, true, true, true, - true + true, + true, + false }; /* IBM 128-bit extended precision format: a pair of IEEE double precision @@ -3445,7 +3643,7 @@ encode_ibm_extended (const struct real_format *fmt, long *buf, base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format; - /* Renormlize R before doing any arithmetic on it. */ + /* Renormalize R before doing any arithmetic on it. */ normr = *r; if (normr.cl == rvc_normal) normalize (&normr); @@ -3495,18 +3693,20 @@ const struct real_format ibm_extended_format = encode_ibm_extended, decode_ibm_extended, 2, - 1, 53 + 53, 53, -1021 + 53, 1024, 127, -1, + false, true, true, true, true, - true + true, + true, + false }; const struct real_format mips_extended_format = @@ -3514,18 +3714,20 @@ const struct real_format mips_extended_format = encode_ibm_extended, decode_ibm_extended, 2, - 1, 53 + 53, 53, -1021 + 53, 1024, 127, -1, + false, true, true, true, true, - false + true, + false, + true }; @@ -3575,8 +3777,11 @@ encode_ieee_quad (const struct real_format *fmt, long *buf, if (r->canonical) { - /* Don't use bits from the significand. The - initialization above is right. */ + if (fmt->canonical_nan_lsbs_set) + { + image3 |= 0x7fff; + image2 = image1 = image0 = 0xffffffff; + } } else if (HOST_BITS_PER_LONG == 32) { @@ -3598,16 +3803,7 @@ encode_ieee_quad (const struct real_format *fmt, long *buf, 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) + if (((image3 & 0xffff) | image2 | image1 | image0) == 0) image3 |= 0x4000; } else @@ -3781,18 +3977,20 @@ const struct real_format ieee_quad_format = encode_ieee_quad, decode_ieee_quad, 2, - 1, 113, 113, -16381, 16384, 127, 127, + false, true, true, true, true, - true + true, + true, + false }; const struct real_format mips_quad_format = @@ -3800,18 +3998,20 @@ const struct real_format mips_quad_format = encode_ieee_quad, decode_ieee_quad, 2, - 1, 113, 113, -16381, 16384, 127, 127, + false, true, true, true, true, - false + true, + false, + true }; /* Descriptions of VAX floating point formats can be found beginning at @@ -4098,7 +4298,6 @@ const struct real_format vax_f_format = encode_vax_f, decode_vax_f, 2, - 1, 24, 24, -127, @@ -4109,6 +4308,9 @@ const struct real_format vax_f_format = false, false, false, + false, + false, + false, false }; @@ -4117,7 +4319,6 @@ const struct real_format vax_d_format = encode_vax_d, decode_vax_d, 2, - 1, 56, 56, -127, @@ -4128,6 +4329,9 @@ const struct real_format vax_d_format = false, false, false, + false, + false, + false, false }; @@ -4136,7 +4340,6 @@ const struct real_format vax_g_format = encode_vax_g, decode_vax_g, 2, - 1, 53, 53, -1023, @@ -4147,221 +4350,29 @@ const struct real_format vax_g_format = false, false, 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 *); - +/* Encode real R into a single precision DFP value in BUF. */ static void -encode_i370_single (const struct real_format *fmt ATTRIBUTE_UNUSED, - long *buf, const REAL_VALUE_TYPE *r) +encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, + long *buf ATTRIBUTE_UNUSED, + const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) { - unsigned long sign, exp, sig, image; + encode_decimal32 (fmt, buf, r); +} - 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); -} +/* 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 @@ -4399,294 +4410,71 @@ decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, decode_decimal128 (fmt, r, buf); } -/* Single precision decimal floating point (IEEE 754R). */ +/* Single precision decimal floating point (IEEE 754). */ const struct real_format decimal_single_format = { encode_decimal_single, decode_decimal_single, 10, - 1, /* log10 */ 7, 7, -95, 96, 31, 31, + false, + true, true, true, true, true, - true + true, + false }; -/* Double precision decimal floating point (IEEE 754R). */ +/* Double precision decimal floating point (IEEE 754). */ const struct real_format decimal_double_format = { encode_decimal_double, decode_decimal_double, 10, - 1, /* log10 */ 16, 16, -383, 384, 63, 63, + false, true, true, true, true, - true + true, + true, + false }; -/* Quad precision decimal floating point (IEEE 754R). */ +/* Quad precision decimal floating point (IEEE 754). */ const struct real_format decimal_quad_format = { encode_decimal_quad, decode_decimal_quad, 10, - 1, /* log10 */ 34, 34, -6143, 6144, 127, 127, + false, + true, 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, + true, false }; - /* A synthetic "format" for internal arithmetic. It's the size of the internal significand minus the two bits needed for proper rounding. @@ -4717,18 +4505,20 @@ 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, + false, + false, true, true, false, true, - true + true, + false }; /* Calculate the square root of X in mode MODE, and store the result @@ -4761,7 +4551,7 @@ real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode, } /* Infinity and NaN return themselves. */ - if (real_isinf (x) || real_isnan (x)) + if (!real_isfinite (x)) { *r = *x; return false; @@ -4935,29 +4725,58 @@ real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x) for initializing and clearing the MPFR parameter. */ void -mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r) +mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode) { /* We use a string as an intermediate type. */ char buf[128]; int ret; + /* Take care of Infinity and NaN. */ + if (r->cl == rvc_inf) + { + mpfr_set_inf (m, r->sign == 1 ? -1 : 1); + return; + } + + if (r->cl == rvc_nan) + { + mpfr_set_nan (m); + return; + } + real_to_hexadecimal (buf, r, sizeof (buf), 0, 1); /* mpfr_set_str() parses hexadecimal floats from strings in the same format that GCC will output them. Nothing extra is needed. */ - ret = mpfr_set_str (m, buf, 16, GMP_RNDN); + ret = mpfr_set_str (m, buf, 16, rndmode); gcc_assert (ret == 0); } -/* Convert from MPFR to REAL_VALUE_TYPE. */ +/* Convert from MPFR to REAL_VALUE_TYPE, for a given type TYPE and rounding + mode RNDMODE. TYPE is only relevant if M is a NaN. */ void -real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m) +real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode) { /* We use a string as an intermediate type. */ char buf[128], *rstr; mp_exp_t exp; - rstr = mpfr_get_str (NULL, &exp, 16, 0, m, GMP_RNDN); + /* Take care of Infinity and NaN. */ + if (mpfr_inf_p (m)) + { + real_inf (r); + if (mpfr_sgn (m) < 0) + *r = REAL_VALUE_NEGATE (*r); + return; + } + + if (mpfr_nan_p (m)) + { + real_nan (r, "", 1, TYPE_MODE (type)); + return; + } + + rstr = mpfr_get_str (NULL, &exp, 16, 0, m, rndmode); /* The additional 12 chars add space for the sprintf below. This leaves 6 digits for the exponent which is supposedly enough. */ @@ -4988,3 +4807,35 @@ real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode) real_trunc (&cint, mode, c); return real_identical (c, &cint); } + +/* Write into BUF the maximum representable finite floating-point + number, (1 - b**-p) * b**emax for a given FP format FMT as a hex + float string. LEN is the size of BUF, and the buffer must be large + enough to contain the resulting string. */ + +void +get_max_float (const struct real_format *fmt, char *buf, size_t len) +{ + int i, n; + char *p; + + strcpy (buf, "0x0."); + n = fmt->p; + for (i = 0, p = buf + 4; i + 3 < n; i += 4) + *p++ = 'f'; + if (i < n) + *p++ = "08ce"[n - i]; + sprintf (p, "p%d", fmt->emax); + 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. */ + buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4]; + } + + gcc_assert (strlen (buf) < len); +}