aboutsummaryrefslogtreecommitdiff
path: root/gcc/real.c
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@redhat.com>2002-03-11 11:13:45 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2002-03-11 11:13:45 +0000
commit3fcaac1d8c04d2966e667e1e4b18959bb94656c9 (patch)
treeb35783a3200c2c8aa44adc916c24401dfe49041e /gcc/real.c
parentd25558bee8343ee30661c00aa2faefd89d60068c (diff)
downloadgcc-3fcaac1d8c04d2966e667e1e4b18959bb94656c9.zip
gcc-3fcaac1d8c04d2966e667e1e4b18959bb94656c9.tar.gz
gcc-3fcaac1d8c04d2966e667e1e4b18959bb94656c9.tar.bz2
defaults.h (LARGEST_EXPONENT_IS_NORMAL, [...]): New.
* defaults.h (LARGEST_EXPONENT_IS_NORMAL, ROUND_TOWARDS_ZERO): New. (MODE_HAS_NANS, MODE_HAS_INFINITIES): Evaluate to false if LARGEST_EXPONENT_IS_NORMAL for the given mode. (MODE_HAS_SIGN_DEPENDENT_ROUNDING): False when ROUND_TOWARDS_ZERO. * real.c (eadd1): Make rounding dependent on !ROUND_TOWARDS_ZERO. (ediv, emul, eldexp, esqrt): Likewise. (etoe113, etoe64, etoe53, etoe24, etodec, etoibm, etoc4x): Likewise. (e24toe): Only check NaNs & infinities if !LARGEST_EXPONENT_IS_NORMAL. (saturate): New function. (toe53, toe24): Saturate on overflow if LARGEST_EXPONENT_IS_NORMAL. (make_nan): Use a saturation value instead of a NaN if LARGEST_EXPONENT_IS_NORMAL. Warn when this happens. * fp-bit.c (pack_d): Saturate on NaN, infinite or overflowing inputs if LARGEST_EXPONENT_IS_NORMAL. Represent subnormals as zero if NO_DENORMALS. Only round to nearest if !ROUND_TOWARDS_ZERO. (unpack_d): No NaNs or infinities if LARGEST_EXPONENT_IS_NORMAL. (_fpmul_parts, _fpdiv_parts): Only round to nearest if !ROUND_TOWARDS_ZERO. * doc/tm.texi (LARGEST_EXPONENT_IS_NORMAL): Document. (ROUND_TOWARDS_ZERO): Document. From-SVN: r50569
Diffstat (limited to 'gcc/real.c')
-rw-r--r--gcc/real.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/gcc/real.c b/gcc/real.c
index 559cb05..0d3e657 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -336,6 +336,7 @@ static int eiisnan PARAMS ((const UEMUSHORT *));
static int eiisneg PARAMS ((const UEMUSHORT *));
static void make_nan PARAMS ((UEMUSHORT *, int, enum machine_mode));
#endif
+static void saturate PARAMS ((UEMUSHORT *, int, int, int));
static void emovi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
static void emovo PARAMS ((const UEMUSHORT *, UEMUSHORT *));
static void ecleaz PARAMS ((UEMUSHORT *));
@@ -2871,7 +2872,7 @@ eadd1 (a, b, c)
esubm (ai, bi);
subflg = 1;
}
- emdnorm (bi, lost, subflg, ltb, 64);
+ emdnorm (bi, lost, subflg, ltb, !ROUND_TOWARDS_ZERO);
done:
emovo (bi, c);
@@ -2967,7 +2968,7 @@ ediv (a, b, c)
i = edivm (ai, bi);
/* calculate exponent */
lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
+ emdnorm (bi, i, 0, lt, !ROUND_TOWARDS_ZERO);
emovo (bi, c);
divsign:
@@ -3064,7 +3065,7 @@ emul (a, b, c)
j = emulm (ai, bi);
/* calculate exponent */
lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
+ emdnorm (bi, j, 0, lt, !ROUND_TOWARDS_ZERO);
emovo (bi, c);
mulsign:
@@ -3445,7 +3446,7 @@ e24toe (pe, y)
yy[M] = (r & 0x7f) | 0200;
r &= ~0x807f; /* strip sign and 7 significand bits */
#ifdef INFINITY
- if (r == 0x7f80)
+ if (!LARGEST_EXPONENT_IS_NORMAL (32) && r == 0x7f80)
{
#ifdef NANS
if (REAL_WORDS_BIG_ENDIAN)
@@ -3536,7 +3537,7 @@ etoe113 (x, e)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 113;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
@@ -3632,7 +3633,7 @@ etoe64 (x, e)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 64;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
@@ -3852,7 +3853,7 @@ etoe53 (x, e)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 53;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
@@ -3877,6 +3878,11 @@ toe53 (x, y)
return;
}
#endif
+ if (LARGEST_EXPONENT_IS_NORMAL (64) && x[1] > 2047)
+ {
+ saturate (y, eiisneg (x), 64, 1);
+ return;
+ }
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
@@ -4031,7 +4037,7 @@ etoe24 (x, e)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 24;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
#ifdef INFINITY
nonorm:
@@ -4056,6 +4062,11 @@ toe24 (x, y)
return;
}
#endif
+ if (LARGEST_EXPONENT_IS_NORMAL (32) && x[1] > 255)
+ {
+ saturate (y, eiisneg (x), 32, 1);
+ return;
+ }
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
@@ -4070,7 +4081,7 @@ toe24 (x, y)
i = *p++;
/* Handle overflow cases. */
- if (i >= 255)
+ if (!LARGEST_EXPONENT_IS_NORMAL (32) && i >= 255)
{
#ifdef INFINITY
*y |= (UEMUSHORT) 0x7f80;
@@ -5628,7 +5639,7 @@ eldexp (x, pwr2, y)
li = xi[1];
li += pwr2;
i = 0;
- emdnorm (xi, i, i, li, 64);
+ emdnorm (xi, i, i, li, !ROUND_TOWARDS_ZERO);
emovo (xi, y);
}
@@ -5826,7 +5837,7 @@ etodec (x, d)
/* Round off to nearest or even. */
rndsav = rndprc;
rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
todec (xi, d);
}
@@ -5938,7 +5949,7 @@ etoibm (x, d, mode)
/* round off to nearest or even */
rndsav = rndprc;
rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
toibm (xi, d, mode);
}
@@ -6136,7 +6147,7 @@ etoc4x (x, d, mode)
/* Round off to nearest or even. */
rndsav = rndprc;
rndprc = mode == QFmode ? 24 : 32;
- emdnorm (xi, 0, 0, exp, 64);
+ emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
rndprc = rndsav;
toc4x (xi, d, mode);
}
@@ -6298,7 +6309,15 @@ make_nan (nan, sign, mode)
{
int n;
const UEMUSHORT *p;
+ int size;
+ size = GET_MODE_BITSIZE (mode);
+ if (LARGEST_EXPONENT_IS_NORMAL (size))
+ {
+ warning ("%d-bit floats cannot hold NaNs", size);
+ saturate (nan, sign, size, 0);
+ return;
+ }
switch (mode)
{
/* Possibly the `reserved operand' patterns on a VAX can be
@@ -6353,6 +6372,34 @@ make_nan (nan, sign, mode)
}
#endif /* NANS */
+
+/* Create a saturation value for a SIZE-bit float, assuming that
+ LARGEST_EXPONENT_IS_NORMAL (SIZE).
+
+ If SIGN is true, fill X with the most negative value, otherwise fill
+ it with the most positive value. WARN is true if the function should
+ warn about overflow. */
+
+static void
+saturate (x, sign, size, warn)
+ UEMUSHORT *x;
+ int sign, size, warn;
+{
+ int i;
+
+ if (warn && extra_warnings)
+ warning ("value exceeds the range of a %d-bit float", size);
+
+ /* Create the most negative value. */
+ for (i = 0; i < size / EMUSHORT_SIZE; i++)
+ x[i] = 0xffff;
+
+ /* Make it positive, if necessary. */
+ if (!sign)
+ x[REAL_WORDS_BIG_ENDIAN? 0 : i - 1] = 0x7fff;
+}
+
+
/* This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
@@ -6876,7 +6923,7 @@ esqrt (x, y)
k |= (int) num[i];
/* Renormalize and round off. */
- emdnorm (sq, k, 0, exp, 64);
+ emdnorm (sq, k, 0, exp, !ROUND_TOWARDS_ZERO);
emovo (sq, y);
}
#endif