/* real.c - software floating point emulation.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 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>
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Swap the arguments such that A has the larger exponent. */
r->cl = rvc_normal;
r->sign = sign;
SET_REAL_EXP (r, exp);
+ /* Zero out the remaining fields. */
+ r->signalling = 0;
+ r->canonical = 0;
/* Re-normalize the result. */
normalize (r);
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (r == a || r == b)
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (r == a || r == b)
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (a->sign != b->sign)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
/* Perform the binary or unary operation described by CODE.
- For a unary operation, leave OP1 NULL. */
+ For a unary operation, leave OP1 NULL. This function returns
+ true if the result may be inexact due to loss of precision. */
-void
+bool
real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
const REAL_VALUE_TYPE *op1)
{
switch (code)
{
case PLUS_EXPR:
- do_add (r, op0, op1, 0);
- break;
+ return do_add (r, op0, op1, 0);
case MINUS_EXPR:
- do_add (r, op0, op1, 1);
- break;
+ return do_add (r, op0, op1, 1);
case MULT_EXPR:
- do_multiply (r, op0, op1);
- break;
+ return do_multiply (r, op0, op1);
case RDIV_EXPR:
- do_divide (r, op0, op1);
- break;
+ return do_divide (r, op0, op1);
case MIN_EXPR:
if (op1->cl == rvc_nan)
break;
default:
- abort ();
+ gcc_unreachable ();
}
+ return false;
}
/* Legacy. Similar, but return the result directly. */
return do_compare (op0, op1, 0) != 0;
default:
- abort ();
+ gcc_unreachable ();
}
}
case rvc_normal:
return REAL_EXP (r);
default:
- abort ();
+ gcc_unreachable ();
}
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
for (i = 0; i < SIGSZ; ++i)
if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
i = r->sig[SIGSZ-1];
- else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
+ 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];
}
- else
- abort ();
i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r);
return i;
default:
- abort ();
+ gcc_unreachable ();
}
}
high = t.sig[SIGSZ-1];
low = t.sig[SIGSZ-2];
}
- else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
+ 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 = low << (HOST_BITS_PER_LONG - 1) << 1;
low |= t.sig[SIGSZ-4];
}
- else
- abort ();
if (r->sign)
{
break;
default:
- abort ();
+ gcc_unreachable ();
}
*plow = low;
strcpy (str, (r.sign ? "-NaN" : "+NaN"));
return;
default:
- abort ();
+ gcc_unreachable ();
}
/* Bound the number of digits printed by the size of the representation. */
/* Bound the number of digits printed by the size of the output buffer. */
max_digits = buf_size - 1 - 1 - 2 - max_digits - 1;
- if (max_digits > buf_size)
- abort ();
+ gcc_assert (max_digits <= buf_size);
if (digits > max_digits)
digits = max_digits;
do_multiply (&r, &r, ten);
digit = rtd_divmod (&r, &pten);
dec_exp -= 1;
- if (digit == 0)
- abort ();
+ gcc_assert (digit != 0);
}
/* ... or overflow. */
*p++ = '0';
dec_exp += 1;
}
- else if (digit > 10)
- abort ();
else
- *p++ = digit + '0';
+ {
+ gcc_assert (digit <= 10);
+ *p++ = digit + '0';
+ }
/* Generate subsequent digits. */
while (--digits > 0)
strcpy (str, (r->sign ? "-NaN" : "+NaN"));
return;
default:
- abort ();
+ gcc_unreachable ();
}
if (digits == 0)
sprintf (exp_buf, "p%+d", exp);
max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1;
- if (max_digits > buf_size)
- abort ();
+ gcc_assert (max_digits <= buf_size);
if (digits > max_digits)
digits = max_digits;
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);
{
r->sig[SIGSZ-1] = high;
r->sig[SIGSZ-2] = low;
- memset (r->sig, 0, sizeof(long)*(SIGSZ-2));
}
- else if (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT)
+ 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;
- if (SIGSZ > 4)
- memset (r->sig, 0, sizeof(long)*(SIGSZ-4));
}
- else
- abort ();
normalize (r);
}
{
static REAL_VALUE_TYPE tens[EXP_BITS];
- if (n < 0 || n >= EXP_BITS)
- abort ();
+ gcc_assert (n >= 0);
+ gcc_assert (n < EXP_BITS);
if (tens[n].cl == rvc_zero)
{
{
static REAL_VALUE_TYPE tens[EXP_BITS];
- if (n < 0 || n >= EXP_BITS)
- abort ();
+ 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));
{
static REAL_VALUE_TYPE num[10];
- if (n < 0 || n > 9)
- abort ();
+ 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);
const struct real_format *fmt;
fmt = REAL_MODE_FORMAT (mode);
- if (fmt == NULL)
- abort ();
+ gcc_assert (fmt);
if (*str == 0)
{
else
{
int base = 10, d;
- bool neg = false;
memset (r, 0, sizeof (*r));
r->cl = rvc_nan;
while (ISSPACE (*str))
str++;
if (*str == '-')
- str++, neg = true;
+ str++;
else if (*str == '+')
str++;
if (*str == '0')
add_significands (r, r, &u);
break;
default:
- abort ();
+ gcc_unreachable ();
}
get_zero (&u, 0);
int np2;
fmt = REAL_MODE_FORMAT (mode);
- if (fmt == NULL)
- abort ();
+ gcc_assert (fmt);
r->cl = rvc_normal;
r->sign = sign;
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* If we're not base2, normalize the exponent to a multiple of
const struct real_format *fmt;
fmt = REAL_MODE_FORMAT (mode);
- if (fmt == NULL)
- abort ();
+ gcc_assert (fmt);
*r = *a;
round_for_format (fmt, r);
const struct real_format *fmt;
fmt = REAL_MODE_FORMAT (mode);
- if (fmt == NULL)
- abort ();
+ gcc_assert (fmt);
return real_to_target_fmt (buf, r, fmt);
}
const struct real_format *fmt;
fmt = REAL_MODE_FORMAT (mode);
- if (fmt == NULL)
- abort ();
+ gcc_assert (fmt);
(*fmt->decode) (fmt, r, buf);
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (sizeof(unsigned long) > sizeof(unsigned int))
break;
default:
- abort ();
+ gcc_unreachable ();
}
buf[0] = image;
-125,
128,
31,
+ 31,
true,
true,
true,
-125,
128,
31,
+ 31,
true,
true,
true,
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (FLOAT_WORDS_BIG_ENDIAN)
-1021,
1024,
63,
+ 63,
true,
true,
true,
-1021,
1024,
63,
+ 63,
true,
true,
true,
else
{
exp += 16383 - 1;
- if (exp < 0)
- abort ();
+ gcc_assert (exp >= 0);
}
image_hi |= exp;
break;
default:
- abort ();
+ gcc_unreachable ();
}
buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
-16382,
16384,
95,
+ 95,
true,
true,
true,
-16381,
16384,
79,
+ 79,
true,
true,
true,
-16381,
16384,
79,
+ 79,
true,
true,
true,
-16381,
16384,
79,
+ 79,
true,
true,
true,
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
- ignored. Zeroes, Infinities, and NaNs are set in both doubles
- due to precedent. */
+ +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 *);
53,
-1021 + 53,
1024,
+ 127,
-1,
true,
true,
53,
-1021 + 53,
1024,
+ 127,
-1,
true,
true,
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (FLOAT_WORDS_BIG_ENDIAN)
-16381,
16384,
127,
+ 127,
true,
true,
true,
-16381,
16384,
127,
+ 127,
true,
true,
true,
break;
default:
- abort ();
+ gcc_unreachable ();
}
buf[0] = image;
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (FLOAT_WORDS_BIG_ENDIAN)
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (FLOAT_WORDS_BIG_ENDIAN)
-127,
127,
15,
+ 15,
false,
false,
false,
-127,
127,
15,
+ 15,
false,
false,
false,
-1023,
1023,
15,
+ 15,
false,
false,
false,
break;
default:
- abort ();
+ gcc_unreachable ();
}
buf[0] = image;
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (FLOAT_WORDS_BIG_ENDIAN)
-64,
63,
31,
+ 31,
false,
false,
false, /* ??? The encoding does allow for "unnormals". */
-64,
63,
63,
+ 63,
false,
false,
false, /* ??? The encoding does allow for "unnormals". */
break;
default:
- abort ();
+ gcc_unreachable ();
}
image = ((exp & 0xff) << 24) | (sig & 0xffffff);
break;
default:
- abort ();
+ gcc_unreachable ();
}
exp = (exp & 0xff) << 24;
24,
-126,
128,
+ 23,
-1,
false,
false,
32,
-126,
128,
+ 31,
-1,
false,
false,
-MAX_EXP,
MAX_EXP,
-1,
+ -1,
true,
true,
false,
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
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