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 Tue, Mar 25, 2003 at 06:46:27AM -0300, Alexandre Oliva wrote:
> It fixes the very bug I mentioned in my earlier posts.

Not quite.  It moves the bug around.

I think the cleanest way to correct this is to fix the representation.
I've briefly tested the following by eye on both x86 and mips.



r~



Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.111
diff -c -p -d -u -r1.111 real.c
--- real.c	26 Feb 2003 21:07:40 -0000	1.111
+++ real.c	27 Mar 2003 01:23:42 -0000
@@ -158,7 +158,6 @@ get_canonical_qnan (r, sign)
   memset (r, 0, sizeof (*r));
   r->class = rvc_nan;
   r->sign = sign;
-  r->sig[SIGSZ-1] = SIG_MSB >> 1;
 }
 
 static inline void
@@ -169,7 +168,7 @@ get_canonical_snan (r, sign)
   memset (r, 0, sizeof (*r));
   r->class = rvc_nan;
   r->sign = sign;
-  r->sig[SIGSZ-1] = SIG_MSB >> 2;
+  r->signalling = 1;
 }
 
 static inline void
@@ -1235,6 +1234,8 @@ real_identical (a, b)
  	return false;
       /* FALLTHRU */
     case rvc_nan:
+      if (a->signalling != b->signalling)
+	return false;
       for (i = 0; i < SIGSZ; ++i)
 	if (a->sig[i] != b->sig[i])
 	  return false;
@@ -2249,23 +2250,7 @@ real_nan (r, str, quiet, mode)
       r->sig[SIGSZ-1] &= ~SIG_MSB;
 
       /* Force quiet or signalling NaN.  */
-      if (quiet)
-	r->sig[SIGSZ-1] |= SIG_MSB >> 1;
-      else
-	r->sig[SIGSZ-1] &= ~(SIG_MSB >> 1);
-
-      /* Force at least one bit of the significand set.  */
-      for (d = 0; d < SIGSZ; ++d)
-	if (r->sig[d])
-	  break;
-      if (d == SIGSZ)
-	r->sig[SIGSZ-1] |= SIG_MSB >> 2;
-
-      /* Our intermediate format forces QNaNs to have MSB-1 set.
-	 If the target format has QNaNs with the top bit unset,
-	 mirror the output routines and invert the top two bits.  */
-      if (!fmt->qnan_msb_set)
-	r->sig[SIGSZ-1] ^= (SIG_MSB >> 1) | (SIG_MSB >> 2);
+      r->signalling = !quiet;
     }
 
   return true;
@@ -2325,14 +2310,6 @@ round_for_format (fmt, r)
 
     case rvc_nan:
       clear_significand_below (r, np2);
-
-      /* If we've cleared the entire significand, we need one bit
-	 set for this to continue to be a NaN.  */
-      for (i = 0; i < SIGSZ; ++i)
-	if (r->sig[i])
-	  break;
-      if (i == SIGSZ)
-	r->sig[SIGSZ-1] = SIG_MSB >> 2;
       return;
 
     case rvc_normal:
@@ -2642,10 +2619,15 @@ encode_ieee_single (fmt, buf, r)
     case rvc_nan:
       if (fmt->has_nans)
 	{
+	  if (r->signalling == fmt->qnan_msb_set)
+	    sig &= ~(1 << 22);
+	  else
+	    sig |= 1 << 22;
+	  if (sig == 0)
+	    sig = 1 << 21;
+
 	  image |= 255 << 23;
 	  image |= sig;
-	  if (!fmt->qnan_msb_set)
-	    image ^= 1 << 23 | 1 << 22;
 	}
       else
 	image |= 0x7fffffff;
@@ -2703,8 +2685,7 @@ decode_ieee_single (fmt, r, buf)
 	{
 	  r->class = rvc_nan;
 	  r->sign = sign;
-	  if (!fmt->qnan_msb_set)
-	    image ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+	  r->signalling = ((image >> 22) & 1) ^ fmt->qnan_msb_set;
 	  r->sig[SIGSZ-1] = image;
 	}
       else
@@ -2739,6 +2720,23 @@ const struct real_format ieee_single_for
     true
   };
 
