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]

[ColdFire 31/63] Fix rounding problems in fpgnulib.c


This patch fixes two bugs in fpgnulib.c's __truncdfsf2.  First,
it was not rounding to nearest even; it was rounding halfway cases
towards infinity instead.  Second, it was not detecting overflow
in subnormal numbers (i.e. cases where a DFmode subnormal rounds
to FLT_MIN).

Richard


gcc/
200x-xx-xx  Nathan Sidwell  <nathan@codesourcery.com>

	* config/m68k/fpgnulib.c (__truncdfsf2): Implement round to
	nearest even, fix denormal rounding overflow.

Index: gcc/config/m68k/fpgnulib.c
===================================================================
--- gcc/config/m68k/fpgnulib.c	2007-01-09 15:02:03.000000000 +0000
+++ gcc/config/m68k/fpgnulib.c	2007-01-09 15:02:11.000000000 +0000
@@ -277,6 +277,8 @@ __truncdfsf2 (double a1)
   register long mant;
   register union float_long fl;
   register union double_long dl1;
+  int sticky;
+  int shift;
 
   dl1.d = a1;
 
@@ -288,29 +290,45 @@ __truncdfsf2 (double a1)
 
   exp = EXPD (dl1) - EXCESSD + EXCESS;
 
+  sticky = dl1.l.lower & ((1 << 22) - 1);
+  mant = MANTD (dl1);
   /* shift double mantissa 6 bits so we can round */
-  mant = MANTD (dl1) >> 6;
+  sticky |= mant & ((1 << 6) - 1);
+  mant >>= 6;
 
   /* Check for underflow and denormals.  */
   if (exp <= 0)
     {
       if (exp < -24)
-	mant = 0;
+	{
+	  sticky |= mant;
+	  mant = 0;
+	}
       else
-	mant >>= 1 - exp;
+	{
+	  sticky |= mant & ((1 << (1 - exp)) - 1);
+	  mant >>= 1 - exp;
+	}
       exp = 0;
     }
   
-  /* now round and shift down */
-  mant += 1;
-  mant >>= 1;
-
-  /* did the round overflow? */
-  if (mant & 0xFF000000L)
+  /* now round */
+  shift = 1;
+  if ((mant & 1) && (sticky || (mant & 2)))
     {
-      mant >>= 1;
-      exp++;
+      int rounding = exp ? 2 : 1;
+
+      mant += 1;
+
+      /* did the round overflow? */
+      if (mant >= (HIDDEN << rounding))
+	{
+	  exp++;
+	  shift = rounding;
+	}
     }
+  /* shift down */
+  mant >>= shift;
 
   mant &= ~HIDDEN;
 


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