]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Jan 2007 19:49:59 +0000 (19:49 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Jan 2007 19:49:59 +0000 (19:49 +0000)
200x-xx-xx  Nathan Sidwell  <nathan@codesourcery.com>

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120925 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m68k/fpgnulib.c

index 4f4801b7826b8d2b89ae71d5f33e965815d90c97..4d95624c9b49e4198afef4e20fbc20a1292fbf4f 100644 (file)
@@ -1,3 +1,8 @@
+2007-01-18  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * config/m68k/fpgnulib.c (__truncdfsf2): Implement round to
+       nearest even, fix denormal rounding overflow.
+
 2007-01-18  Richard Sandiford  <richard@codesourcery.com>
 
        * config/m68k/m68k.md (movsf_cf_hard): Use fsmove instead of
index cbff9184abfc6f561ae483a7ddc3a9cb99034754..2a7f6c75d11ac7c60d2df29a0400c353254e78a9 100644 (file)
@@ -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;