summaryrefslogtreecommitdiff
path: root/libgcc/config/s390/32/_fixsfdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/config/s390/32/_fixsfdi.c')
-rw-r--r--libgcc/config/s390/32/_fixsfdi.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/libgcc/config/s390/32/_fixsfdi.c b/libgcc/config/s390/32/_fixsfdi.c
index dbf40b43a72..99f91a7051a 100644
--- a/libgcc/config/s390/32/_fixsfdi.c
+++ b/libgcc/config/s390/32/_fixsfdi.c
@@ -26,13 +26,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef __s390x__
-#define EXP(fp) (((fp.l) >> 23) & 0xFF)
-#define EXCESS 126
+#define EXPONENT_BIAS 127
+#define MANTISSA_BITS 23
+#define EXP(fp) (((fp.l) >> MANTISSA_BITS) & 0xFF)
+#define PRECISION (MANTISSA_BITS + 1)
#define SIGNBIT 0x80000000
#define SIGN(fp) ((fp.l) & SIGNBIT)
-#define HIDDEN (1 << 23)
+#define HIDDEN (1 << MANTISSA_BITS)
#define MANT(fp) (((fp.l) & 0x7FFFFF) | HIDDEN)
#define FRAC(fp) ((fp.l) & 0x7FFFFF)
+#define LLONG_MAX 9223372036854775807LL
+#define LLONG_MIN (-LLONG_MAX - 1LL)
typedef int DItype_x __attribute__ ((mode (DI)));
typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
@@ -45,6 +49,12 @@ union float_long
USItype_x l;
};
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+ __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) );
+}
+
DItype_x __fixsfdi (float a1);
/* convert double to int */
@@ -58,32 +68,34 @@ __fixsfdi (float a1)
fl1.f = a1;
/* +/- 0, denormalized */
-
if (!EXP (fl1))
return 0;
- exp = EXP (fl1) - EXCESS - 24;
+ exp = EXP (fl1) - EXPONENT_BIAS - MANTISSA_BITS;
/* number < 1 */
-
- if (exp < -24)
+ if (exp <= -PRECISION)
return 0;
/* NaN */
- if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
- return 0x8000000000000000ULL;
+ if ((EXP (fl1) == 0xff) && (FRAC (fl1) != 0)) /* NaN */
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0x8000000000000000ULL;
+ }
/* Number big number & +/- inf */
-
- if (exp >= 40) {
- l = (long long)1<<63;
- if (!SIGN(fl1))
- l--;
- return l;
+ if (exp >= 40) {
+ /* Don't throw an exception for -1p+63 */
+ if (!SIGN (fl1) || exp > 40 || FRAC (fl1) != 0)
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return SIGN (fl1) ? LLONG_MIN : LLONG_MAX;
}
- l = MANT(fl1);
+ l = MANT (fl1);
if (exp > 0)
l <<= exp;