real.h (EXP_BITS): Make room for...
authorAlexandre Oliva <aoliva@redhat.com>
Tue, 1 Apr 2003 21:45:28 +0000 (21:45 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Tue, 1 Apr 2003 21:45:28 +0000 (21:45 +0000)
* real.h (EXP_BITS): Make room for...
(struct real_value): ... added canonical bit.
(struct real_format): Added pnan.
(mips_single_format, mips_double_format, mips_extended_format,
mips_quad_format): New.
* real.c: Copy p to pnan in all formats.
(get_canonical_qnan, get_canonical_snan): Set canonical bit.
(real_nan): Use pnan to compute significand's shift.
(real_identical): Disregard significand in canonical
NaNs.
(real_hash): Likewise.  Take signalling into account.
(encode_ieee_single, encode_ieee_double, encode_ieee_quad):
Disregard significand bits in canonical NaNs.  Set all bits of
canonical NaN if !qnan_msb_set.
(encode_ibm_extended, decode_ibm_extended): Likewise.  Use
qnan_msb_set to tell the base double format.
(ibm_extended_format): Use 53 as pnan.
(mips_single_format, mips_double_format, mips_extended_format,
mips_quad_format): Copied from the corresponding ieee/ibm
formats, with qnan_msb_set false.
* config/mips/iris6.h (MIPS_TFMODE_FORMAT): Use mips_extended_format.
* config/mips/linux64.h (MIPS_TFMODE_FORMAT): Use mips_quad_format.
* config/mips/mips.c (override_options): Use mips_single_format
and mips_double_format.  Default TFmode to mips_quad_format.
* config/mips/t-linux64 (tp-bit.c): Define QUIET_NAN_NEGATED.
* config/mips/t-irix6: Likewise.
* config/mips/t-mips (fp-bit.c, dp-bit.c): Likewise.
* config/fp-bit.c (pack_d, unpack_d): Obey it.

From-SVN: r65146

gcc/ChangeLog
gcc/config/fp-bit.c
gcc/config/mips/iris6.h
gcc/config/mips/linux64.h
gcc/config/mips/mips.c
gcc/config/mips/t-iris6
gcc/config/mips/t-linux64
gcc/config/mips/t-mips
gcc/real.c
gcc/real.h

index a96f1ad677a302febcdf647d65d219cbacc68377..82c47e019bc98a6af5054884abdee379a59caba3 100644 (file)
@@ -1,3 +1,34 @@
+2003-04-01  Alexandre Oliva  <aoliva@redhat.com>
+
+       * real.h (EXP_BITS): Make room for...
+       (struct real_value): ... added canonical bit.
+       (struct real_format): Added pnan.
+       (mips_single_format, mips_double_format, mips_extended_format,
+       mips_quad_format): New.
+       * real.c: Copy p to pnan in all formats.
+       (get_canonical_qnan, get_canonical_snan): Set canonical bit.
+       (real_nan): Use pnan to compute significand's shift.
+       (real_identical): Disregard significand in canonical
+       NaNs.
+       (real_hash): Likewise.  Take signalling into account.
+       (encode_ieee_single, encode_ieee_double, encode_ieee_quad):
+       Disregard significand bits in canonical NaNs.  Set all bits of
+       canonical NaN if !qnan_msb_set.
+       (encode_ibm_extended, decode_ibm_extended): Likewise.  Use
+       qnan_msb_set to tell the base double format.
+       (ibm_extended_format): Use 53 as pnan.
+       (mips_single_format, mips_double_format, mips_extended_format,
+       mips_quad_format): Copied from the corresponding ieee/ibm
+       formats, with qnan_msb_set false.
+       * config/mips/iris6.h (MIPS_TFMODE_FORMAT): Use mips_extended_format.
+       * config/mips/linux64.h (MIPS_TFMODE_FORMAT): Use mips_quad_format.
+       * config/mips/mips.c (override_options): Use mips_single_format
+       and mips_double_format.  Default TFmode to mips_quad_format.
+       * config/mips/t-linux64 (tp-bit.c): Define QUIET_NAN_NEGATED.
+       * config/mips/t-irix6: Likewise.
+       * config/mips/t-mips (fp-bit.c, dp-bit.c): Likewise.
+       * config/fp-bit.c (pack_d, unpack_d): Obey it.
+
 2003-04-01  Geoffrey Keating  <geoffk@apple.com>
 
        * unwind-dw2-fde-darwin.c (DESTRUCTOR_MAY_BE_CALLED_LIVE): New.
index 3e0b843f5050ea39666edc6fc66fba7e2f43e65c..2832f96d5780ee248fe5a0bbde83e69723768e0b 100644 (file)
@@ -210,7 +210,11 @@ pack_d ( fp_number_type *  src)
       exp = EXPMAX;
       if (src->class == CLASS_QNAN || 1)
        {
+#ifdef QUIET_NAN_NEGATED
+         fraction |= QUIET_NAN - 1;
+#else
          fraction |= QUIET_NAN;
+#endif
        }
     }
   else if (isinf (src))
