summaryrefslogtreecommitdiff
path: root/gcc/libgcc2.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1994-06-02 22:10:30 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1994-06-02 22:10:30 +0000
commitb37ebc511b7ab572a581ec2e6d3c0851940b28de (patch)
treeef103607021237ec626056d60dc673a2b864e568 /gcc/libgcc2.c
parentc17b94a8b387896f8cee670b124dca0e24dc1633 (diff)
downloadgcc-b37ebc511b7ab572a581ec2e6d3c0851940b28de.tar.gz
(__floatdisf): Protect against double-rounding error.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7431 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r--gcc/libgcc2.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
index ad0dc16fe11..fc2e1ac64b4 100644
--- a/gcc/libgcc2.c
+++ b/gcc/libgcc2.c
@@ -1021,6 +1021,25 @@ __floatdidf (u)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
+#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+#define DF_SIZE 53
+#define SF_SIZE 24
+#else
+#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
+#define DF_SIZE 56
+#define SF_SIZE 24
+#else
+#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
+#define DF_SIZE 56
+#define SF_SIZE 24
+#else
+#define DF_SIZE 0
+#define SF_SIZE 0
+#endif
+#endif
+#endif
+
SFtype
__floatdisf (u)
@@ -1035,6 +1054,22 @@ __floatdisf (u)
if (u < 0)
u = -u, negate = 1;
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated in DFmode,
+ by a bit that won't be lost. The bit can go in anywhere below the
+ rounding position of the SFmode. A fixed mask and bit position
+ handles all usual configurations. It doesn't handle the case
+ of 128-bit DImode, however. */
+ if (DF_SIZE < DI_SIZE
+ && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
+ {
+#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
+ if (u >= ((UDItype) 1 << DF_SIZE))
+ {
+ if ((USItype) u & (REP_BIT - 1))
+ u |= REP_BIT;
+ }
+ }
f = (USItype) (u >> WORD_SIZE);
f *= HIGH_HALFWORD_COEFF;
f *= HIGH_HALFWORD_COEFF;