defaults.h (LARGEST_EXPONENT_IS_NORMAL, [...]): New.
authorRichard Sandiford <rsandifo@redhat.com>
Mon, 11 Mar 2002 11:13:45 +0000 (11:13 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 11 Mar 2002 11:13:45 +0000 (11:13 +0000)
* 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
gcc/config/fp-bit.c
gcc/defaults.h
gcc/doc/tm.texi
gcc/real.c

index a88c373939846c6149cf5577d8c7a0dab69aabfd..d01c087820872b9491704b9059e0acc8284b3757 100644 (file)
@@ -1,3 +1,26 @@
+2002-03-11  Richard Sandiford  <rsandifo@redhat.com>
+
+       * 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  <aj@suse.de>
 
        * cfg.c (dump_flow_info): Remove unused variable.
index 4d39d91287699c292380a4f8af5ac802fdcf1e1d..5da7a8efe13884839f39fa7cfba028507dda67a6 100644 (file)
@@ -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))
          {
index 5142ee7b471017e3b65457e99d2b8969f74a5904..ffec32c626665be9757e8481948dc086c82cd23d 100644 (file)
@@ -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 */
index 344c711f57caa5f0bd085d7afc3a001f1bd045e5..ad7917eca4b910da8e1a9248ab26e4c572cbb739 100644 (file)
@@ -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})
index 559cb058cc7effea1bd33ec0e810a29c91d16056..0d3e657ce9cc6d91b721dfde34666fd0b60dffe1 100644 (file)
@@ -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