diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2002-03-11 11:13:45 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2002-03-11 11:13:45 +0000 |
commit | 3fcaac1d8c04d2966e667e1e4b18959bb94656c9 (patch) | |
tree | b35783a3200c2c8aa44adc916c24401dfe49041e /gcc/real.c | |
parent | d25558bee8343ee30661c00aa2faefd89d60068c (diff) | |
download | gcc-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.c | 75 |
1 files changed, 61 insertions, 14 deletions
@@ -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 |