+const struct real_format mips_single_format = 
+  {
+    encode_ieee_single,
+    decode_ieee_single,
+    2,
+    1,
+    24,
+    -125,
+    128,
+    31,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
+
 
 /* IEEE double-precision format.  */
 
@@ -2791,10 +2789,15 @@ encode_ieee_double (fmt, buf, r)
     case rvc_nan:
       if (fmt->has_nans)
 	{
+	  if (r->signalling == fmt->qnan_msb_set)
+	    sig_hi &= ~(1 << 19);
+	  else
+	    sig_hi |= 1 << 19;
+	  if (sig_hi == 0 && sig_lo == 0)
+	    sig_hi = 1 << 18;
+
 	  image_hi |= 2047 << 20;
 	  image_hi |= sig_hi;
-	  if (!fmt->qnan_msb_set)
-	    image_hi ^= 1 << 19 | 1 << 18;
 	  image_lo = sig_lo;
 	}
       else
@@ -2884,6 +2887,7 @@ decode_ieee_double (fmt, r, buf)
 	{
 	  r->class = rvc_nan;
 	  r->sign = sign;
+	  r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set;
 	  if (HOST_BITS_PER_LONG == 32)
 	    {
 	      r->sig[SIGSZ-1] = image_hi;
@@ -2891,9 +2895,6 @@ decode_ieee_double (fmt, r, buf)
 	    }
 	  else
 	    r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo;
-
-	  if (!fmt->qnan_msb_set)
-	    r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
 	}
       else
 	{
@@ -2933,6 +2934,23 @@ const struct real_format ieee_double_for
     true
   };
 
+const struct real_format mips_double_format = 
+  {
+    encode_ieee_double,
+    decode_ieee_double,
+    2,
+    1,
+    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,
@@ -2999,8 +3017,12 @@ encode_ieee_extended (fmt, buf, r)
 	      sig_hi = sig_lo >> 31 >> 1;
 	      sig_lo &= 0xffffffff;
 	    }
-	  if (!fmt->qnan_msb_set)
-	    sig_hi ^= 1 << 30 | 1 << 29;
+	  if (r->signalling == fmt->qnan_msb_set)
+	    sig_hi &= ~(1 << 30);
+	  else
+	    sig_hi |= 1 << 30;
+	  if ((sig_hi & 0x7fffffff) == 0 && sig_lo == 0)
+	    sig_hi = 1 << 29;
 
 	  /* Intel requires the explicit integer bit to be set, otherwise
 	     it considers the value a "pseudo-nan".  Motorola docs say it
@@ -3131,6 +3153,7 @@ decode_ieee_extended (fmt, r, buf)
 	{
 	  r->class = rvc_nan;
 	  r->sign = sign;
+	  r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set;
 	  if (HOST_BITS_PER_LONG == 32)
 	    {
 	      r->sig[SIGSZ-1] = sig_hi;
@@ -3138,9 +3161,6 @@ decode_ieee_extended (fmt, r, buf)
 	    }
 	  else
 	    r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
-
-	  if (!fmt->qnan_msb_set)
-	    r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
 	}
       else
 	{
@@ -3332,6 +3352,23 @@ 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,
+    -1021 + 53,
+    1024,
+    -1,
+    true,
+    true,
+    true,
+    true,
+    false
+  };
+
 
 /* IEEE quad precision format.  */
 
@@ -3395,9 +3432,12 @@ encode_ieee_quad (fmt, buf, r)
 	      image0 &= 0xffffffff;
 	      image2 &= 0xffffffff;
 	    }
-
-	  if (!fmt->qnan_msb_set)
-	    image3 ^= 1 << 15 | 1 << 14;
+	  if (r->signalling == fmt->qnan_msb_set)
+	    image3 &= ~0x8000;
+	  else
+	    image3 |= 0x8000;
+	  if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
+	    image3 |= 0x4000;
 	}
       else
 	{
@@ -3522,6 +3562,7 @@ decode_ieee_quad (fmt, r, buf)
 	{
 	  r->class = rvc_nan;
 	  r->sign = sign;
+	  r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set;
 
 	  if (HOST_BITS_PER_LONG == 32)
 	    {
@@ -3536,9 +3577,6 @@ decode_ieee_quad (fmt, r, buf)
 	      r->sig[1] = (image3 << 31 << 1) | image2;
 	    }
 	  lshift_significand (r, r, SIGNIFICAND_BITS - 113);
-
-	  if (!fmt->qnan_msb_set)
-	    r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
 	}
       else
 	{
@@ -3584,6 +3622,23 @@ const struct real_format ieee_quad_forma
     true,
     true,
     true
+  };
+
+const struct real_format mips_quad_format = 
+  {
+    encode_ieee_quad,
+    decode_ieee_quad,
+    2,
+    1,
+    113,
+    -16381,
+    16384,
+    127,
+    true,
+    true,
+    true,
+    true,
+    false
   };
 
 /* Descriptions of VAX floating point formats can be found beginning at
Index: real.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.h,v
retrieving revision 1.61
diff -c -p -d -u -r1.61 real.h
--- real.h	15 Jan 2003 17:40:26 -0000	1.61
+++ real.h	27 Mar 2003 01:23:42 -0000
@@ -35,7 +35,7 @@ enum real_value_class {
 };
 
 #define SIGNIFICAND_BITS	(128 + HOST_BITS_PER_LONG)
-#define EXP_BITS		(32 - 3)
+#define EXP_BITS		(32 - 4)
 #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))
@@ -44,6 +44,7 @@ struct real_value GTY(())
 {
   ENUM_BITFIELD (real_value_class) class : 2;
   unsigned int sign : 1;
+  unsigned int signalling : 1;
   signed int exp : EXP_BITS;
   unsigned long sig[SIGSZ];
 };
@@ -221,12 +222,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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]