/* real.c - software floating point emulation.
- Copyright (C) 1993-2015 Free Software Foundation, Inc.
+ Copyright (C) 1993-2020 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
Re-written by Richard Henderson <rth@redhat.com>
for (i = 0; i < w; ++i)
r->sig[i] = 0;
- r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
+ /* We are actually passing N == SIGNIFICAND_BITS which would result
+ in an out-of-bound access below. */
+ if (n % HOST_BITS_PER_LONG != 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
case CLASS2 (rvc_normal, rvc_inf):
/* R + Inf = Inf. */
*r = *b;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
r->sign = sign ^ subtract_p;
return false;
case CLASS2 (rvc_inf, rvc_normal):
/* Inf + R = Inf. */
*r = *a;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
return false;
case CLASS2 (rvc_inf, rvc_inf):
case CLASS2 (rvc_nan, rvc_nan):
/* ANY * NaN = NaN. */
*r = *b;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
r->sign = sign;
return false;
case CLASS2 (rvc_nan, rvc_inf):
/* NaN * ANY = NaN. */
*r = *a;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
r->sign = sign;
return false;
case CLASS2 (rvc_nan, rvc_nan):
/* ANY / NaN = NaN. */
*r = *b;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
r->sign = sign;
return false;
case CLASS2 (rvc_nan, rvc_inf):
/* NaN / ANY = NaN. */
*r = *a;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
r->sign = sign;
return false;
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 (a->sign != b->sign)
+ return -a->sign - -b->sign;
+
if (REAL_EXP (a) > REAL_EXP (b))
ret = 1;
else if (REAL_EXP (a) < REAL_EXP (b))
case rvc_zero:
case rvc_inf:
case rvc_nan:
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
break;
case rvc_normal:
case MIN_EXPR:
if (op1->cl == rvc_nan)
+ {
*r = *op1;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
+ }
else if (do_compare (op0, op1, -1) < 0)
*r = *op0;
else
case MAX_EXPR:
if (op1->cl == rvc_nan)
+ {
*r = *op1;
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
+ }
else if (do_compare (op0, op1, 1) < 0)
*r = *op1;
else
case rvc_zero:
case rvc_inf:
case rvc_nan:
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ r->signalling = 0;
break;
case rvc_normal:
return (r->cl == rvc_nan);
}
+/* Determine whether a floating-point value X is a signaling NaN. */
+bool real_issignaling_nan (const REAL_VALUE_TYPE *r)
+{
+ return real_isnan (r) && r->signalling;
+}
+
/* Determine whether a floating-point value X is finite. */
bool
case rvc_inf:
case rvc_nan:
overflow:
- i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+ i = HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1);
if (!r->sign)
i--;
return i;
do_multiply (&u, &v, ten);
- /* Stop if we're now >= 1. */
- if (REAL_EXP (&u) > 0)
+ /* Stop if we're now >= 1 or zero. */
+ if (REAL_EXP (&u) > 0 || u.cl == rvc_zero)
break;
v = u;
/* Nonzero value, possibly overflowing or underflowing. */
mpfr_init2 (m, SIGNIFICAND_BITS);
- inexact = mpfr_strtofr (m, str, NULL, 10, GMP_RNDZ);
+ inexact = mpfr_strtofr (m, str, NULL, 10, MPFR_RNDZ);
/* The result should never be a NaN, and because the rounding is
toward zero should never be an infinity. */
gcc_assert (!mpfr_nan_p (m) && !mpfr_inf_p (m));
}
else
{
- real_from_mpfr (r, m, NULL_TREE, GMP_RNDZ);
+ real_from_mpfr (r, m, NULL_TREE, MPFR_RNDZ);
/* 1 to 3 bits may have been shifted off (with a sticky bit)
because the hex digits used in real_from_mpfr did not
start with a digit 8 to f, but the exponent bounds above
if (fmt.decimal_p ())
decimal_from_integer (r);
- else if (fmt)
+ if (fmt)
real_convert (r, fmt, r);
}
{
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_set_ui (m, 1, MPFR_RNDN);
+ mpfr_exp (m, m, MPFR_RNDN);
+ real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN);
mpfr_clear (m);
}
{
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_sqrt_ui (m, 2, MPFR_RNDN);
+ real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN);
mpfr_clear (m);
}
return &value;
/* Our MSB is always unset for NaNs. */
r->sig[SIGSZ-1] &= ~SIG_MSB;
- /* Force quiet or signalling NaN. */
+ /* Force quiet or signaling NaN. */
r->signalling = !quiet;
}
{
underflow:
get_zero (r, r->sign);
+ /* FALLTHRU */
case rvc_zero:
if (!fmt->has_signed_zero)
r->sign = 0;
round_for_format (fmt, r);
+ /* Make resulting NaN value to be qNaN. The caller has the
+ responsibility to avoid the operation if flag_signaling_nans
+ is on. */
+ if (r->cl == rvc_nan)
+ r->signalling = 0;
+
/* round_for_format de-normalizes denormals. Undo just that part. */
if (r->cl == rvc_normal)
normalize (r);
return h;
case rvc_normal:
- h |= REAL_EXP (r) << 3;
+ h |= (unsigned int)REAL_EXP (r) << 3;
break;
case rvc_nan:
128,
31,
31,
+ 32,
false,
true,
true,
128,
31,
31,
+ 32,
false,
true,
true,
128,
31,
31,
+ 32,
false,
true,
true,
129,
31,
31,
+ 0,
true,
false,
false,
1024,
63,
63,
+ 64,
false,
true,
true,
1024,
63,
63,
+ 64,
false,
true,
true,
1024,
63,
63,
+ 64,
false,
true,
true,
16384,
95,
95,
+ 0,
false,
true,
true,
16384,
79,
79,
+ 65,
false,
true,
true,
16384,
79,
79,
+ 65,
false,
true,
true,
16384,
79,
79,
+ 33,
false,
true,
true,
1024,
127,
-1,
+ 0,
false,
true,
true,
1024,
127,
-1,
+ 0,
false,
true,
true,
16384,
127,
127,
+ 128,
false,
true,
true,
16384,
127,
127,
+ 128,
false,
true,
true,
127,
15,
15,
+ 0,
false,
false,
false,
127,
15,
15,
+ 0,
false,
false,
false,
1023,
15,
15,
+ 0,
false,
false,
false,
97,
31,
31,
+ 32,
false,
true,
true,
385,
63,
63,
+ 64,
false,
true,
true,
6145,
127,
127,
+ 128,
false,
true,
true,
}
}
+/* Encode arm_bfloat types. */
+static void
+encode_arm_bfloat_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 - 8)) & 0x7f;
+
+ switch (r->cl)
+ {
+ case rvc_zero:
+ break;
+
+ case rvc_inf:
+ if (fmt->has_inf)
+ image |= 255 << 7;
+ else
+ image |= 0x7fff;
+ break;
+
+ case rvc_nan:
+ if (fmt->has_nans)
+ {
+ if (r->canonical)
+ sig = (fmt->canonical_nan_lsbs_set ? (1 << 6) - 1 : 0);
+ if (r->signalling == fmt->qnan_msb_set)
+ sig &= ~(1 << 6);
+ else
+ sig |= 1 << 6;
+ if (sig == 0)
+ sig = 1 << 5;
+
+ image |= 255 << 7;
+ image |= sig;
+ }
+ else
+ image |= 0x7fff;
+ break;
+
+ case rvc_normal:
+ if (denormal)
+ exp = 0;
+ else
+ exp = REAL_EXP (r) + 127 - 1;
+ image |= exp << 7;
+ image |= sig;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ buf[0] = image;
+}
+
+/* Decode arm_bfloat types. */
+static void
+decode_arm_bfloat_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 >> 7) & 0xff;
+
+ memset (r, 0, sizeof (*r));
+ image <<= HOST_BITS_PER_LONG - 8;
+ 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;
+ }
+}
+
/* Half-precision format, as specified in IEEE 754R. */
const struct real_format ieee_half_format =
{
16,
15,
15,
+ 16,
false,
true,
true,
17,
15,
15,
+ 0,
false,
true,
false,
false,
"arm_half"
};
+
+/* ARM Bfloat half-precision format. This format resembles a truncated
+ (16-bit) version of the 32-bit IEEE 754 single-precision floating-point
+ format. */
+const struct real_format arm_bfloat_half_format =
+ {
+ encode_arm_bfloat_half,
+ decode_arm_bfloat_half,
+ 2,
+ 8,
+ 8,
+ -125,
+ 128,
+ 15,
+ 15,
+ 0,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ true,
+ false,
+ "arm_bfloat_half"
+ };
+
\f
/* A synthetic "format" for internal arithmetic. It's the size of the
internal significand minus the two bits needed for proper rounding.
MAX_EXP,
-1,
-1,
+ 0,
false,
false,
true,
neg = false;
t = *x;
- bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+ bit = HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1);
for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
{
if (init)
real_convert (r, fmt, r);
}
+/* Return true (including 0) if integer part of R is even, else return
+ false. The function is not valid for rvc_inf and rvc_nan classes. */
+
+static bool
+is_even (REAL_VALUE_TYPE *r)
+{
+ gcc_assert (r->cl != rvc_inf);
+ gcc_assert (r->cl != rvc_nan);
+
+ if (r->cl == rvc_zero)
+ return true;
+
+ /* For (-1,1), number is even. */
+ if (REAL_EXP (r) <= 0)
+ return true;
+
+ /* Check lowest bit, if not set, return true. */
+ else if (REAL_EXP (r) <= SIGNIFICAND_BITS)
+ {
+ unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+ int w = n / HOST_BITS_PER_LONG;
+
+ unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG));
+
+ if ((r->sig[w] & num) == 0)
+ return true;
+ }
+ else
+ return true;
+
+ return false;
+}
+
+/* Return true if R is halfway between two integers, else return
+ false. */
+
+static bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+ if (r->cl != rvc_normal)
+ return false;
+
+ /* For numbers (-0.5,0) and (0,0.5). */
+ if (REAL_EXP (r) < 0)
+ return false;
+
+ else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+ {
+ unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r) - 1;
+ int w = n / HOST_BITS_PER_LONG;
+
+ for (int i = 0; i < w; ++i)
+ if (r->sig[i] != 0)
+ return false;
+
+ unsigned long num = 1UL << (n % HOST_BITS_PER_LONG);
+
+ if ((r->sig[w] & num) != 0 && (r->sig[w] & (num - 1)) == 0)
+ return true;
+ }
+ return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+ const REAL_VALUE_TYPE *x)
+{
+ if (is_halfway_below (x))
+ {
+ /* Special case as -0.5 rounds to -0.0 and
+ similarly +0.5 rounds to +0.0. */
+ if (REAL_EXP (x) == 0)
+ {
+ *r = *x;
+ clear_significand_below (r, SIGNIFICAND_BITS);
+ }
+ else
+ {
+ do_add (r, x, &dconsthalf, x->sign);
+ if (!is_even (r))
+ do_add (r, r, &dconstm1, x->sign);
+ }
+ if (fmt)
+ real_convert (r, fmt, r);
+ }
+ else
+ real_round (r, fmt, x);
+}
+
/* Set the sign of R to the sign of X. */
void
r->sign = x->sign;
}
-/* Check whether the real constant value given is an integer. */
+/* Check whether the real constant value given is an integer.
+ Returns false for signaling NaN. */
bool
real_isinteger (const REAL_VALUE_TYPE *c, format_helper fmt)
return false;
}
+/* Calculate nextafter (X, Y) or nexttoward (X, Y). Return true if
+ underflow or overflow needs to be raised. */
+
+bool
+real_nextafter (REAL_VALUE_TYPE *r, format_helper fmt,
+ const REAL_VALUE_TYPE *x, const REAL_VALUE_TYPE *y)
+{
+ int cmp = do_compare (x, y, 2);
+ /* If either operand is NaN, return qNaN. */
+ if (cmp == 2)
+ {
+ get_canonical_qnan (r, 0);
+ return false;
+ }
+ /* If x == y, return y cast to target type. */
+ if (cmp == 0)
+ {
+ real_convert (r, fmt, y);
+ return false;
+ }
+
+ if (x->cl == rvc_zero)
+ {
+ get_zero (r, y->sign);
+ r->cl = rvc_normal;
+ SET_REAL_EXP (r, fmt->emin - fmt->p + 1);
+ r->sig[SIGSZ - 1] = SIG_MSB;
+ return false;
+ }
+
+ int np2 = SIGNIFICAND_BITS - fmt->p;
+ /* For denormals adjust np2 correspondingly. */
+ if (x->cl == rvc_normal && REAL_EXP (x) < fmt->emin)
+ np2 += fmt->emin - REAL_EXP (x);
+
+ REAL_VALUE_TYPE u;
+ get_zero (r, x->sign);
+ get_zero (&u, 0);
+ set_significand_bit (&u, np2);
+ r->cl = rvc_normal;
+ SET_REAL_EXP (r, REAL_EXP (x));
+
+ if (x->cl == rvc_inf)
+ {
+ bool borrow = sub_significands (r, r, &u, 0);
+ gcc_assert (borrow);
+ SET_REAL_EXP (r, fmt->emax);
+ }
+ else if (cmp == (x->sign ? 1 : -1))
+ {
+ if (add_significands (r, x, &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) > fmt->emax)
+ {
+ get_inf (r, x->sign);
+ return true;
+ }
+ r->sig[SIGSZ - 1] = SIG_MSB;
+ }
+ }
+ else
+ {
+ if (REAL_EXP (x) > fmt->emin && x->sig[SIGSZ - 1] == SIG_MSB)
+ {
+ int i;
+ for (i = SIGSZ - 2; i >= 0; i--)
+ if (x->sig[i])
+ break;
+ if (i < 0)
+ {
+ /* When mantissa is 1.0, we need to subtract only
+ half of u: nextafter (1.0, 0.0) is 1.0 - __DBL_EPSILON__ / 2
+ rather than 1.0 - __DBL_EPSILON__. */
+ clear_significand_bit (&u, np2);
+ np2--;
+ set_significand_bit (&u, np2);
+ }
+ }
+ sub_significands (r, x, &u, 0);
+ }
+
+ /* Clear out trailing garbage. */
+ clear_significand_below (r, np2);
+ normalize (r);
+ if (REAL_EXP (r) <= fmt->emin - fmt->p)
+ {
+ get_zero (r, x->sign);
+ return true;
+ }
+ return r->cl == rvc_zero || REAL_EXP (r) < fmt->emin;
+}
+
/* 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. */
+ enough to contain the resulting string. If NORM_MAX, instead write
+ the maximum representable finite normalized floating-point number,
+ defined to be such that all choices of digits for that exponent are
+ representable in the format (this only makes a difference for IBM
+ long double). */
void
-get_max_float (const struct real_format *fmt, char *buf, size_t len)
+get_max_float (const struct real_format *fmt, char *buf, size_t len,
+ bool norm_max)
{
int i, n;
char *p;
+ bool is_ibm_extended = fmt->pnan < fmt->p;
strcpy (buf, "0x0.");
n = fmt->p;
*p++ = 'f';
if (i < n)
*p++ = "08ce"[n - i];
- sprintf (p, "p%d", fmt->emax);
- if (fmt->pnan < fmt->p)
+ sprintf (p, "p%d",
+ (is_ibm_extended && norm_max) ? fmt->emax - 1 : fmt->emax);
+ if (is_ibm_extended && !norm_max)
{
/* This is an IBM extended double format made up of two IEEE
doubles. The value of the long double is the sum of the
gcc_assert (strlen (buf) < len);
}
+/* True if all values of integral type can be represented
+ by this floating-point type exactly. */
+
+bool format_helper::can_represent_integral_type_p (tree type) const
+{
+ gcc_assert (! decimal_p () && INTEGRAL_TYPE_P (type));
+
+ /* INT?_MIN is power-of-two so it takes
+ only one mantissa bit. */
+ bool signed_p = TYPE_SIGN (type) == SIGNED;
+ return TYPE_PRECISION (type) - signed_p <= significand_size (*this);
+}
+
/* True if mode M has a NaN representation and
the treatment of NaN operands is important. */
{
return HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (x));
}
+
+/* Fills r with the largest value such that 1 + r*r won't overflow.
+ This is used in both sin (atan (x)) and cos (atan(x)) optimizations. */
+
+void
+build_sinatan_real (REAL_VALUE_TYPE * r, tree type)
+{
+ REAL_VALUE_TYPE maxval;
+ mpfr_t mpfr_const1, mpfr_c, mpfr_maxval;
+ machine_mode mode = TYPE_MODE (type);
+ const struct real_format * fmt = REAL_MODE_FORMAT (mode);
+
+ real_maxval (&maxval, 0, mode);
+
+ mpfr_inits (mpfr_const1, mpfr_c, mpfr_maxval, NULL);
+
+ mpfr_from_real (mpfr_const1, &dconst1, MPFR_RNDN);
+ mpfr_from_real (mpfr_maxval, &maxval, MPFR_RNDN);
+
+ mpfr_sub (mpfr_c, mpfr_maxval, mpfr_const1, MPFR_RNDN);
+ mpfr_sqrt (mpfr_c, mpfr_c, MPFR_RNDZ);
+
+ real_from_mpfr (r, mpfr_c, fmt, MPFR_RNDZ);
+
+ mpfr_clears (mpfr_const1, mpfr_c, mpfr_maxval, NULL);
+}