summaryrefslogtreecommitdiffstats
path: root/libgcc/config
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2014-02-07 10:14:24 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2014-02-07 10:14:24 +0000
commitfc1cd0120e978d0f7155b5a2058e460fd078c0b0 (patch)
treebd57e14f45de42cc9484512765bf1e00c671e867 /libgcc/config
parentbe2c7f8f8bace931b3c47d28f07c8f0eb6f8f9dd (diff)
downloadppe42-gcc-fc1cd0120e978d0f7155b5a2058e460fd078c0b0.tar.gz
ppe42-gcc-fc1cd0120e978d0f7155b5a2058e460fd078c0b0.zip
2014-02-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* config/s390/32/_fixdfdi.c: Throw invalid exception if number cannot be represented. * config/s390/32/_fixsfdi.c: Likewise. * config/s390/32/_fixtfdi.c: Likewise. * config/s390/32/_fixunsdfdi.c: Likewise. * config/s390/32/_fixunssfdi.c: Likewise. * config/s390/32/_fixunstfdi.c: Likewise. 2014-02-07 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> * gcc.target/s390/fp2int1.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207596 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc/config')
-rw-r--r--libgcc/config/s390/32/_fixdfdi.c42
-rw-r--r--libgcc/config/s390/32/_fixsfdi.c44
-rw-r--r--libgcc/config/s390/32/_fixtfdi.c28
-rw-r--r--libgcc/config/s390/32/_fixunsdfdi.c46
-rw-r--r--libgcc/config/s390/32/_fixunssfdi.c50
-rw-r--r--libgcc/config/s390/32/_fixunstfdi.c37
6 files changed, 181 insertions, 66 deletions
diff --git a/libgcc/config/s390/32/_fixdfdi.c b/libgcc/config/s390/32/_fixdfdi.c
index b1ba06d7335..e6dd4d11441 100644
--- a/libgcc/config/s390/32/_fixdfdi.c
+++ b/libgcc/config/s390/32/_fixdfdi.c
@@ -27,12 +27,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef __s390x__
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
-#define EXCESSD 1022
+#define EXPONENT_BIAS 1023
+#define MANTISSA_BITS 52
+#define PRECISION (MANTISSA_BITS + 1)
#define SIGNBIT 0x80000000
-#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
+#define SIGN(fp) ((fp.l.upper) & SIGNBIT)
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
#define FRACD_LL(fp) (fp.ll & (HIDDEND_LL-1))
-#define HIDDEND_LL ((UDItype_x)1 << 52)
+#define HIDDEND_LL ((UDItype_x)1 << MANTISSA_BITS)
+#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)));
@@ -48,6 +52,12 @@ union double_long {
UDItype_x ll;
};
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+ __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) );
+}
+
DItype_x __fixdfdi (double a1);
/* convert double to int */
@@ -61,29 +71,33 @@ __fixdfdi (double a1)
dl1.d = a1;
/* +/- 0, denormalized */
-
if (!EXPD (dl1))
return 0;
- exp = EXPD (dl1) - EXCESSD - 53;
+ /* The exponent - considered the binary point at the right end of
+ the mantissa. */
+ exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
/* number < 1 */
-
- if (exp < -53)
+ if (exp <= -PRECISION)
return 0;
/* NaN */
if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
- return 0x8000000000000000ULL;
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0x8000000000000000ULL;
+ }
/* Number big number & +/- inf */
-
if (exp >= 11) {
- l = (long long)1<<63;
- if (!SIGND(dl1))
- l--;
- return l;
+ /* Don't throw an exception for -1p+63 */
+ if (!SIGN (dl1) || exp > 11 || FRACD_LL (dl1) != 0)
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return SIGN (dl1) ? LLONG_MIN : LLONG_MAX;
}
l = MANTD_LL(dl1);
@@ -94,6 +108,6 @@ __fixdfdi (double a1)
else
l >>= -exp;
- return (SIGND (dl1) ? -l : l);
+ return (SIGN (dl1) ? -l : l);
}
#endif /* !__s390x__ */
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;
diff --git a/libgcc/config/s390/32/_fixtfdi.c b/libgcc/config/s390/32/_fixtfdi.c
index 50b6c9b46ac..de84972a22a 100644
--- a/libgcc/config/s390/32/_fixtfdi.c
+++ b/libgcc/config/s390/32/_fixtfdi.c
@@ -31,13 +31,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define MANTISSA_BITS 112
#define PRECISION (MANTISSA_BITS + 1)
#define SIGNBIT 0x80000000
-#define SIGND(fp) ((fp.l.i[0]) & SIGNBIT)
+#define SIGN(fp) ((fp.l.i[0]) & SIGNBIT)
#define MANTD_HIGH_LL(fp) ((fp.ll[0] & HIGH_LL_FRAC_MASK) | HIGH_LL_UNIT_BIT)
#define MANTD_LOW_LL(fp) (fp.ll[1])
#define FRACD_ZERO_P(fp) (!fp.ll[1] && !(fp.ll[0] & HIGH_LL_FRAC_MASK))
#define HIGH_LL_FRAC_BITS 48
#define HIGH_LL_UNIT_BIT ((UDItype_x)1 << HIGH_LL_FRAC_BITS)
#define HIGH_LL_FRAC_MASK (HIGH_LL_UNIT_BIT - 1)
+#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)));
@@ -52,6 +54,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) );
+}
+
DItype_x __fixtfdi (long double a1);
/* convert double to unsigned int */
@@ -79,7 +87,11 @@ __fixtfdi (long double a1)
/* NaN: All exponent bits set and a nonzero fraction. */
if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
- return 0x8000000000000000ULL;
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0x8000000000000000ULL;
+ }
/* One extra bit is needed for the unit bit which is appended by
MANTD_HIGH_LL on the left of the matissa. */
@@ -92,13 +104,19 @@ __fixtfdi (long double a1)
or more. */
if (exp >= 0)
{
- l = 1ULL << 63; /* long long min */
- return SIGND (dl1) ? l : l - 1;
+ /* Don't throw an exception for -1p+63 */
+ if (!SIGN (dl1)
+ || exp > 0
+ || MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
+ || (dl1.ll[0] & HIGH_LL_FRAC_MASK))
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return SIGN (dl1) ? LLONG_MIN : LLONG_MAX;
}
l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
| MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
- return SIGND (dl1) ? -(l >> -exp) : l >> -exp;
+ return SIGN (dl1) ? -(l >> -exp) : l >> -exp;
}
#endif /* !__s390x__ */
diff --git a/libgcc/config/s390/32/_fixunsdfdi.c b/libgcc/config/s390/32/_fixunsdfdi.c
index 84cc8bc1a38..0a249611a23 100644
--- a/libgcc/config/s390/32/_fixunsdfdi.c
+++ b/libgcc/config/s390/32/_fixunsdfdi.c
@@ -27,9 +27,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#ifndef __s390x__
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
-#define EXCESSD 1022
+#define EXPONENT_BIAS 1023
+#define MANTISSA_BITS 52
+#define PRECISION (MANTISSA_BITS + 1)
#define SIGNBIT 0x80000000
-#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
+#define SIGN(fp) ((fp.l.upper) & SIGNBIT)
#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
#define FRACD_LL(fp) (fp.ll & (HIDDEND_LL-1))
#define HIDDEND_LL ((UDItype_x)1 << 52)
@@ -48,6 +50,12 @@ union double_long {
UDItype_x ll;
};
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+ __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) );
+}
+
UDItype_x __fixunsdfdi (double a1);
/* convert double to unsigned int */
@@ -60,28 +68,44 @@ __fixunsdfdi (double a1)
dl1.d = a1;
- /* +/- 0, denormalized, negative */
-
- if (!EXPD (dl1) || SIGND(dl1))
+ /* +/- 0, denormalized */
+ if (!EXPD (dl1))
return 0;
- exp = EXPD (dl1) - EXCESSD - 53;
+ /* Negative. */
+ if (SIGN (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;
+ }
+
+ exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
/* number < 1 */
- if (exp < -53)
+ if (exp < -PRECISION)
return 0;
/* NaN */
if ((EXPD(dl1) == 0x7ff) && (FRACD_LL(dl1) != 0)) /* NaN */
- return 0x0ULL;
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0x0ULL;
+ }
/* Number big number & + inf */
- if (exp >= 12) {
- return 0xFFFFFFFFFFFFFFFFULL;
- }
+ if (exp >= 12)
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0xFFFFFFFFFFFFFFFFULL;
+ }
l = MANTD_LL(dl1);
diff --git a/libgcc/config/s390/32/_fixunssfdi.c b/libgcc/config/s390/32/_fixunssfdi.c
index aeb477a4ee8..7aeed28a0bd 100644
--- a/libgcc/config/s390/32/_fixunssfdi.c
+++ b/libgcc/config/s390/32/_fixunssfdi.c
@@ -26,11 +26,12 @@ 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 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)
@@ -45,6 +46,12 @@ union float_long
USItype_x l;
};
+static __inline__ void
+fexceptdiv (float d, float e)
+{
+ __asm__ __volatile__ ("debr %0,%1" : : "f" (d), "f" (e) );
+}
+
UDItype_x __fixunssfdi (float a1);
/* convert float to unsigned int */
@@ -57,30 +64,45 @@ __fixunssfdi (float a1)
fl1.f = a1;
- /* +/- 0, denormalized, negative */
-
- if (!EXP (fl1) || SIGN(fl1))
+ /* +/- 0, denormalized */
+ if (!EXP (fl1))
return 0;
- exp = EXP (fl1) - EXCESS - 24;
+ /* Negative. */
+ if (SIGN (fl1))
+ {
+ /* Value is <= -1.0
+ C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ if (EXP (fl1) >= EXPONENT_BIAS)
+ fexceptdiv (0.0, 0.0);
+ return 0;
+ }
- /* number < 1 */
+ exp = EXP (fl1) - EXPONENT_BIAS - MANTISSA_BITS;
+ /* number < 1 */
if (exp < -24)
return 0;
/* NaN */
- if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
- return 0x0ULL;
+ 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 0x0ULL;
+ }
/* Number big number & + inf */
- if (exp >= 41) {
- return 0xFFFFFFFFFFFFFFFFULL;
- }
+ if (exp >= 41)
+ {
+ /* C99 Annex F.4 requires an "invalid" exception to be thrown. */
+ fexceptdiv (0.0, 0.0);
+ return 0xFFFFFFFFFFFFFFFFULL;
+ }
- l = MANT(fl1);
+ l = MANT (fl1);
if (exp > 0)
l <<= exp;
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