aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2007-01-18 19:49:59 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2007-01-18 19:49:59 +0000
commite444d54e44e4ac836ee2f78dd5bddf75a1c2b95f (patch)
treedd09592ee23041e2582c2bbdf6b2f384cb0efdc5
parent17e143a1730125d9630c8fb1b0ec9a334330a1c0 (diff)
downloadgcc-e444d54e44e4ac836ee2f78dd5bddf75a1c2b95f.zip
gcc-e444d54e44e4ac836ee2f78dd5bddf75a1c2b95f.tar.gz
gcc-e444d54e44e4ac836ee2f78dd5bddf75a1c2b95f.tar.bz2
200x-xx-xx Nathan Sidwell <nathan@codesourcery.com>
gcc/ 200x-xx-xx Nathan Sidwell <nathan@codesourcery.com> * config/m68k/fpgnulib.c (__truncdfsf2): Implement round to nearest even, fix denormal rounding overflow. From-SVN: r120925
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/m68k/fpgnulib.c40
2 files changed, 34 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4f4801b..4d95624 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/m68k/fpgnulib.c b/gcc/config/m68k/fpgnulib.c
index cbff918..2a7f6c7 100644
--- a/gcc/config/m68k/fpgnulib.c
+++ b/gcc/config/m68k/fpgnulib.c
@@ -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;