| Index: gcc/gcc/real.c
|
| diff --git a/gcc/gcc/real.c b/gcc/gcc/real.c
|
| index d4a3941e67e59fbef153e2699ccddb34b2437f2a..25e599dfe352e4f2d57a0721c87f6d9702c9cc63 100644
|
| --- a/gcc/gcc/real.c
|
| +++ b/gcc/gcc/real.c
|
| @@ -57,7 +57,7 @@
|
|
|
| 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.
|
| + denormal number fits in 17 exponent bits; we store 26.
|
|
|
| Note that the decimal string conversion routines are sensitive to
|
| rounding errors. Since the raw arithmetic routines do not themselves
|
| @@ -1000,10 +1000,10 @@ bool
|
| real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
|
| const REAL_VALUE_TYPE *op1)
|
| {
|
| - enum tree_code code = icode;
|
| + enum tree_code code = (enum tree_code) icode;
|
|
|
| if (op0->decimal || (op1 && op1->decimal))
|
| - return decimal_real_arithmetic (r, icode, op0, op1);
|
| + return decimal_real_arithmetic (r, code, op0, op1);
|
|
|
| switch (code)
|
| {
|
| @@ -1072,7 +1072,7 @@ bool
|
| real_compare (int icode, const REAL_VALUE_TYPE *op0,
|
| const REAL_VALUE_TYPE *op1)
|
| {
|
| - enum tree_code code = icode;
|
| + enum tree_code code = (enum tree_code) icode;
|
|
|
| switch (code)
|
| {
|
| @@ -1343,7 +1343,7 @@ real_to_integer (const REAL_VALUE_TYPE *r)
|
|
|
| if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
|
| i = r->sig[SIGSZ-1];
|
| - else
|
| + else
|
| {
|
| gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG);
|
| i = r->sig[SIGSZ-1];
|
| @@ -1394,11 +1394,11 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
|
|
|
| case rvc_normal:
|
| if (r->decimal)
|
| - {
|
| + {
|
| decimal_real_to_integer2 (plow, phigh, r);
|
| return;
|
| }
|
| -
|
| +
|
| exp = REAL_EXP (r);
|
| if (exp <= 0)
|
| goto underflow;
|
| @@ -1415,7 +1415,7 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
|
| high = t.sig[SIGSZ-1];
|
| low = t.sig[SIGSZ-2];
|
| }
|
| - else
|
| + else
|
| {
|
| gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
|
| high = t.sig[SIGSZ-1];
|
| @@ -2117,7 +2117,7 @@ real_from_string2 (const char *s, enum machine_mode mode)
|
|
|
| /* Initialize R from string S and desired MODE. */
|
|
|
| -void
|
| +void
|
| real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode)
|
| {
|
| if (DECIMAL_FLOAT_MODE_P (mode))
|
| @@ -2126,8 +2126,8 @@ real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode)
|
| real_from_string (r, s);
|
|
|
| if (mode != VOIDmode)
|
| - real_convert (r, mode, r);
|
| -}
|
| + real_convert (r, mode, r);
|
| +}
|
|
|
| /* Initialize R from the integer pair HIGH+LOW. */
|
|
|
| @@ -2342,7 +2342,7 @@ dconst_e_ptr (void)
|
| mpfr_exp (m, m, GMP_RNDN);
|
| real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
|
| mpfr_clear (m);
|
| -
|
| +
|
| }
|
| return &value;
|
| }
|
| @@ -2497,7 +2497,7 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
|
| fmt = REAL_MODE_FORMAT (mode);
|
| gcc_assert (fmt);
|
| memset (r, 0, sizeof (*r));
|
| -
|
| +
|
| if (fmt->b == 10)
|
| decimal_real_maxval (r, sign, mode);
|
| else
|
| @@ -4459,41 +4459,41 @@ const struct real_format vax_g_format =
|
| /* 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,
|
| + 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
|
| +static void
|
| decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
| - REAL_VALUE_TYPE *r 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
|
| +static void
|
| encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
| - long *buf 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
|
| +static void
|
| decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
| - REAL_VALUE_TYPE *r 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
|
| +static void
|
| encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
| long *buf ATTRIBUTE_UNUSED,
|
| const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
|
| @@ -4502,7 +4502,7 @@ encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
| }
|
|
|
| /* Decode a quad precision DFP value in BUF into a real R. */
|
| -static void
|
| +static void
|
| decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
| REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
|
| const long *buf ATTRIBUTE_UNUSED)
|
| @@ -4515,7 +4515,7 @@ const struct real_format decimal_single_format =
|
| {
|
| encode_decimal_single,
|
| decode_decimal_single,
|
| - 10,
|
| + 10,
|
| 7,
|
| 7,
|
| -94,
|
| @@ -4527,7 +4527,7 @@ const struct real_format decimal_single_format =
|
| true,
|
| true,
|
| true,
|
| - true,
|
| + true,
|
| true,
|
| false
|
| };
|
| @@ -4570,11 +4570,172 @@ const struct real_format decimal_quad_format =
|
| true,
|
| true,
|
| true,
|
| - true,
|
| - true,
|
| + true,
|
| + true,
|
| + true,
|
| + false
|
| + };
|
| +
|
| +/* Encode half-precision floats. This routine is used both for the IEEE
|
| + ARM alternative encodings. */
|
| +static void
|
| +encode_ieee_half (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 << 15;
|
| + sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 11)) & 0x3ff;
|
| +
|
| + switch (r->cl)
|
| + {
|
| + case rvc_zero:
|
| + break;
|
| +
|
| + case rvc_inf:
|
| + if (fmt->has_inf)
|
| + image |= 31 << 10;
|
| + else
|
| + image |= 0x7fff;
|
| + break;
|
| +
|
| + case rvc_nan:
|
| + if (fmt->has_nans)
|
| + {
|
| + if (r->canonical)
|
| + sig = (fmt->canonical_nan_lsbs_set ? (1 << 9) - 1 : 0);
|
| + if (r->signalling == fmt->qnan_msb_set)
|
| + sig &= ~(1 << 9);
|
| + else
|
| + sig |= 1 << 9;
|
| + if (sig == 0)
|
| + sig = 1 << 8;
|
| +
|
| + image |= 31 << 10;
|
| + image |= sig;
|
| + }
|
| + else
|
| + image |= 0x3ff;
|
| + 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) + 15 - 1;
|
| + image |= exp << 10;
|
| + image |= sig;
|
| + break;
|
| +
|
| + default:
|
| + gcc_unreachable ();
|
| + }
|
| +
|
| + buf[0] = image;
|
| +}
|
| +
|
| +/* Decode half-precision floats. This routine is used both for the IEEE
|
| + ARM alternative encodings. */
|
| +static void
|
| +decode_ieee_half (const struct real_format *fmt, REAL_VALUE_TYPE *r,
|
| + const long *buf)
|
| +{
|
| + unsigned long image = buf[0] & 0xffff;
|
| + bool sign = (image >> 15) & 1;
|
| + int exp = (image >> 10) & 0x1f;
|
| +
|
| + memset (r, 0, sizeof (*r));
|
| + image <<= HOST_BITS_PER_LONG - 11;
|
| + image &= ~SIG_MSB;
|
| +
|
| + if (exp == 0)
|
| + {
|
| + if (image && fmt->has_denorm)
|
| + {
|
| + r->cl = rvc_normal;
|
| + r->sign = sign;
|
| + SET_REAL_EXP (r, -14);
|
| + r->sig[SIGSZ-1] = image << 1;
|
| + normalize (r);
|
| + }
|
| + else if (fmt->has_signed_zero)
|
| + r->sign = sign;
|
| + }
|
| + else if (exp == 31 && (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 - 15 + 1);
|
| + r->sig[SIGSZ-1] = image | SIG_MSB;
|
| + }
|
| +}
|
| +
|
| +/* Half-precision format, as specified in IEEE 754R. */
|
| +const struct real_format ieee_half_format =
|
| + {
|
| + encode_ieee_half,
|
| + decode_ieee_half,
|
| + 2,
|
| + 11,
|
| + 11,
|
| + -13,
|
| + 16,
|
| + 15,
|
| + 15,
|
| + false,
|
| + true,
|
| + true,
|
| + true,
|
| + true,
|
| + true,
|
| true,
|
| false
|
| };
|
| +
|
| +/* ARM's alternative half-precision format, similar to IEEE but with
|
| + no reserved exponent value for NaNs and infinities; rather, it just
|
| + extends the range of exponents by one. */
|
| +const struct real_format arm_half_format =
|
| + {
|
| + encode_ieee_half,
|
| + decode_ieee_half,
|
| + 2,
|
| + 11,
|
| + 11,
|
| + -13,
|
| + 17,
|
| + 15,
|
| + 15,
|
| + false,
|
| + true,
|
| + false,
|
| + false,
|
| + true,
|
| + true,
|
| + false,
|
| + false
|
| + };
|
|
|
| /* A synthetic "format" for internal arithmetic. It's the size of the
|
| internal significand minus the two bits needed for proper rounding.
|
| @@ -4837,13 +4998,13 @@ mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode)
|
| 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. */
|
| @@ -4893,7 +5054,7 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode)
|
| sprintf (buf, "0x.%sp%d", rstr, (int) exp);
|
|
|
| mpfr_free_str (rstr);
|
| -
|
| +
|
| real_from_string (r, buf);
|
| }
|
|
|
|
|