]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libgcc/config/s390/32/_fixunssfdi.c
_fixdfdi.c: Throw invalid exception if number cannot be represented.
[thirdparty/gcc.git] / libgcc / config / s390 / 32 / _fixunssfdi.c
index eaaad9648d01a14d2199e5f17348795908047d51..7aeed28a0bdd78276f194425fdadf67cda0c76ad 100644 (file)
@@ -1,6 +1,5 @@
 /* Definitions of target machine for GNU compiler, for IBM S/390
-   Copyright (C) 1999, 2000, 2001, 2007, 2008 and 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1999-2014 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
                   Ulrich Weigand (uweigand@de.ibm.com).
 
@@ -25,11 +24,14 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#define EXP(fp)         (((fp.l) >> 23) & 0xFF)
-#define EXCESS          126
+#ifndef __s390x__
+
+#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)
 
@@ -44,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 */
@@ -56,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;
@@ -88,3 +111,4 @@ __fixunssfdi (float a1)
 
     return l;
 }
+#endif /* !__s390x__ */