Commit 29e11dab by Richard Kenner

(earith, ereal_negate, eneg, eisneg, enan, emovo, esub, eadd, ediv):

Propagate the sign of NaNs, so that e.g. -(NaN) evaluates to -NaN.
(emul, eremain, e53toe, e64toe, e113toe, e24toe, esqrt): Likewise.
(make_nan): New arg specifies sign of NaN.  All callers changed.
(eiisneg): New function.
(esqrt): Compute sqrt(-0.0) to be -0.0, not 0.0.

From-SVN: r6511
parent b9b63425
/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF, /* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
and support for XFmode IEEE extended real floating point arithmetic. and support for XFmode IEEE extended real floating point arithmetic.
Contributed by Stephen L. Moshier (moshier@world.std.com). Contributed by Stephen L. Moshier (moshier@world.std.com).
Copyright (C) 1993 Free Software Foundation, Inc. Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC. This file is part of GNU CC.
...@@ -322,7 +322,7 @@ do { EMUSHORT w[4]; \ ...@@ -322,7 +322,7 @@ do { EMUSHORT w[4]; \
void warning (); void warning ();
extern int extra_warnings; extern int extra_warnings;
int ecmp (), enormlz (), eshift (); int ecmp (), enormlz (), eshift ();
int eisneg (), eisinf (), eisnan (), eiisinf (), eiisnan (); int eisneg (), eisinf (), eisnan (), eiisinf (), eiisnan (), eiisneg ();
void eadd (), esub (), emul (), ediv (); void eadd (), esub (), emul (), ediv ();
void eshup1 (), eshup8 (), eshup6 (), eshdn1 (), eshdn8 (), eshdn6 (); void eshup1 (), eshup8 (), eshup6 (), eshdn1 (), eshdn8 (), eshdn6 ();
void eabs (), eneg (), emov (), eclear (), einfin (), efloor (); void eabs (), eneg (), emov (), eclear (), einfin (), efloor ();
...@@ -490,7 +490,7 @@ earith (value, icode, r1, r2) ...@@ -490,7 +490,7 @@ earith (value, icode, r1, r2)
if (ecmp (d2, ezero) == 0) if (ecmp (d2, ezero) == 0)
{ {
#ifdef NANS #ifdef NANS
enan (v); enan (v, eisneg (d1) ^ eisneg (d2));
break; break;
#else #else
abort (); abort ();
...@@ -616,10 +616,6 @@ ereal_negate (x) ...@@ -616,10 +616,6 @@ ereal_negate (x)
REAL_VALUE_TYPE r; REAL_VALUE_TYPE r;
GET_REAL (&x, e); GET_REAL (&x, e);
#ifdef NANS
if (eisnan (e))
return (x);
#endif
eneg (e); eneg (e);
PUT_REAL (e, &r); PUT_REAL (e, &r);
return (r); return (r);
...@@ -1096,6 +1092,7 @@ ereal_isneg (x) ...@@ -1096,6 +1092,7 @@ ereal_isneg (x)
* esubm (ai, bi) subtract significands, bi = bi - ai * esubm (ai, bi) subtract significands, bi = bi - ai
* eiisinf (ai) 1 if infinite * eiisinf (ai) 1 if infinite
* eiisnan (ai) 1 if a NaN * eiisnan (ai) 1 if a NaN
* eiisneg (ai) 1 if sign bit of ai != 0, else 0
* einan (ai) set ai = NaN * einan (ai) set ai = NaN
* eiinfin (ai) set ai = infinity * eiinfin (ai) set ai = infinity
* *
...@@ -1349,27 +1346,19 @@ eneg (x) ...@@ -1349,27 +1346,19 @@ eneg (x)
unsigned EMUSHORT x[]; unsigned EMUSHORT x[];
{ {
#ifdef NANS
if (eisnan (x))
return;
#endif
x[NE - 1] ^= 0x8000; /* Toggle the sign bit */ x[NE - 1] ^= 0x8000; /* Toggle the sign bit */
} }
/* Return 1 if external format number is negative, /* Return 1 if sign bit of external format number is nonzero,
* else return zero, including when it is a NaN. * else return zero.
*/ */
int int
eisneg (x) eisneg (x)
unsigned EMUSHORT x[]; unsigned EMUSHORT x[];
{ {
#ifdef NANS
if (eisnan (x))
return (0);
#endif
if (x[NE - 1] & 0x8000) if (x[NE - 1] & 0x8000)
return (1); return (1);
else else
...@@ -1468,15 +1457,16 @@ einfin (x) ...@@ -1468,15 +1457,16 @@ einfin (x)
The exponent is 7fff, the leading mantissa word is c000. */ The exponent is 7fff, the leading mantissa word is c000. */
void void
enan (x) enan (x, sign)
register unsigned EMUSHORT *x; register unsigned EMUSHORT *x;
int sign;
{ {
register int i; register int i;
for (i = 0; i < NE - 2; i++) for (i = 0; i < NE - 2; i++)
*x++ = 0; *x++ = 0;
*x++ = 0xc000; *x++ = 0xc000;
*x = 0x7fff; *x = (sign << 15) | 0x7fff;
} }
...@@ -1552,7 +1542,7 @@ emovo (a, b) ...@@ -1552,7 +1542,7 @@ emovo (a, b)
#ifdef NANS #ifdef NANS
if (eiisnan (a)) if (eiisnan (a))
{ {
enan (b); enan (b, eiisneg (a));
return; return;
} }
#endif #endif
...@@ -1646,6 +1636,16 @@ eiisnan (x) ...@@ -1646,6 +1636,16 @@ eiisnan (x)
return (0); return (0);
} }
/* Return nonzero if sign of internal format number is nonzero. */
int
eiisneg (x)
unsigned EMUSHORT x[];
{
return x[0] != 0;
}
/* Fill internal format number with infinity pattern. /* Fill internal format number with infinity pattern.
This has maximum exponent and significand all zeros. */ This has maximum exponent and significand all zeros. */
...@@ -2484,7 +2484,7 @@ esub (a, b, c) ...@@ -2484,7 +2484,7 @@ esub (a, b, c)
&& ((eisneg (a) ^ eisneg (b)) == 0)) && ((eisneg (a) ^ eisneg (b)) == 0))
{ {
mtherr ("esub", INVALID); mtherr ("esub", INVALID);
enan (c); enan (c, 0);
return; return;
} }
#endif #endif
...@@ -2522,7 +2522,7 @@ eadd (a, b, c) ...@@ -2522,7 +2522,7 @@ eadd (a, b, c)
&& ((eisneg (a) ^ eisneg (b)) != 0)) && ((eisneg (a) ^ eisneg (b)) != 0))
{ {
mtherr ("esub", INVALID); mtherr ("esub", INVALID);
enan (c); enan (c, 0);
return; return;
} }
#endif #endif
...@@ -2665,7 +2665,7 @@ ediv (a, b, c) ...@@ -2665,7 +2665,7 @@ ediv (a, b, c)
|| (eisinf (a) && eisinf (b))) || (eisinf (a) && eisinf (b)))
{ {
mtherr ("ediv", INVALID); mtherr ("ediv", INVALID);
enan (c); enan (c, eisneg (a) ^ eisneg (b));
return; return;
} }
#endif #endif
...@@ -2773,7 +2773,7 @@ emul (a, b, c) ...@@ -2773,7 +2773,7 @@ emul (a, b, c)
|| (eisinf (b) && (ecmp (a, ezero) == 0))) || (eisinf (b) && (ecmp (a, ezero) == 0)))
{ {
mtherr ("emul", INVALID); mtherr ("emul", INVALID);
enan (c); enan (c, eisneg (a) ^ eisneg (b));
return; return;
} }
#endif #endif
...@@ -2884,14 +2884,14 @@ e53toe (pe, y) ...@@ -2884,14 +2884,14 @@ e53toe (pe, y)
if (((pe[3] & 0xf) != 0) || (pe[2] != 0) if (((pe[3] & 0xf) != 0) || (pe[2] != 0)
|| (pe[1] != 0) || (pe[0] != 0)) || (pe[1] != 0) || (pe[0] != 0))
{ {
enan (y); enan (y, yy[0] != 0);
return; return;
} }
#else #else
if (((pe[0] & 0xf) != 0) || (pe[1] != 0) if (((pe[0] & 0xf) != 0) || (pe[1] != 0)
|| (pe[2] != 0) || (pe[3] != 0)) || (pe[2] != 0) || (pe[3] != 0))
{ {
enan (y); enan (y, yy[0] != 0);
return; return;
} }
#endif #endif
...@@ -2984,7 +2984,7 @@ e64toe (pe, y) ...@@ -2984,7 +2984,7 @@ e64toe (pe, y)
{ {
if (pe[i] != 0) if (pe[i] != 0)
{ {
enan (y); enan (y, (*p & 0x8000) != 0);
return; return;
} }
} }
...@@ -2993,7 +2993,7 @@ e64toe (pe, y) ...@@ -2993,7 +2993,7 @@ e64toe (pe, y)
{ {
if (pe[i] != 0) if (pe[i] != 0)
{ {
enan (y); enan (y, (*p & 0x8000) != 0);
return; return;
} }
} }
...@@ -3040,7 +3040,7 @@ e113toe (pe, y) ...@@ -3040,7 +3040,7 @@ e113toe (pe, y)
{ {
if (pe[i] != 0) if (pe[i] != 0)
{ {
enan (y); enan (y, yy[0] != 0);
return; return;
} }
} }
...@@ -3049,7 +3049,7 @@ e113toe (pe, y) ...@@ -3049,7 +3049,7 @@ e113toe (pe, y)
{ {
if (pe[i] != 0) if (pe[i] != 0)
{ {
enan (y); enan (y, yy[0] != 0);
return; return;
} }
} }
...@@ -3129,13 +3129,13 @@ e24toe (pe, y) ...@@ -3129,13 +3129,13 @@ e24toe (pe, y)
#ifdef MIEEE #ifdef MIEEE
if (((pe[0] & 0x7f) != 0) || (pe[1] != 0)) if (((pe[0] & 0x7f) != 0) || (pe[1] != 0))
{ {
enan (y); enan (y, yy[0] != 0);
return; return;
} }
#else #else
if (((pe[1] & 0x7f) != 0) || (pe[0] != 0)) if (((pe[1] & 0x7f) != 0) || (pe[0] != 0))
{ {
enan (y); enan (y, yy[0] != 0);
return; return;
} }
#endif #endif
...@@ -3192,7 +3192,7 @@ etoe113 (x, e) ...@@ -3192,7 +3192,7 @@ etoe113 (x, e)
#ifdef NANS #ifdef NANS
if (eisnan (x)) if (eisnan (x))
{ {
make_nan (e, TFmode); make_nan (e, eisneg (x), TFmode);
return; return;
} }
#endif #endif
...@@ -3222,7 +3222,7 @@ toe113 (a, b) ...@@ -3222,7 +3222,7 @@ toe113 (a, b)
#ifdef NANS #ifdef NANS
if (eiisnan (a)) if (eiisnan (a))
{ {
make_nan (b, TFmode); make_nan (b, eiisneg (a), TFmode);
return; return;
} }
#endif #endif
...@@ -3274,7 +3274,7 @@ etoe64 (x, e) ...@@ -3274,7 +3274,7 @@ etoe64 (x, e)
#ifdef NANS #ifdef NANS
if (eisnan (x)) if (eisnan (x))
{ {
make_nan (e, XFmode); make_nan (e, eisneg (x), XFmode);
return; return;
} }
#endif #endif
...@@ -3305,7 +3305,7 @@ toe64 (a, b) ...@@ -3305,7 +3305,7 @@ toe64 (a, b)
#ifdef NANS #ifdef NANS
if (eiisnan (a)) if (eiisnan (a))
{ {
make_nan (b, XFmode); make_nan (b, eiisneg (a), XFmode);
return; return;
} }
#endif #endif
...@@ -3400,7 +3400,7 @@ etoe53 (x, e) ...@@ -3400,7 +3400,7 @@ etoe53 (x, e)
#ifdef NANS #ifdef NANS
if (eisnan (x)) if (eisnan (x))
{ {
make_nan (e, DFmode); make_nan (e, eisneg (x), DFmode);
return; return;
} }
#endif #endif
...@@ -3431,7 +3431,7 @@ toe53 (x, y) ...@@ -3431,7 +3431,7 @@ toe53 (x, y)
#ifdef NANS #ifdef NANS
if (eiisnan (x)) if (eiisnan (x))
{ {
make_nan (y, DFmode); make_nan (y, eiisneg (x), DFmode);
return; return;
} }
#endif #endif
...@@ -3539,7 +3539,7 @@ etoe24 (x, e) ...@@ -3539,7 +3539,7 @@ etoe24 (x, e)
#ifdef NANS #ifdef NANS
if (eisnan (x)) if (eisnan (x))
{ {
make_nan (e, SFmode); make_nan (e, eisneg (x), SFmode);
return; return;
} }
#endif #endif
...@@ -3569,7 +3569,7 @@ toe24 (x, y) ...@@ -3569,7 +3569,7 @@ toe24 (x, y)
#ifdef NANS #ifdef NANS
if (eiisnan (x)) if (eiisnan (x))
{ {
make_nan (y, SFmode); make_nan (y, eiisneg (x), SFmode);
return; return;
} }
#endif #endif
...@@ -5117,7 +5117,7 @@ eremain (a, b, c) ...@@ -5117,7 +5117,7 @@ eremain (a, b, c)
|| eisnan (a) || eisnan (a)
|| eisnan (b)) || eisnan (b))
{ {
enan (c); enan (c, 0);
return; return;
} }
#endif #endif
...@@ -5582,14 +5582,14 @@ unsigned EMUSHORT SFnan[2] = {0, 0xffc0}; ...@@ -5582,14 +5582,14 @@ unsigned EMUSHORT SFnan[2] = {0, 0xffc0};
void void
make_nan (nan, mode) make_nan (nan, sign, mode)
unsigned EMUSHORT *nan; unsigned EMUSHORT *nan;
int sign;
enum machine_mode mode; enum machine_mode mode;
{ {
int i, n; int n;
unsigned EMUSHORT *p; unsigned EMUSHORT *p;
n = 0;
switch (mode) switch (mode)
{ {
/* Possibly the `reserved operand' patterns on a VAX can be /* Possibly the `reserved operand' patterns on a VAX can be
...@@ -5615,8 +5615,14 @@ enum machine_mode mode; ...@@ -5615,8 +5615,14 @@ enum machine_mode mode;
default: default:
abort (); abort ();
} }
for (i=0; i < n; i++) #ifdef MIEEE
*nan++ = (sign << 15) | *p++;
#endif
while (--n != 0)
*nan++ = *p++; *nan++ = *p++;
#ifndef MIEEE
*nan = (sign << 15) | *p;
#endif
} }
/* Convert an SFmode target `float' value to a REAL_VALUE_TYPE. /* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
...@@ -5961,16 +5967,13 @@ esqrt (x, y) ...@@ -5961,16 +5967,13 @@ esqrt (x, y)
i = ecmp (x, ezero); i = ecmp (x, ezero);
if (i <= 0) if (i <= 0)
{ {
#ifdef NANS if (i == -1)
if (i == -2)
{ {
enan (y);
return;
}
#endif
eclear (y);
if (i < 0)
mtherr ("esqrt", DOMAIN); mtherr ("esqrt", DOMAIN);
eclear (y);
}
else
emov (x, y);
return; return;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment