OSDN Git Service

(tablejump_internal4+1): Fix typo in condition.
[pf3gnuchains/gcc-fork.git] / gcc / real.c
index 082cfd0..3ebf8f3 100644 (file)
@@ -1,6 +1,6 @@
 /* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
    and support for XFmode IEEE extended real floating point arithmetic.
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
    Contributed by Stephen L. Moshier (moshier@world.std.com).
 
 This file is part of GNU CC.
@@ -471,7 +471,7 @@ endian (e, x, mode)
          th = (unsigned long) e[0] & 0xffff;
          t = (unsigned long) e[1] & 0xffff;
          t |= th << 16;
-         x[0] = t;
+         x[0] = (long) t;
          break;
 
        default:
@@ -520,7 +520,7 @@ endian (e, x, mode)
          th = (unsigned long) e[1] & 0xffff;
          t = (unsigned long) e[0] & 0xffff;
          t |= th << 16;
-         x[0] = t;
+         x[0] = (long) t;
          break;
 
        default:
@@ -758,14 +758,17 @@ efixui (x)
 /* REAL_VALUE_FROM_INT macro.  */
 
 void 
-ereal_from_int (d, i, j)
+ereal_from_int (d, i, j, mode)
      REAL_VALUE_TYPE *d;
      HOST_WIDE_INT i, j;
+     enum machine_mode mode;
 {
   unsigned EMUSHORT df[NE], dg[NE];
   HOST_WIDE_INT low, high;
   int sign;
 
+  if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+    abort ();
   sign = 0;
   low = i;
   if ((high = j) < 0)
@@ -785,6 +788,36 @@ ereal_from_int (d, i, j)
   eadd (df, dg, dg);
   if (sign)
     eneg (dg);
+
+  /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
+     Avoid double-rounding errors later by rounding off now from the
+     extra-wide internal format to the requested precision.  */
+  switch (GET_MODE_BITSIZE (mode))
+    {
+    case 32:
+      etoe24 (dg, df);
+      e24toe (df, dg);
+      break;
+
+    case 64:
+      etoe53 (dg, df);
+      e53toe (df, dg);
+      break;
+
+    case 96:
+      etoe64 (dg, df);
+      e64toe (df, dg);
+      break;
+
+    case 128:
+      etoe113 (dg, df);
+      e113toe (df, dg);
+      break;
+
+    default:
+      abort ();
+  }
+
   PUT_REAL (dg, d);
 }
 
@@ -792,13 +825,16 @@ ereal_from_int (d, i, j)
 /* REAL_VALUE_FROM_UNSIGNED_INT macro.   */
 
 void 
-ereal_from_uint (d, i, j)
+ereal_from_uint (d, i, j, mode)
      REAL_VALUE_TYPE *d;
      unsigned HOST_WIDE_INT i, j;
+     enum machine_mode mode;
 {
   unsigned EMUSHORT df[NE], dg[NE];
   unsigned HOST_WIDE_INT low, high;
 
+  if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+    abort ();
   low = i;
   high = j;
   eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
@@ -806,6 +842,36 @@ ereal_from_uint (d, i, j)
   emul (dg, df, dg);
   ultoe (&low, df);
   eadd (df, dg, dg);
+
+  /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
+     Avoid double-rounding errors later by rounding off now from the
+     extra-wide internal format to the requested precision.  */
+  switch (GET_MODE_BITSIZE (mode))
+    {
+    case 32:
+      etoe24 (dg, df);
+      e24toe (df, dg);
+      break;
+
+    case 64:
+      etoe53 (dg, df);
+      e53toe (df, dg);
+      break;
+
+    case 96:
+      etoe64 (dg, df);
+      e64toe (df, dg);
+      break;
+
+    case 128:
+      etoe113 (dg, df);
+      e113toe (df, dg);
+      break;
+
+    default:
+      abort ();
+  }
+
   PUT_REAL (dg, d);
 }
 
@@ -2597,8 +2663,15 @@ eadd1 (a, b, c)
            {
              if (bi[j] != 0)
                {
-                 /* This could overflow, but let emovo take care of that. */
                  ltb += 1;
+                 if (ltb >= 0x7fff)
+                   {
+                     eclear (c);
+                     if (ai[0] != 0)
+                       eneg (c);
+                     einfin (c);
+                     return;
+                   }
                  break;
                }
            }
@@ -2978,8 +3051,14 @@ e64toe (pe, y)
   else
     {
       p = &yy[0] + (NE - 1);
+#ifdef ARM_EXTENDED_IEEE_FORMAT
+      /* For ARMs, the exponent is in the lowest 15 bits of the word.  */
+      *p-- = (e[0] & 0x8000) | (e[1] & 0x7ffff);
+      e += 2;
+#else
       *p-- = *e++;
       ++e;
+#endif
       for (i = 0; i < 4; i++)
        *p-- = *e++;
     }
@@ -2987,7 +3066,7 @@ e64toe (pe, y)
 #ifdef INFINITY
   /* Point to the exponent field and check max exponent cases.  */
   p = &yy[NE - 1];
-  if (*p == 0x7fff)
+  if ((*p & 0x7fff) == 0x7fff)
     {
 #ifdef NANS
       if (! REAL_WORDS_BIG_ENDIAN)
@@ -3005,7 +3084,8 @@ e64toe (pe, y)
        }
       else
        {
-         for (i = 1; i <= 4; i++)
+#ifdef ARM_EXTENDED_IEEE_FORMAT
+         for (i = 2; i <= 5; i++)
            {
              if (pe[i] != 0)
                {
@@ -3013,6 +3093,23 @@ e64toe (pe, y)
                  return;
                }
            }
+#else /* not ARM */
+         /* In Motorola extended precision format, the most significant
+            bit of an infinity mantissa could be either 1 or 0.  It is
+            the lower order bits that tell whether the value is a NaN.  */
+         if ((pe[2] & 0x7fff) != 0)
+           goto bigend_nan;
+
+         for (i = 3; i <= 5; i++)
+           {
+             if (pe[i] != 0)
+               {
+bigend_nan:
+                 enan (y, (*p & 0x8000) != 0);
+                 return;
+               }
+           }
+#endif /* not ARM */
        }
 #endif /* NANS */
       eclear (y);
@@ -3390,11 +3487,17 @@ toe64 (a, b)
 #ifdef IEEE
   if (REAL_WORDS_BIG_ENDIAN)
     {
+#ifdef ARM_EXTENDED_IEEE_FORMAT
+      /* The exponent is in the lowest 15 bits of the first word.  */
+      *q++ = i ? 0x8000 : 0;
+      *q++ = *p++;
+#else
       if (i)
        *q++ = *p++ | 0x8000;
       else
        *q++ = *p++;
       *q++ = 0;
+#endif
     }
   else
     {
@@ -6091,12 +6194,15 @@ significand_size (mode)
      enum machine_mode mode;
 {
 
-switch (mode)
+/* Don't test the modes, but their sizes, lest this
+   code won't work for BITS_PER_UNIT != 8 .  */
+
+switch (GET_MODE_BITSIZE (mode))
   {
-  case SFmode:
+  case 32:
     return 24;
 
-  case DFmode:
+  case 64:
 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
     return 53;
 #else
@@ -6111,9 +6217,9 @@ switch (mode)
 #endif
 #endif
 
-  case XFmode:
+  case 96:
     return 64;
-  case TFmode:
+  case 128:
     return 113;
 
   default: