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]

[middle-end, ColdFire 28/63] Change the canonical NaN representation


The NaNs generated by __builtin_nan() have a different significand to
the ones created by the ColdFire FPU.  __builtin_nan() sets the msb
(to indicate a quiet NaN) and clears the rest, whereas the FPU sets
every bit.

MIPS diverges from the norm in a different way.  On MIPS, quiet NaNs
have the msb clear and signalling NaNs have the msb set.  However,
in a canonical NaN, all other bits of significand will be set.

So we have the following canonical significands for quiet NaNs:

   Normal:   10000000....
   MIPS:     01111111....
   ColdFire: 11111111....

The problem is that both of the MIPS divergences (the inverted
sense of the msb, and canonical form of the lsbs) are controlled
by a single real_format flag.  This patch splits it into two and
creates new real_formats for ColdFire.  It fixes the ieee/copysign
test.

Note that the new formats are only chosen when using the ColdFire FPU.
We still want to use normal NaNs for soft float, at least until the
ColdFire libm libraries use the FPU encoding (if that ever happens).

The 68881 uses the same NaN encoding as ColdFire.  I don't know if
we want to do the same thing there or not; Andreas didn't seem too
keen when I mentioned the problem in a glibc context.

Richard


gcc/
	* real.h (real_format): Add a canonical_nan_lsbs_set field.
	(coldfire_single_format): Declare.
	(coldfire_double_format): Likewise.
	* real.c (encode_ieee_single): Use canonical_nan_lsbs_set instead
	of qnan_msb_set to determine the lower bits of a canonical
	NaN significand.
	(encode_ieee_double): Likewise.
	(encode_ieee_quad): Likewise.
	(ieee_single_format): Initialize canonical_nan_lsbs_set.
	(mips_single_format): Likewise.
	(ieee_double_format): Likewise.
	(mips_double_format): Likewise.
	(ieee_extended_motorola_format): Likewise.
	(ieee_extended_intel_96_format): Likewise.
	(ieee_extended_intel_128_format): Likewise.
	(ieee_extended_intel_96_round_53_format): Likewise.
	(ibm_extended_format): Likewise.
	(mips_extended_format): Likewise.
	(ieee_quad_format): Likewise.
	(mips_quad_format): Likewise.
	(vax_f_format): Likewise.
	(vax_d_format): Likewise.
	(vax_g_format): Likewise.
	(i370_single_format): Likewise.
	(i370_double_format): Likewise.
	(decimal_single_format): Likewise.
	(decimal_double_format): Likewise.
	(decimal_quad_format): Likewise.
	(c4x_single_format): Likewise.
	(c4x_extended_format): Likewise.
	(real_internal_format): Likewise.
	(coldfire_single_format): New real_format.
	(coldfire_double_format): Likewise.
	* config/pdp11/pdp11.c (pdp11_f_format): Initialize
	canonical_nan_lsbs_set.
	(pdp11_d_format): Likewise.
	* config/m68k/m68k.c (override_options): Override REAL_FORMAT_MODE
	if TARGET_COLDFIRE_CPU.

Index: gcc/real.h
===================================================================
--- gcc/real.h	2007-01-09 13:18:12.000000000 +0000
+++ gcc/real.h	2007-01-09 15:02:10.000000000 +0000
@@ -155,6 +155,7 @@ struct real_format
   bool has_denorm;
   bool has_signed_zero;
   bool qnan_msb_set;
+  bool canonical_nan_lsbs_set;
 };
 
 
@@ -255,8 +256,10 @@ extern unsigned int real_hash (const REA
 /* 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 coldfire_single_format;
 extern const struct real_format ieee_double_format;
 extern const struct real_format mips_double_format;
+extern const struct real_format coldfire_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_96_round_53_format;
Index: gcc/real.c
===================================================================
--- gcc/real.c	2007-01-09 13:18:12.000000000 +0000
+++ gcc/real.c	2007-01-09 15:02:10.000000000 +0000
@@ -2681,18 +2681,12 @@ encode_ieee_single (const struct real_fo
       if (fmt->has_nans)
 	{
 	  if (r->canonical)
-	    sig = 0;
+	    sig = (fmt->canonical_nan_lsbs_set ? (1 << 22) - 1 : 0);
 	  if (r->signalling == fmt->qnan_msb_set)
 	    sig &= ~(1 << 22);
 	  else
 	    sig |= 1 << 22;
-	  /* 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)
+	  if (sig == 0)
 	    sig = 1 << 21;
 
 	  image |= 255 << 23;
@@ -2787,7 +2781,8 @@ const struct real_format ieee_single_for
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 const struct real_format mips_single_format =
@@ -2806,9 +2801,29 @@ const struct real_format mips_single_for
     true,
     true,
     true,
-    false
+    false,
+    true
   };
 
+const struct real_format coldfire_single_format =
+  {
+    encode_ieee_single,
+    decode_ieee_single,
+    2,
+    1,
+    24,
+    24,
+    -125,
+    128,
+    31,
+    31,
+    true,
+    true,
+    true,
+    true,
+    true,
+    true
+  };
 
 /* IEEE double-precision format.  */
 
@@ -2860,21 +2875,23 @@ encode_ieee_double (const struct real_fo
       if (fmt->has_nans)
 	{
 	  if (r->canonical)
-	    sig_hi = sig_lo = 0;
+	    {
+	      if (fmt->canonical_nan_lsbs_set)
+		{
+		  sig_hi = (1 << 19) - 1;
+		  sig_lo = 0xffffffff;
+		}
+	      else
+		{
+		  sig_hi = 0;
+		  sig_lo = 0;
+		}
+	    }
 	  if (r->signalling == fmt->qnan_msb_set)
 	    sig_hi &= ~(1 << 19);
 	  else
 	    sig_hi |= 1 << 19;
-	  /* 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)
+	  if (sig_hi == 0 && sig_lo == 0)
 	    sig_hi = 1 << 18;
 
 	  image_hi |= 2047 << 20;
@@ -3012,7 +3029,8 @@ const struct real_format ieee_double_for
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 const struct real_format mips_double_format =
@@ -3031,9 +3049,29 @@ const struct real_format mips_double_for
     true,
     true,
     true,
-    false
+    false,
+    true
   };
 
+const struct real_format coldfire_double_format =
+  {
+    encode_ieee_double,
+    decode_ieee_double,
+    2,
+    1,
+    53,
+    53,
+    -1021,
+    1024,
+    63,
+    63,
+    true,
+    true,
+    true,
+    true,
+    true,
+    true
+  };
 
 /* IEEE extended real format.  This comes in three flavors: Intel's as
    a 12 byte image, Intel's as a 16 byte image, and Motorola's.  Intel
@@ -3361,7 +3399,8 @@ const struct real_format ieee_extended_m
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 const struct real_format ieee_extended_intel_96_format =
@@ -3380,7 +3419,8 @@ const struct real_format ieee_extended_i
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 const struct real_format ieee_extended_intel_128_format =
@@ -3399,7 +3439,8 @@ const struct real_format ieee_extended_i
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 /* The following caters to i386 systems that set the rounding precision
@@ -3420,7 +3461,8 @@ const struct real_format ieee_extended_i
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 /* IBM 128-bit extended precision format: a pair of IEEE double precision
@@ -3506,7 +3548,8 @@ const struct real_format ibm_extended_fo
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 const struct real_format mips_extended_format =
@@ -3525,7 +3568,8 @@ const struct real_format mips_extended_f
     true,
     true,
     true,
-    false
+    false,
+    true
   };
 
 
@@ -3575,8 +3619,11 @@ encode_ieee_quad (const struct real_form
 
 	  if (r->canonical)
 	    {
-	      /* Don't use bits from the significand.  The
-		 initialization above is right.  */
+	      if (fmt->canonical_nan_lsbs_set)
+		{
+		  image3 |= 0x7fff;
+		  image2 = image1 = image0 = 0xffffffff;
+		}
 	    }
 	  else if (HOST_BITS_PER_LONG == 32)
 	    {
@@ -3598,16 +3645,7 @@ encode_ieee_quad (const struct real_form
 	    image3 &= ~0x8000;
 	  else
 	    image3 |= 0x8000;
-	  /* 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)
+	  if (((image3 & 0xffff) | image2 | image1 | image0) == 0)
 	    image3 |= 0x4000;
 	}
       else
@@ -3792,7 +3830,8 @@ const struct real_format ieee_quad_forma
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 const struct real_format mips_quad_format =
@@ -3811,7 +3850,8 @@ const struct real_format mips_quad_forma
     true,
     true,
     true,
-    false
+    false,
+    true
   };
 
 /* Descriptions of VAX floating point formats can be found beginning at
@@ -4109,6 +4149,7 @@ const struct real_format vax_f_format =
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4128,6 +4169,7 @@ const struct real_format vax_d_format =
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4147,6 +4189,7 @@ const struct real_format vax_g_format =
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4323,6 +4366,7 @@ const struct real_format i370_single_for
     false,
     false, /* ??? The encoding does allow for "unnormals".  */
     false, /* ??? The encoding does allow for "unnormals".  */
+    false,
     false
   };
 
@@ -4342,6 +4386,7 @@ const struct real_format i370_double_for
     false,
     false, /* ??? The encoding does allow for "unnormals".  */
     false, /* ??? The encoding does allow for "unnormals".  */
+    false,
     false
   };
 
@@ -4416,7 +4461,8 @@ const struct real_format decimal_single_
     true,
     true,
     true, 
-    true
+    true,
+    false
   };
 
 /* Double precision decimal floating point (IEEE 754R). */
@@ -4436,7 +4482,8 @@ const struct real_format decimal_double_
     true,
     true,
     true,
-    true
+    true,
+    false
   };
 
 /* Quad precision decimal floating point (IEEE 754R). */
@@ -4456,7 +4503,8 @@ const struct real_format decimal_quad_fo
     true,
     true, 
     true, 
-    true
+    true,
+    false
   };
 
 /* The "twos-complement" c4x format is officially defined as
@@ -4665,6 +4713,7 @@ const struct real_format c4x_single_form
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4684,6 +4733,7 @@ const struct real_format c4x_extended_fo
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -4728,7 +4778,8 @@ const struct real_format real_internal_f
     true,
     false,
     true,
-    true
+    true,
+    false
   };
 
 /* Calculate the square root of X in mode MODE, and store the result
Index: gcc/config/pdp11/pdp11.c
===================================================================
--- gcc/config/pdp11/pdp11.c	2007-01-09 13:18:12.000000000 +0000
+++ gcc/config/pdp11/pdp11.c	2007-01-09 15:02:10.000000000 +0000
@@ -78,6 +78,7 @@ const struct real_format pdp11_f_format 
     false,
     false,
     false,
+    false,
     false
   };
 
@@ -96,6 +97,7 @@ const struct real_format pdp11_d_format 
     false,
     false,
     false,
+    false,
     false
   };
 
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	2007-01-09 15:02:09.000000000 +0000
+++ gcc/config/m68k/m68k.c	2007-01-09 15:02:10.000000000 +0000
@@ -536,6 +536,12 @@ override_options (void)
 	      : (m68k_cpu_flags & FL_COLDFIRE) != 0 ? FPUTYPE_COLDFIRE
 	      : FPUTYPE_68881);
 
+  if (TARGET_COLDFIRE_FPU)
+    {
+      REAL_MODE_FORMAT (SFmode) = &coldfire_single_format;
+      REAL_MODE_FORMAT (DFmode) = &coldfire_double_format;
+    }
+
   /* Sanity check to ensure that msep-data and mid-sahred-library are not
    * both specified together.  Doing so simply doesn't make sense.
    */


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