OSDN Git Service

* tree.h: Forward-declare struct realvaluetype.
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 559cb05..456108e 100644 (file)
@@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "real.h"
 #include "tree.h"
 #include "toplev.h"
 #include "tm_p.h"
@@ -165,8 +166,7 @@ unknown arithmetic type
 #define EMUSHORT_SIZE HOST_BITS_PER_LONG
 #define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
 #else
-/*  You will have to modify this program to have a smaller unit size.  */
-#define EMU_NON_COMPILE
+  #error "You will have to modify this program to have a smaller unit size."
 #endif
 #endif
 #endif
@@ -199,92 +199,55 @@ typedef unsigned int UHItype __attribute__ ((mode (HI)));
 #if HOST_BITS_PER_LONGLONG >= EMULONG_SIZE
 #define EMULONG long long int
 #else
-/*  You will have to modify this program to have a smaller unit size.  */
-#define EMU_NON_COMPILE
+  #error "You will have to modify this program to have a smaller unit size."
 #endif
 #endif
 #endif
 #endif
 
-
-/* The host interface doesn't work if no 16-bit size exists.  */
 #if EMUSHORT_SIZE != 16
-#define EMU_NON_COMPILE
+  #error "The host interface doesn't work if no 16-bit size exists."
 #endif
 
-/* OK to continue compilation.  */
-#ifndef EMU_NON_COMPILE
-
-/* Construct macros to translate between REAL_VALUE_TYPE and e type.
-   In GET_REAL and PUT_REAL, r and e are pointers.
-   A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
-   in memory, with no holes.  */
+/* Calculate the size of the generic "e" type.  This always has
+   identical in-memory size to REAL_VALUE_TYPE.  The sizes are supposed
+   to be the same as well, but when REAL_VALUE_TYPE_SIZE is not evenly
+   divisible by HOST_BITS_PER_WIDE_INT we have some padding in
+   REAL_VALUE_TYPE.
+   There are only two supported sizes: ten and six 16-bit words (160
+   or 96 bits).  */
 
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 96 || \
-    ((INTEL_EXTENDED_IEEE_FORMAT != 0) && MAX_LONG_DOUBLE_TYPE_SIZE == 128)
-/* Number of 16 bit words in external e type format */
+#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !INTEL_EXTENDED_IEEE_FORMAT
+/* TFmode */
+# define NE 10
+# define MAXDECEXP 4932
+# define MINDECEXP -4977
+#else
 # define NE 6
 # define MAXDECEXP 4932
 # define MINDECEXP -4956
-# define GET_REAL(r,e)  memcpy ((e), (r), 2*NE)
-# define PUT_REAL(e,r)                                         \
-       do {                                                    \
-         memcpy ((r), (e), 2*NE);                              \
-         if (2*NE < sizeof (*r))                               \
-           memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE);        \
-       } while (0)
-# else /* no XFmode */
-#  if MAX_LONG_DOUBLE_TYPE_SIZE == 128
-#   define NE 10
-#   define MAXDECEXP 4932
-#   define MINDECEXP -4977
-#   define GET_REAL(r,e) memcpy ((e), (r), 2*NE)
-#   define PUT_REAL(e,r)                                       \
-       do {                                                    \
-         memcpy ((r), (e), 2*NE);                              \
-         if (2*NE < sizeof (*r))                               \
-           memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE);        \
-       } while (0)
-#else
-#define NE 6
-#define MAXDECEXP 4932
-#define MINDECEXP -4956
-/* Emulator uses target format internally
-   but host stores it in host endian-ness.  */
-
-#define GET_REAL(r,e)                                                  \
-do {                                                                   \
-     if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN)         \
-       e53toe ((const UEMUSHORT *) (r), (e));                          \
-     else                                                              \
-       {                                                               \
-        UEMUSHORT w[4];                                        \
-         memcpy (&w[3], ((const EMUSHORT *) r), sizeof (EMUSHORT));    \
-         memcpy (&w[2], ((const EMUSHORT *) r) + 1, sizeof (EMUSHORT));        \
-         memcpy (&w[1], ((const EMUSHORT *) r) + 2, sizeof (EMUSHORT));        \
-         memcpy (&w[0], ((const EMUSHORT *) r) + 3, sizeof (EMUSHORT));        \
-        e53toe (w, (e));                                               \
-       }                                                               \
-   } while (0)
-
-#define PUT_REAL(e,r)                                                  \
-do {                                                                   \
-     if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN)         \
-       etoe53 ((e), (UEMUSHORT *) (r));                                \
-     else                                                              \
-       {                                                               \
-        UEMUSHORT w[4];                                        \
-        etoe53 ((e), w);                                               \
-         memcpy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT));          \
-         memcpy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT));      \
-         memcpy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT));      \
-         memcpy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT));      \
-       }                                                               \
-   } while (0)
-
-#endif /* not TFmode */
-#endif /* not XFmode */
+#endif
 
+/* Fail compilation if 2*NE is not the appropriate size.
+   If HOST_BITS_PER_WIDE_INT is 64, we're going to have padding
+   at the end of the array, because neither 96 nor 160 is
+   evenly divisible by 64.  */
+struct compile_test_dummy {
+  char twice_NE_must_equal_sizeof_REAL_VALUE_TYPE
+  [(sizeof (REAL_VALUE_TYPE) >= 2*NE) ? 1 : -1];
+};
+
+/* Construct macros to translate between REAL_VALUE_TYPE and e type.
+   In GET_REAL and PUT_REAL, r and e are pointers.
+   A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
+   in memory, with no holes.  */
+#define GET_REAL(r, e)  memcpy ((e), (r), 2*NE)
+#define PUT_REAL(e, r)                                         \
+  do {                                                         \
+    memcpy (r, e, 2*NE);                                       \
+    if (2*NE < sizeof (*r))                                    \
+      memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE);     \
+  } while (0)
 
 /* Number of 16 bit words in internal format */
 #define NI (NE+3)
@@ -333,9 +296,10 @@ static void einfin PARAMS ((UEMUSHORT *));
 static void enan       PARAMS ((UEMUSHORT *, int));
 static void einan      PARAMS ((UEMUSHORT *));
 static int eiisnan     PARAMS ((const UEMUSHORT *));
-static int eiisneg     PARAMS ((const UEMUSHORT *));
 static void make_nan   PARAMS ((UEMUSHORT *, int, enum machine_mode));
 #endif
+static int eiisneg     PARAMS ((const UEMUSHORT *));
+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 *));
@@ -606,17 +570,10 @@ earith (value, icode, r1, r2)
       break;
 
     case RDIV_EXPR:
-#ifndef REAL_INFINITY
+#ifndef INFINITY
       if (ecmp (d2, ezero) == 0)
-       {
-#ifdef NANS
-       enan (v, eisneg (d1) ^ eisneg (d2));
-       break;
-#else
        abort ();
 #endif
-       }
-#endif
       ediv (d2, d1, v);        /* d1/d2 */
       break;
 
@@ -1110,6 +1067,22 @@ real_value_truncate (mode, arg)
   return (r);
 }
 
+/* Return true if ARG can be represented exactly in MODE.  */
+
+bool
+exact_real_truncate (mode, arg)
+     enum machine_mode mode;
+     REAL_VALUE_TYPE *arg;
+{
+  REAL_VALUE_TYPE trunc;
+
+  if (target_isnan (*arg))
+    return false;
+
+  trunc = real_value_truncate (mode, *arg);
+  return ereal_cmp (*arg, trunc) == 0;
+}
+
 /* Try to change R into its exact multiplicative inverse in machine mode
    MODE.  Return nonzero function value if successful.  */
 
@@ -1645,7 +1618,7 @@ eisnan (x)
   for (i = 0; i < NE - 1; i++)
     {
       if (*x++ != 0)
-        return (1);
+       return (1);
     }
 #endif
 
@@ -1882,7 +1855,6 @@ eiisnan (x)
 
 /* Return nonzero if sign of exploded e-type X is nonzero.  */
 
-#ifdef NANS
 static int
 eiisneg (x)
      const UEMUSHORT x[];
