aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel1@de.ibm.com>2008-01-30 08:00:51 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2008-01-30 08:00:51 +0000
commit393c005884c547ee6d4cebb2fb938e6214714e9e (patch)
tree4acc05569093f04c2196aa7a4d7d564d139579f1
parenta99d95a270cabbbf43024c32ac6225da13e4aad1 (diff)
downloadgcc-393c005884c547ee6d4cebb2fb938e6214714e9e.zip
gcc-393c005884c547ee6d4cebb2fb938e6214714e9e.tar.gz
gcc-393c005884c547ee6d4cebb2fb938e6214714e9e.tar.bz2
fixdfdi.h (__fixunstfdi, __fixtfdi): Rearrange the overflow check to make it easier to read.
2008-01-30 Andreas Krebbel <krebbel1@de.ibm.com> * config/s390/fixdfdi.h (__fixunstfdi, __fixtfdi): Rearrange the overflow check to make it easier to read. (__fixtfdi): Change the type of the ll member in union long_double to UDItype_x. 2008-01-30 Andreas Krebbel <krebbel1@de.ibm.com> * gcc.target/s390/tf_to_di-1.c: New testcase. From-SVN: r131957
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/s390/fixdfdi.h34
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/s390/tf_to_di-1.c46
4 files changed, 77 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 45021464..176a137 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2008-01-30 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * config/s390/fixdfdi.h (__fixunstfdi, __fixtfdi): Rearrange
+ the overflow check to make it easier to read.
+ (__fixtfdi): Change the type of the ll member in union
+ long_double to UDItype_x.
+
2008-01-30 Jakub Jelinek <jakub@redhat.com>
PR middle-end/34969
diff --git a/gcc/config/s390/fixdfdi.h b/gcc/config/s390/fixdfdi.h
index f3e48ac..865bf46 100644
--- a/gcc/config/s390/fixdfdi.h
+++ b/gcc/config/s390/fixdfdi.h
@@ -77,13 +77,15 @@ __fixunstfdi (long double a1)
if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
return 0x0ULL;
- /* If the upper ll part of the mantissa isn't
- zeroed out after shifting the number would be to large. */
- if (exp >= -HIGH_LL_FRAC_BITS)
- return 0xFFFFFFFFFFFFFFFFULL;
-
+ /* One extra bit is needed for the unit bit which is appended by
+ MANTD_HIGH_LL on the left of the matissa. */
exp += HIGH_LL_FRAC_BITS + 1;
+ /* If the result would still need a left shift it will be too large
+ to be represented. */
+ if (exp > 0)
+ return 0xFFFFFFFFFFFFFFFFULL;
+
l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
| MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
@@ -117,7 +119,7 @@ union double_long {
struct {
SItype_x i[4]; /* 32 bit parts: 0 upper ... 3 lowest */
} l;
- DItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */
+ UDItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */
};
DItype_x __fixtfdi (long double a1);
@@ -136,7 +138,7 @@ __fixtfdi (long double a1)
if (!EXPD (dl1))
return 0;
- /* The exponent - considered the binary point at the right end of
+ /* The exponent - considered the binary point at the right end of
the mantissa. */
exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
@@ -149,17 +151,21 @@ __fixtfdi (long double a1)
if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
return 0x8000000000000000ULL;
- /* If the upper ll part of the mantissa isn't
- zeroed out after shifting the number would be to large. */
- if (exp >= -HIGH_LL_FRAC_BITS)
+ /* One extra bit is needed for the unit bit which is appended by
+ MANTD_HIGH_LL on the left of the matissa. */
+ exp += HIGH_LL_FRAC_BITS + 1;
+
+ /* If the result would still need a left shift it will be too large
+ to be represented. Compared to the unsigned variant we have to
+ take care that there is still space for the sign bit to be
+ applied. So we can only go on if there is a right-shift by one
+ or more. */
+ if (exp >= 0)
{
- l = (long long)1 << 63; /* long int min */
+ l = 1ULL << 63; /* long long min */
return SIGND (dl1) ? l : l - 1;
}
- /* The extra bit is needed for the sign bit. */
- exp += HIGH_LL_FRAC_BITS + 1;
-
l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
| MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9c21887..3cee20a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2008-01-30 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * gcc.target/s390/tf_to_di-1.c: New testcase.
+
2008-01-30 Paul Thomas <pault@gcc.gnu.org>
PR fortran/34975
diff --git a/gcc/testsuite/gcc.target/s390/tf_to_di-1.c b/gcc/testsuite/gcc.target/s390/tf_to_di-1.c
new file mode 100644
index 0000000..d79e6f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/tf_to_di-1.c
@@ -0,0 +1,46 @@
+/* { dg-options "-O0 -mlong-double-128" } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+check_ll (long double ld, long long ll)
+{
+ if ((long long)ld != ll)
+ {
+ printf ("ld: %Lf expect: %lld result: %lld\n",
+ ld, ll, (long long)ld);
+ abort ();
+ }
+}
+
+void
+check_ull (long double ld, unsigned long long ull)
+{
+ if ((unsigned long long)ld != ull)
+ {
+ printf ("ld: %Lf expect: %llu result: %llu\n",
+ ld, ull, (unsigned long long)ld);
+ abort ();
+ }
+}
+
+int
+main ()
+{
+ const long long ll_max = (long long)((1ULL << 63) - 1);
+ const long long ll_min = -ll_max - 1;
+
+ check_ll (206.23253, 206LL);
+ check_ull (206.23253, 206ULL);
+ check_ll ((long double)ll_max, ll_max);
+ check_ull ((long double)ll_max, ll_max);
+ check_ll ((long double)ll_min, ll_min);
+ check_ll (0.0, 0);
+ check_ull (0.0, 0);
+ check_ll (-1.0, -1);
+ check_ll ((long double)0xffffffffffffffffULL, ll_max);
+ check_ull ((long double)0xffffffffffffffffULL, 0xffffffffffffffffULL);
+
+ return 0;
+}