@@ -521,7 +525,11 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
       else
        {
          /* Nonzero fraction, means nan */
+#ifdef QUIET_NAN_NEGATED
+         if ((fraction & QUIET_NAN) == 0)
+#else
          if (fraction & QUIET_NAN)
+#endif
            {
              dst->class = CLASS_QNAN;
            }
index dd69c15606475cc6df392b6bbd57d1ac7c9cb2c0..69f01aafa2f76929457f80077be993f5a5d3cf76 100644 (file)
@@ -525,4 +525,4 @@ do {                                                                         \
 -_SYSTYPE_SVR4 -woff 131 \
 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
 
-#define MIPS_TFMODE_FORMAT ibm_extended_format
+#define MIPS_TFMODE_FORMAT mips_extended_format
index db1d4e0cc40733ebe425f5a1d5472e011d48c891..c78e789f89ca1d76dcb63ce4ef33acf82ac32d6f 100644 (file)
@@ -98,4 +98,4 @@ Boston, MA 02111-1307, USA.  */
    for long double.  There's no need to override this here, since
    ieee_quad_format is the default, but let's put this here to make
    sure nobody thinks we just forgot to set it to something else.  */
-#define MIPS_TFMODE_FORMAT ieee_quad_format
+#define MIPS_TFMODE_FORMAT mips_quad_format
index b806fb1c97562775ad5e813d4cdce781587f7314..6425f2322039892d37b581c7b11bc0dad51d4623 100644 (file)
@@ -5714,8 +5714,12 @@ override_options ()
   else
     mips16 = 0;
 
+  real_format_for_mode[SFmode - QFmode] = &mips_single_format;
+  real_format_for_mode[DFmode - QFmode] = &mips_double_format;
 #ifdef MIPS_TFMODE_FORMAT
   real_format_for_mode[TFmode - QFmode] = &MIPS_TFMODE_FORMAT;
+#else
+  real_format_for_mode[TFmode - QFmode] = &mips_quad_format;
 #endif
   
   mips_print_operand_punct['?'] = 1;
index a1be0b9c9ed2faa968a0ff5a927a3ddf6fbca4b8..d403df4cf00e38c9ec6b39f4462151dd23b0f50d 100644 (file)
@@ -27,6 +27,7 @@ tp-bit.c: $(srcdir)/config/fp-bit.c
        echo '#ifdef __MIPSEL__' > tp-bit.c
        echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
        echo '#endif' >> tp-bit.c
+       echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
        echo '#if __LDBL_MANT_DIG__ == 106' >> tp-bit.c
        echo '# define TFLOAT' >> tp-bit.c
        cat $(srcdir)/config/fp-bit.c >> tp-bit.c
index cf63928777076891a575ffd084071b633e148848..a0792f23a94e3e580318f0b43c76fca1fffeab68 100644 (file)
@@ -13,6 +13,7 @@ tp-bit.c: $(srcdir)/config/fp-bit.c
        echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
        echo '#endif' >> tp-bit.c
        echo '#if __LDBL_MANT_DIG__ == 113' >> tp-bit.c
+       echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
        echo '# define TFLOAT' >> tp-bit.c
        cat $(srcdir)/config/fp-bit.c >> tp-bit.c
        echo '#endif' >> tp-bit.c
index 292386d03830a83283bd024a6576da10ee966fc3..497f4fb20cb567481a6ed40b049da809b0246944 100644 (file)
@@ -9,6 +9,7 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
        echo '#ifdef __MIPSEL__' > dp-bit.c
        echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
        echo '#endif' >> dp-bit.c
+       echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
        cat $(srcdir)/config/fp-bit.c >> dp-bit.c
 
 fp-bit.c: $(srcdir)/config/fp-bit.c
@@ -16,4 +17,5 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
        echo '#ifdef __MIPSEL__' >> fp-bit.c
        echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
        echo '#endif' >> fp-bit.c
+       echo '#define QUIET_NAN_NEGATED' >> fp-bit.c
        cat $(srcdir)/config/fp-bit.c >> fp-bit.c
index 29d5de1f01448b0b33ccd471878f684486dc5b0f..74f430c29ae46bcb4105e1caeca774119553aeb6 100644 (file)
@@ -158,6 +158,7 @@ get_canonical_qnan (r, sign)
   memset (r, 0, sizeof (*r));
   r->class = rvc_nan;
   r->sign = sign;
+  r->canonical = 1;
 }
 
 static inline void
@@ -169,6 +170,7 @@ get_canonical_snan (r, sign)
   r->class = rvc_nan;
   r->sign = sign;
   r->signalling = 1;
+  r->canonical = 1;
 }
 
 static inline void
