]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fixdfdi.h (__fixunstfdi, __fixtfdi): Rearrange the overflow check to make it easier...
authorAndreas Krebbel <krebbel1@de.ibm.com>
Wed, 30 Jan 2008 08:00:51 +0000 (08:00 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Wed, 30 Jan 2008 08:00:51 +0000 (08:00 +0000)
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

gcc/ChangeLog
gcc/config/s390/fixdfdi.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/tf_to_di-1.c [new file with mode: 0644]

index 450214646c1ab84fa46eda5111f30307b3180ea5..176a1372e662353b13ec27e37694817adf4e7221 100644 (file)
@@ -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
index f3e48ac8f9d992f5f6d1091570a46a53e081fa47..865bf46b99fa4e68da9df7f13d6dc5296d292e95 100644 (file)
@@ -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));
 
index 9c218875da701da618441be4f7e77351223f078d..3cee20a403ccdffbaffa4009b9bf36f663489dfe 100644 (file)
@@ -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 (file)
index 0000000..d79e6f3
--- /dev/null
@@ -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;
+}