This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: mips SNaN/QNaN is swapped


On Apr  1, 2003, Richard Henderson <rth at redhat dot com> wrote:

> You've missed the needed change to real_identical.  In this case,
> if canonical, you should ignore the significand.  This implies a
> needed change to real_hash as well.

> And further implies that canonical should ignore the existing value
> of sig.

This revised patch corrects the two problems above.  Ok to install if
it bootstraps on athlon-pc-linux-gnu and generates the correct bit
patterns on native, x-mips64-linux and x-mips-sgi-irix6.5?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva at redhat dot 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.

Index: gcc/real.c
===================================================================
RCS file: /cvs/uberbaum/gcc/real.c,v
retrieving revision 1.114
diff -u -p -r1.114 real.c
--- gcc/real.c 31 Mar 2003 21:02:10 -0000 1.114
+++ gcc/real.c 1 Apr 2003 14:10:41 -0000
@@ -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;
@@ -2569,6 +2574,10 @@ real_hash (r)
       /* FALLTHRU */
 
     case rvc_nan:
+      if (r->signalling)
+	h ^= (unsigned int)-1;
+      if (r->canonical)
+	break;
       if (sizeof(unsigned long) > sizeof(unsigned int))
 	for (i = 0; i < SIGSZ; ++i)
 	  {
@@ -2621,11 +2630,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 +2729,7 @@ const struct real_format ieee_single_for
     2,
     1,
     24,
+    24,
     -125,
     128,
     31,
@@ -2722,6 +2740,24 @@ const struct real_format ieee_single_for
     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
+  };
+
 
 /* IEEE double-precision format.  */
 
@@ -2774,11 +2810,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 +2956,7 @@ const struct real_format ieee_double_for
     2,
     1,
     53,
+    53,
     -1021,
     1024,
     63,
@@ -2919,6 +2967,24 @@ const struct real_format ieee_double_for
     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
+  };
+
 
 /* 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 +3233,7 @@ const struct real_format ieee_extended_m
     2,
     1,
     64,
+    64,
     -16382,
     16384,
     95,
@@ -3184,6 +3251,7 @@ const struct real_format ieee_extended_i
     2,
     1,
     64,
+    64,
     -16381,
     16384,
     79,
@@ -3201,6 +3269,7 @@ const struct real_format ieee_extended_i
     2,
     1,
     64,
+    64,
     -16381,
     16384,
     79,
@@ -3228,11 +3297,14 @@ static void decode_ibm_extended PARAMS (
 
 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 +3319,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 +3342,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 +3363,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 +3384,7 @@ const struct real_format ibm_extended_fo
     2,
     1,
     53 + 53,
+    53,
     -1021 + 53,
     1024,
     -1,
@@ -3320,6 +3395,24 @@ const struct real_format ibm_extended_fo
     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
+  };
+
 
 /* IEEE quad precision format.  */
 
@@ -3367,7 +3460,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 +3485,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 +3672,7 @@ const struct real_format ieee_quad_forma
     2,
     1,
     113,
+    113,
     -16381,
     16384,
     127,
@@ -3574,6 +3682,24 @@ const struct real_format ieee_quad_forma
     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
+  };
 
 /* Descriptions of VAX floating point formats can be found beginning at
 
@@ -3873,6 +3999,7 @@ const struct real_format vax_f_format = 
     2,
     1,
     24,
+    24,
     -127,
     127,
     15,
@@ -3890,6 +4017,7 @@ const struct real_format vax_d_format = 
     2,
     1,
     56,
+    56,
     -127,
     127,
     15,
@@ -3907,6 +4035,7 @@ const struct real_format vax_g_format = 
     2,
     1,
     53,
+    53,
     -1023,
     1023,
     15,
@@ -4089,6 +4218,7 @@ const struct real_format i370_single_for
     16,
     4,
     6,
+    6,
     -64,
     63,
     31,
@@ -4106,6 +4236,7 @@ const struct real_format i370_double_for
     16,
     4,
     14,
+    14,
     -64,
     63,
     63,
@@ -4321,6 +4452,7 @@ const struct real_format c4x_single_form
     2,
     1,
     24,
+    24,
     -126,
     128,
     -1,
@@ -4338,6 +4470,7 @@ const struct real_format c4x_extended_fo
     2,
     1,
     32,
+    32,
     -126,
     128,
     -1,
@@ -4383,6 +4516,7 @@ const struct real_format real_internal_f
     decode_internal,
     2,
     1,
+    SIGNIFICAND_BITS - 2,
     SIGNIFICAND_BITS - 2,
     -MAX_EXP,
     MAX_EXP,
Index: gcc/real.h
===================================================================
RCS file: /cvs/uberbaum/gcc/real.h,v
retrieving revision 1.63
diff -u -p -r1.63 real.h
--- gcc/real.h 31 Mar 2003 14:30:27 -0000 1.63
+++ gcc/real.h 1 Apr 2003 14:10:42 -0000
@@ -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 ((c
 
 /* 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;
Index: gcc/config/fp-bit.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/fp-bit.c,v
retrieving revision 1.39
diff -u -p -r1.39 fp-bit.c
--- gcc/config/fp-bit.c 26 Jan 2003 10:06:57 -0000 1.39
+++ gcc/config/fp-bit.c 1 Apr 2003 14:10:42 -0000
@@ -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_numbe
       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: gcc/config/mips/iris6.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/iris6.h,v
retrieving revision 1.58
diff -u -p -r1.58 iris6.h
--- gcc/config/mips/iris6.h 19 Mar 2003 18:18:36 -0000 1.58
+++ gcc/config/mips/iris6.h 1 Apr 2003 14:10:43 -0000
@@ -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: gcc/config/mips/linux64.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/linux64.h,v
retrieving revision 1.2
diff -u -p -r1.2 linux64.h
--- gcc/config/mips/linux64.h 11 Mar 2003 23:31:01 -0000 1.2
+++ gcc/config/mips/linux64.h 1 Apr 2003 14:10:43 -0000
@@ -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: gcc/config/mips/mips.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/mips.c,v
retrieving revision 1.252
diff -u -p -r1.252 mips.c
--- gcc/config/mips/mips.c 19 Feb 2003 18:03:09 -0000 1.252
+++ gcc/config/mips/mips.c 1 Apr 2003 14:10:50 -0000
@@ -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: gcc/config/mips/t-iris6
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/t-iris6,v
retrieving revision 1.17
diff -u -p -r1.17 t-iris6
--- gcc/config/mips/t-iris6 28 Jan 2003 02:18:43 -0000 1.17
+++ gcc/config/mips/t-iris6 1 Apr 2003 14:10:50 -0000
@@ -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: gcc/config/mips/t-linux64
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/t-linux64,v
retrieving revision 1.1
diff -u -p -r1.1 t-linux64
--- gcc/config/mips/t-linux64 19 Jan 2003 13:04:24 -0000 1.1
+++ gcc/config/mips/t-linux64 1 Apr 2003 14:10:50 -0000
@@ -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: gcc/config/mips/t-mips
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/t-mips,v
retrieving revision 1.5
diff -u -p -r1.5 t-mips
--- gcc/config/mips/t-mips 29 Jul 2002 22:21:41 -0000 1.5
+++ gcc/config/mips/t-mips 1 Apr 2003 14:10:50 -0000
@@ -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
-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva at {redhat dot com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva at {lsd dot ic dot unicamp dot br, gnu.org}
Free Software Evangelist                Professional serial bug killer

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]