@@ -1212,7 +1214,7 @@ real_isnegzero (r)
 
 /* Compare two floating-point objects for bitwise identity.  */
 
-extern bool
+bool
 real_identical (a, b)
      const REAL_VALUE_TYPE *a, *b;
 {
@@ -1237,6 +1239,9 @@ real_identical (a, b)
     case rvc_nan:
       if (a->signalling != b->signalling)
        return false;
+      /* The significand is ignored for canonical NaNs.  */
+      if (a->canonical || b->canonical)
+       return a->canonical == b->canonical;
       break;
 
     default:
@@ -2246,7 +2251,7 @@ real_nan (r, str, quiet, mode)
 
       /* Shift the significand into place such that the bits
         are in the most significant bits for the format.  */
-      lshift_significand (r, r, SIGNIFICAND_BITS - fmt->p);
+      lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan);
 
       /* Our MSB is always unset for NaNs.  */
       r->sig[SIGSZ-1] &= ~SIG_MSB;
@@ -2562,28 +2567,33 @@ real_hash (r)
     {
     case rvc_zero:
     case rvc_inf:
-      break;
+      return h;
 
     case rvc_normal:
       h |= r->exp << 3;
-      /* FALLTHRU */
+      break;
 
     case rvc_nan:
-      if (sizeof(unsigned long) > sizeof(unsigned int))
-       for (i = 0; i < SIGSZ; ++i)
-         {
-           unsigned long s = r->sig[i];
-           h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2));
-         }
-      else
-       for (i = 0; i < SIGSZ; ++i)
-         h ^= r->sig[i];
+      if (r->signalling)
+       h ^= (unsigned int)-1;
+      if (r->canonical)
+       return h;
       break;
 
     default:
       abort ();
     }
 
+  if (sizeof(unsigned long) > sizeof(unsigned int))
+    for (i = 0; i < SIGSZ; ++i)
+      {
+       unsigned long s = r->sig[i];
+       h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2));
+      }
+  else
+    for (i = 0; i < SIGSZ; ++i)
+      h ^= r->sig[i];
+
   return h;
 }
 \f