@@ -1890,7 +1862,6 @@ eiisneg (x)
 
   return x[0] != 0;
 }
-#endif /* NANS */
 
 #if 0
 /* Fill exploded e-type X with infinity pattern.
@@ -2871,7 +2842,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 +2938,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 +3035,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 +3416,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 +3507,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 +3603,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 +3823,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 +3848,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 +4007,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 +4032,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 +4051,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;
@@ -4357,13 +4338,13 @@ eifrac (x, i, frac)
        *i = -(*i);
     }
   else
-      {
-        /* shift not more than 16 bits */
-          eshift (xi, k);
-        *i = (HOST_WIDE_INT) xi[M] & 0xffff;
-        if (xi[0])
-         *i = -(*i);
-      }
+    {
+      /* shift not more than 16 bits */
+      eshift (xi, k);
+      *i = (HOST_WIDE_INT) xi[M] & 0xffff;
+      if (xi[0])
+       *i = -(*i);
+    }
   xi[0] = 0;
   xi[E] = EXONE - 1;
   xi[M] = 0;
@@ -5040,12 +5021,9 @@ etoasc (x, string, ndigs)
        }
     }
  doexp:
-  /*
-     if (expon >= 0)
-     sprintf (ss, "e+%d", expon);
-     else
-     sprintf (ss, "e%d", expon);
-     */
+  /* Strip trailing zeros, but leave at least one.  */
+  while (ss[-1] == '0' && ss[-2] != '.')
+    --ss;
   sprintf (ss, "e%d", expon);
  bxit:
   rndprc = rndsav;
@@ -5628,7 +5606,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 +5804,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 +5916,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);
 }
@@ -6060,11 +6038,11 @@ c4xtoe (d, e, mode)
 
       y[M+1] = dn[1];
       if (mode != QFmode)      /* There are only 2 words in QFmode.  */
-        {
+       {
          y[M+2] = dn[2];       /* Fill in the rest of our mantissa.  */
          y[M+3] = dn[3];
          size = 4;
-        }
+       }
       else
        size = 2;
       eshift (y, -8);
@@ -6073,7 +6051,7 @@ c4xtoe (d, e, mode)
 
       carry = 1;       /* Initially add 1 for the two's complement.  */
       for (i=size + M; i > M; i--)
-        {
+       {
          if (carry && (y[i] == 0x0000))
            /* We overflowed into the next word, carry is the same.  */
            y[i] = carry ? 0x0000 : 0xffff;
@@ -6083,14 +6061,14 @@ c4xtoe (d, e, mode)
              y[i] = ((~y[i]) + carry) & 0xffff;
              carry = 0;
            }
-        }
+       }
 
       if (carry)
-        {
+       {
          eshift (y, -1);
          y[M+1] |= 0x8000;
          r++;
-         }
+       }
        y[1] = r + EXONE;
     }
   else
@@ -6136,7 +6114,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);
 }
@@ -6162,10 +6140,10 @@ toc4x (x, y, mode)
       *y++ = 0x8000;
       *y++ = 0x0000;
       if (mode != QFmode)
-        {
-          *y++ = 0x0000;
-          *y++ = 0x0000;
-        }
+       {
+         *y++ = 0x0000;
+         *y++ = 0x0000;
+       }
       return;
     }
 
@@ -6298,7 +6276,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 +6339,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.  */
 
@@ -6647,7 +6661,7 @@ etoudi (x, i)
     }
   else
     {
-        /* shift not more than 16 bits */
+      /* shift not more than 16 bits */
       eshift (xi, k);
 
 noshift:
@@ -6729,7 +6743,7 @@ etodi (x, i)
     }
   else
     {
-        /* shift not more than 16 bits */
+      /* shift not more than 16 bits */
       eshift (xi, k);
 
       if (WORDS_BIG_ENDIAN)
@@ -6876,11 +6890,10 @@ 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
-#endif /* EMU_NON_COMPILE not defined */
 \f
 /* Return the binary precision of the significand for a given
    floating point mode.  The mode can hold an integer value