]> 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>
Thu, 31 Jan 2008 12:15:50 +0000 (12:15 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Thu, 31 Jan 2008 12:15:50 +0000 (12:15 +0000)
2008-01-31  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-31  Andreas Krebbel  <krebbel1@de.ibm.com>

* gcc.dg/tf_to_di-1.c: New testcase.

From-SVN: r131977

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

index 8500416db3790a57060099f4b3120b3ca2f6c979..405c00155253e45b8dd5e1a60c0f1fbd79950e5a 100644 (file)
@@ -1,3 +1,10 @@
+2008-01-31  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-24  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        Backport:
index fd12243a381dfd3349bf90e2a52e7394935a0304..95a5eef0173790b9b5fc6c335e0876ecf3291a8f 100644 (file)
@@ -78,13 +78,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 to 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));
 
@@ -118,7 +120,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);
@@ -150,17 +152,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 to 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 = (long long)1 << 63; /* long long int 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 c1886f900e38a8bdef5cfbecec7df699cef00052..b00692a5553635bbf934a4d787017b50c973c192 100644 (file)
@@ -1,3 +1,7 @@
+2008-01-31  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * gcc.dg/tf_to_di-1.c: New testcase.
+
 2008-01-24  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        Backport:
diff --git a/gcc/testsuite/gcc.dg/tf_to_di-1.c b/gcc/testsuite/gcc.dg/tf_to_di-1.c
new file mode 100644 (file)
index 0000000..f4f478a
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do run { target s390*-*-* } } */
+/* { 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;
+}