@@ -2621,11 +2631,19 @@ encode_ieee_single (fmt, buf, r)
     case rvc_nan:
       if (fmt->has_nans)
        {
+         if (r->canonical)
+           sig = 0;
          if (r->signalling == fmt->qnan_msb_set)
            sig &= ~(1 << 22);
          else
            sig |= 1 << 22;
-         if (sig == 0)
+         /* We overload qnan_msb_set here: it's only clear for
+            mips_ieee_single, which wants all mantissa bits but the
+            quiet/signalling one set in canonical NaNs (at least
+            Quiet ones).  */
+         if (r->canonical && !fmt->qnan_msb_set)
+           sig |= (1 << 22) - 1;
+         else if (sig == 0)
            sig = 1 << 21;
 
          image |= 255 << 23;
@@ -2712,6 +2730,7 @@ const struct real_format ieee_single_format =
     2,
     1,
     24,
+    24,
     -125,
     128,
     31,
@@ -2722,6 +2741,24 @@ const struct real_format ieee_single_format =
     true
   };
 
+const struct real_format mips_single_format = 
+  {
+    encode_ieee_single,
+    decode_ieee_single,
+    2,
+    1,
+    24,
+    24,
+    -125,
+    128,
+    31,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
+
 \f
 /* IEEE double-precision format.  */
 
@@ -2774,11 +2811,22 @@ encode_ieee_double (fmt, buf, r)
     case rvc_nan:
       if (fmt->has_nans)
        {
+         if (r->canonical)
+           sig_hi = sig_lo = 0;
          if (r->signalling == fmt->qnan_msb_set)
            sig_hi &= ~(1 << 19);
          else
            sig_hi |= 1 << 19;
-         if (sig_hi == 0 && sig_lo == 0)
+         /* We overload qnan_msb_set here: it's only clear for
+            mips_ieee_single, which wants all mantissa bits but the
+            quiet/signalling one set in canonical NaNs (at least
+            Quiet ones).  */
+         if (r->canonical && !fmt->qnan_msb_set)
+           {
+             sig_hi |= (1 << 19) - 1;
+             sig_lo = 0xffffffff;
+           }
+         else if (sig_hi == 0 && sig_lo == 0)
            sig_hi = 1 << 18;
 
          image_hi |= 2047 << 20;
@@ -2909,6 +2957,7 @@ const struct real_format ieee_double_format =
     2,
     1,
     53,
+    53,
     -1021,
     1024,
     63,
@@ -2919,6 +2968,24 @@ const struct real_format ieee_double_format =
     true
   };
 
+const struct real_format mips_double_format = 
+  {
+    encode_ieee_double,
+    decode_ieee_double,
+    2,
+    1,
+    53,
+    53,
+    -1021,
+    1024,
+    63,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
+
 \f
 /* IEEE extended double precision format.  This comes in three
    flavours: Intel's as a 12 byte image, Intel's as a 16 byte image,
@@ -3167,6 +3234,7 @@ const struct real_format ieee_extended_motorola_format =
     2,
     1,
     64,
+    64,
     -16382,
     16384,
     95,
@@ -3184,6 +3252,7 @@ const struct real_format ieee_extended_intel_96_format =
     2,
     1,
     64,
+    64,
     -16381,
     16384,
     79,
@@ -3201,6 +3270,7 @@ const struct real_format ieee_extended_intel_128_format =
     2,
     1,
     64,
+    64,
     -16381,
     16384,
     79,
@@ -3228,11 +3298,14 @@ static void decode_ibm_extended PARAMS ((const struct real_format *,
 
 static void
 encode_ibm_extended (fmt, buf, r)
-     const struct real_format *fmt ATTRIBUTE_UNUSED;
+     const struct real_format *fmt;
      long *buf;
      const REAL_VALUE_TYPE *r;
 {
   REAL_VALUE_TYPE u, v;
+  const struct real_format *base_fmt;
+
+  base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
 
   switch (r->class)
     {
@@ -3247,7 +3320,7 @@ encode_ibm_extended (fmt, buf, r)
     case rvc_inf:
     case rvc_nan:
       /* Both doubles set to Inf / NaN.  */
-      encode_ieee_double (&ieee_double_format, &buf[0], r);
+      encode_ieee_double (base_fmt, &buf[0], r);
       buf[2] = buf[0];
       buf[3] = buf[1];
       return;
@@ -3270,13 +3343,13 @@ encode_ibm_extended (fmt, buf, r)
        {
          /* v = remainder containing additional 53 bits of significand.  */
          do_add (&v, r, &u, 1);
-         round_for_format (&ieee_double_format, &v);
+         round_for_format (base_fmt, &v);
        }
 
-      round_for_format (&ieee_double_format, &u);
+      round_for_format (base_fmt, &u);
 
-      encode_ieee_double (&ieee_double_format, &buf[0], &u);
-      encode_ieee_double (&ieee_double_format, &buf[2], &v);
+      encode_ieee_double (base_fmt, &buf[0], &u);
+      encode_ieee_double (base_fmt, &buf[2], &v);
       break;
 
     default:
@@ -3291,12 +3364,14 @@ decode_ibm_extended (fmt, r, buf)
      const long *buf;
 {
   REAL_VALUE_TYPE u, v;
+  const struct real_format *base_fmt;
 
-  decode_ieee_double (&ieee_double_format, &u, &buf[0]);
+  base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
+  decode_ieee_double (base_fmt, &u, &buf[0]);
 
   if (u.class != rvc_zero && u.class != rvc_inf && u.class != rvc_nan)
     {
-      decode_ieee_double (&ieee_double_format, &v, &buf[2]);
+      decode_ieee_double (base_fmt, &v, &buf[2]);
       do_add (r, &u, &v, 0);
     }
   else
@@ -3310,6 +3385,7 @@ const struct real_format ibm_extended_format =
     2,
     1,
     53 + 53,
+    53,
     -1021 + 53,
     1024,
     -1,
@@ -3320,6 +3396,24 @@ const struct real_format ibm_extended_format =
     true
   };
 
+const struct real_format mips_extended_format = 
+  {
+    encode_ibm_extended,
+    decode_ibm_extended,
+    2,
+    1,
+    53 + 53,
+    53,
+    -1021 + 53,
+    1024,
+    -1,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
+
 \f
 /* IEEE quad precision format.  */
 
@@ -3367,7 +3461,12 @@ encode_ieee_quad (fmt, buf, r)
        {
          image3 |= 32767 << 16;
 
-         if (HOST_BITS_PER_LONG == 32)
+         if (r->canonical)
+           {
+             /* Don't use bits from the significand.  The
+                initialization above is right.  */
+           }
+         else if (HOST_BITS_PER_LONG == 32)
            {
              image0 = u.sig[0];
              image1 = u.sig[1];
@@ -3387,7 +3486,16 @@ encode_ieee_quad (fmt, buf, r)
            image3 &= ~0x8000;
          else
            image3 |= 0x8000;
-         if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
+         /* We overload qnan_msb_set here: it's only clear for
+            mips_ieee_single, which wants all mantissa bits but the
+            quiet/signalling one set in canonical NaNs (at least
+            Quiet ones).  */
+         if (r->canonical && !fmt->qnan_msb_set)
+           {
+             image3 |= 0x7fff;
+             image2 = image1 = image0 = 0xffffffff;
+           }
+         else if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
            image3 |= 0x4000;
        }
       else
@@ -3565,6 +3673,7 @@ const struct real_format ieee_quad_format =
     2,
     1,
     113,
+    113,
     -16381,
     16384,
     127,
@@ -3574,6 +3683,24 @@ const struct real_format ieee_quad_format =
     true,
     true
   };
+
+const struct real_format mips_quad_format = 
+  {
+    encode_ieee_quad,
+    decode_ieee_quad,
+    2,
+    1,
+    113,
+    113,
+    -16381,
+    16384,
+    127,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
 \f
 /* Descriptions of VAX floating point formats can be found beginning at
 
@@ -3873,6 +4000,7 @@ const struct real_format vax_f_format =
     2,
     1,
     24,
+    24,
     -127,
     127,
     15,
@@ -3890,6 +4018,7 @@ const struct real_format vax_d_format =
     2,
     1,
     56,
+    56,
     -127,
     127,
     15,
@@ -3907,6 +4036,7 @@ const struct real_format vax_g_format =
     2,
     1,
     53,
+    53,
     -1023,
     1023,
     15,
@@ -4089,6 +4219,7 @@ const struct real_format i370_single_format =
     16,
     4,
     6,
+    6,
     -64,
     63,
     31,
@@ -4106,6 +4237,7 @@ const struct real_format i370_double_format =
     16,
     4,
     14,
+    14,
     -64,
     63,
     63,
@@ -4321,6 +4453,7 @@ const struct real_format c4x_single_format =
     2,
     1,
     24,
+    24,
     -126,
     128,
     -1,
@@ -4338,6 +4471,7 @@ const struct real_format c4x_extended_format =
     2,
     1,
     32,
+    32,
     -126,
     128,
     -1,
@@ -4384,6 +4518,7 @@ const struct real_format real_internal_format =
     2,
     1,
     SIGNIFICAND_BITS - 2,
+    SIGNIFICAND_BITS - 2,
     -MAX_EXP,
     MAX_EXP,
     -1,
index 9507af2270d84ef742e8c9de224f9655053b0a76..0a470a512f3cd6d06948f294517f70d87eec24f8 100644 (file)
@@ -35,7 +35,7 @@ enum real_value_class {
 };
 
 #define SIGNIFICAND_BITS       (128 + HOST_BITS_PER_LONG)
-#define EXP_BITS               (32 - 4)
+#define EXP_BITS               (32 - 5)
 #define MAX_EXP                        ((1 << (EXP_BITS - 1)) - 1)
 #define SIGSZ                  (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
 #define SIG_MSB                        ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
@@ -45,6 +45,7 @@ struct real_value GTY(())
   ENUM_BITFIELD (real_value_class) class : 2;
   unsigned int sign : 1;
   unsigned int signalling : 1;
+  unsigned int canonical : 1;
   signed int exp : EXP_BITS;
   unsigned long sig[SIGSZ];
 };
@@ -119,6 +120,9 @@ struct real_format
   /* Size of the significand in digits of radix B.  */
   int p;
 
+  /* Size of the significant of a NaN, in digits of radix B.  */
+  int pnan;
+
   /* The minimum negative integer, x, such that b**(x-1) is normalized.  */
   int emin;
 
@@ -222,12 +226,16 @@ extern unsigned int real_hash     PARAMS ((const REAL_VALUE_TYPE *));
 
 /* Target formats defined in real.c.  */
 extern const struct real_format ieee_single_format;
+extern const struct real_format mips_single_format;
 extern const struct real_format ieee_double_format;
+extern const struct real_format mips_double_format;
 extern const struct real_format ieee_extended_motorola_format;
 extern const struct real_format ieee_extended_intel_96_format;
 extern const struct real_format ieee_extended_intel_128_format;
 extern const struct real_format ibm_extended_format;
+extern const struct real_format mips_extended_format;
 extern const struct real_format ieee_quad_format;
+extern const struct real_format mips_quad_format;
 extern const struct real_format vax_f_format;
 extern const struct real_format vax_d_format;
 extern const struct real_format vax_g_format;