From 3fcaac1d8c04d2966e667e1e4b18959bb94656c9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 11 Mar 2002 11:13:45 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 23 ++++++++++++++++ gcc/config/fp-bit.c | 69 +++++++++++++++++++++++++++++++++--------------- gcc/defaults.h | 26 ++++++++++++++----- gcc/doc/tm.texi | 40 ++++++++++++++++++++++++++++ gcc/real.c | 75 +++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 192 insertions(+), 41 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a88c373..d01c087 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2002-03-11 Richard Sandiford + + * 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. + 2002-03-11 Andreas Jaeger * cfg.c (dump_flow_info): Remove unused variable. diff --git a/gcc/config/fp-bit.c b/gcc/config/fp-bit.c index 4d39d91..5da7a8e 100644 --- a/gcc/config/fp-bit.c +++ b/gcc/config/fp-bit.c @@ -1,6 +1,6 @@ /* This is a software floating point library which can be used for targets without hardware floating point. - Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001 + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it @@ -181,7 +181,15 @@ pack_d ( fp_number_type * src) int sign = src->sign; int exp = 0; - if (isnan (src)) + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src))) + { + /* We can't represent these values accurately. By using the + largest possible magnitude, we guarantee that the conversion + of infinity is at least as big as any finite number. */ + exp = EXPMAX; + fraction = ((fractype) 1 << FRACBITS) - 1; + } + else if (isnan (src)) { exp = EXPMAX; if (src->class == CLASS_QNAN || 1) @@ -207,6 +215,13 @@ pack_d ( fp_number_type * src) { if (src->normal_exp < NORMAL_EXPMIN) { +#ifdef NO_DENORMALS + /* Go straight to a zero representation if denormals are not + supported. The denormal handling would be harmless but + isn't unnecessary. */ + exp = 0; + fraction = 0; +#else /* NO_DENORMALS */ /* This number's exponent is too low to fit into the bits available in the number, so we'll store 0 in the exponent and shift the fraction to the right to make up for it. */ @@ -242,8 +257,10 @@ pack_d ( fp_number_type * src) exp += 1; } fraction >>= NGARDS; +#endif /* NO_DENORMALS */ } - else if (src->normal_exp > EXPBIAS) + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) + && src->normal_exp > EXPBIAS) { exp = EXPMAX; fraction = 0; @@ -251,25 +268,35 @@ pack_d ( fp_number_type * src) else { exp = src->normal_exp + EXPBIAS; - /* IF the gard bits are the all zero, but the first, then we're - half way between two numbers, choose the one which makes the - lsb of the answer 0. */ - if ((fraction & GARDMASK) == GARDMSB) - { - if (fraction & (1 << NGARDS)) - fraction += GARDROUND + 1; - } - else + if (!ROUND_TOWARDS_ZERO) { - /* Add a one to the guards to round up */ - fraction += GARDROUND; + /* IF the gard bits are the all zero, but the first, then we're + half way between two numbers, choose the one which makes the + lsb of the answer 0. */ + if ((fraction & GARDMASK) == GARDMSB) + { + if (fraction & (1 << NGARDS)) + fraction += GARDROUND + 1; + } + else + { + /* Add a one to the guards to round up */ + fraction += GARDROUND; + } + if (fraction >= IMPLICIT_2) + { + fraction >>= 1; + exp += 1; + } } - if (fraction >= IMPLICIT_2) + fraction >>= NGARDS; + + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX) { - fraction >>= 1; - exp += 1; + /* Saturate on overflow. */ + exp = EXPMAX; + fraction = ((fractype) 1 << FRACBITS) - 1; } - fraction >>= NGARDS; } } @@ -359,7 +386,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst) dst->fraction.ll = fraction; } } - else if (exp == EXPMAX) + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX) { /* Huge exponent*/ if (fraction == 0) @@ -729,7 +756,7 @@ _fpmul_parts ( fp_number_type * a, } } #endif - if ((high & GARDMASK) == GARDMSB) + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB) { if (high & (1 << NGARDS)) { @@ -839,7 +866,7 @@ _fpdiv_parts (fp_number_type * a, numerator *= 2; } - if ((quotient & GARDMASK) == GARDMSB) + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB) { if (quotient & (1 << NGARDS)) { diff --git a/gcc/defaults.h b/gcc/defaults.h index 5142ee7..ffec32c 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -465,14 +465,26 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE! #define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS #endif +#ifndef LARGEST_EXPONENT_IS_NORMAL +#define LARGEST_EXPONENT_IS_NORMAL(SIZE) 0 +#endif + +#ifndef ROUND_TOWARDS_ZERO +#define ROUND_TOWARDS_ZERO 0 +#endif + #ifndef MODE_HAS_NANS -#define MODE_HAS_NANS(MODE) \ - (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) +#define MODE_HAS_NANS(MODE) \ + (FLOAT_MODE_P (MODE) \ + && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \ + && !LARGEST_EXPONENT_IS_NORMAL (GET_MODE_BITSIZE (MODE))) #endif #ifndef MODE_HAS_INFINITIES -#define MODE_HAS_INFINITIES(MODE) \ - (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) +#define MODE_HAS_INFINITIES(MODE) \ + (FLOAT_MODE_P (MODE) \ + && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \ + && !LARGEST_EXPONENT_IS_NORMAL (GET_MODE_BITSIZE (MODE))) #endif #ifndef MODE_HAS_SIGNED_ZEROS @@ -481,8 +493,10 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE! #endif #ifndef MODE_HAS_SIGN_DEPENDENT_ROUNDING -#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \ - (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT) +#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \ + (FLOAT_MODE_P (MODE) \ + && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \ + && !ROUND_TOWARDS_ZERO) #endif #endif /* ! GCC_DEFAULTS_H */ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 344c711..ad7917e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1385,6 +1385,46 @@ towards @minus{}infinity and towards +infinity. The default definition of this macro is true if @var{mode} is a floating-point mode and the target format is IEEE@. + +@findex ROUND_TOWARDS_ZERO +@item ROUND_TOWARDS_ZERO +If defined, this macro should be true if the prevailing rounding +mode is towards zero. A true value has the following effects: + +@itemize @bullet +@item +@code{MODE_HAS_SIGN_DEPENDENT_ROUNDING} will be false for all modes. + +@item +@file{libgcc.a}'s floating-point emulator will round towards zero +rather than towards nearest. + +@item +The compiler's floating-point emulator will round towards zero after +doing arithmetic, and when converting from the internal float format to +the target format. +@end itemize + +The macro does not affect the parsing of string literals. When the +primary rounding mode is towards zero, library functions like +@code{strtod} might still round towards nearest, and the compiler's +parser should behave like the target's @code{strtod} where possible. + +Not defining this macro is equivalent to returning zero. + +@findex LARGEST_EXPONENT_IS_NORMAL +@item LARGEST_EXPONENT_IS_NORMAL (@var{size}) +This macro should only be defined when the target float format is +described as IEEE@. It should return true if floats with @var{size} +bits do not have a NaN or infinity representation, but use the largest +exponent for normal numbers instead. + +Defining this macro to true for @var{size} causes @code{MODE_HAS_NANS} +and @code{MODE_HAS_INFINITIES} to be false for @var{size}-bit modes. +It also affects the way @file{libgcc.a} and @file{real.c} emulate +floating-point arithmetic. + +The default definition of this macro returns false for all sizes. @end table @deftypefn {Target Hook} bool TARGET_MS_BITFIELD_LAYOUT_P (tree @var{record_type}) 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 -- 2.7.4