summaryrefslogtreecommitdiffstats
path: root/libgcc/config/s390/32/_fixunstfdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/config/s390/32/_fixunstfdi.c')
-rw-r--r--libgcc/config/s390/32/_fixunstfdi.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/libgcc/config/s390/32/_fixunstfdi.c b/libgcc/config/s390/32/_fixunstfdi.c
index 0e2c61fb270..2f90a5f2f16 100644
--- a/libgcc/config/s390/32/_fixunstfdi.c
+++ b/libgcc/config/s390/32/_fixunstfdi.c
@@ -52,6 +52,12 @@ union double_long {
UDItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */
};
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+ __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) );
+}
+
UDItype_x __fixunstfdi (long double a1);
/* convert double to unsigned int */
@@ -64,10 +70,20 @@ __fixunstfdi (long double a1)
dl1.d = a1;
- /* +/- 0, denormalized, negative */
- if (!EXPD (dl1) || SIGND(dl1))
+ /* +/- 0, denormalized */
+ if (!EXPD (dl1))
return 0;
+ /* Negative. */
+ if (SIGND (dl1))
+ {
+ /* Value is <= -1.0
+ C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ if (EXPD (dl1) >= EXPONENT_BIAS)
+ fexceptdiv (0.0, 0.0);
+ return 0;
+ }
+
/* The exponent - considered the binary point at the right end of
the mantissa. */
exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
@@ -80,16 +96,25 @@ __fixunstfdi (long double a1)
/* NaN: All exponent bits set and a nonzero fraction. */
if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
- return 0x0ULL;
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0;
+ }
/* 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 the result would still need a left shift it will be too
+ large to be represented. Infinities have all exponent bits set
+ and will end up here as well. */
if (exp > 0)
- return 0xFFFFFFFFFFFFFFFFULL;
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0xFFFFFFFFFFFFFFFFULL;
+ }
l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
| MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
OpenPOWER on IntegriCloud