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));
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);
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;
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));
--- /dev/null
+/* { 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;
+}