summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog33
-rw-r--r--soft-fp/op-common.h35
-rw-r--r--soft-fp/soft-fp.h3
-rw-r--r--sysdeps/aarch64/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/alpha/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/arm/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/mips/mips64/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/mips/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/powerpc/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/sh/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/tile/sfp-machine.h2
13 files changed, 87 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ffdb54696c..a7dc412492 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2014-02-12  Joseph Myers  <joseph@codesourcery.com>
+
+	* soft-fp/op-common.h (_FP_DECL): Mark exponent as possibly
+	unused.
+	(_FP_PACK_SEMIRAW): Determine tininess based on rounding shifted
+	value if _FP_TININESS_AFTER_ROUNDING and unrounded value is in
+	subnormal range.
+	(_FP_PACK_CANONICAL): Determine tininess based on rounding to
+	normal precision if _FP_TININESS_AFTER_ROUNDING and unrounded
+	value has largest subnormal exponent.
+	* soft-fp/soft-fp.h [FP_NO_EXCEPTIONS]
+	(_FP_TININESS_AFTER_ROUNDING): Undefine and redefine to 0.
+	* sysdeps/aarch64/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): New macro.
+	* sysdeps/alpha/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): Likewise.
+	* sysdeps/arm/soft-fp/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
+	Likewise.
+	* sysdeps/mips/mips64/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): Likewise.
+	* sysdeps/mips/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): Likewise.
+	* sysdeps/powerpc/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): Likewise.
+	* sysdeps/sh/soft-fp/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
+	Likewise.
+	* sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): Likewise.
+	* sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+	(_FP_TININESS_AFTER_ROUNDING): Likewise.
+	* sysdeps/tile/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
+	Likewise.
+
 2014-02-12  Dylan Alex Simon  <dylan@dylex.net>
 
 	[BZ #16545]
diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index e901981b95..6f8c1f3cb0 100644
--- a/soft-fp/op-common.h
+++ b/soft-fp/op-common.h
@@ -32,7 +32,7 @@
 #define _FP_DECL(wc, X)				\
   _FP_I_TYPE X##_c __attribute__ ((unused));	\
   _FP_I_TYPE X##_s __attribute__ ((unused));	\
-  _FP_I_TYPE X##_e;				\
+  _FP_I_TYPE X##_e __attribute__ ((unused));	\
   _FP_FRAC_DECL_##wc (X)
 
 /* Test whether the qNaN bit denotes a signaling NaN.  */
@@ -191,8 +191,22 @@
 #define _FP_PACK_SEMIRAW(fs, wc, X)				\
   do								\
     {								\
+      int _FP_PACK_SEMIRAW_is_tiny				\
+	= X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X);		\
+      if (_FP_TININESS_AFTER_ROUNDING				\
+	  && _FP_PACK_SEMIRAW_is_tiny)				\
+	{							\
+	  FP_DECL_##fs (_FP_PACK_SEMIRAW_T);			\
+	  _FP_FRAC_COPY_##wc (_FP_PACK_SEMIRAW_T, X);		\
+	  _FP_PACK_SEMIRAW_T##_s = X##_s;			\
+	  _FP_PACK_SEMIRAW_T##_e = X##_e;			\
+	  _FP_FRAC_SLL_##wc (_FP_PACK_SEMIRAW_T, 1);		\
+	  _FP_ROUND (wc, _FP_PACK_SEMIRAW_T);			\
+	  if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_SEMIRAW_T))	\
+	    _FP_PACK_SEMIRAW_is_tiny = 0;			\
+	}							\
       _FP_ROUND (wc, X);					\
-      if (X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X))		\
+      if (_FP_PACK_SEMIRAW_is_tiny)				\
 	{							\
 	  if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)		\
 	      || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))	\
@@ -279,6 +293,17 @@
 	  else								\
 	    {								\
 	      /* we've got a denormalized number */			\
+	      int _FP_PACK_CANONICAL_is_tiny = 1;			\
+	      if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0)		\
+		{							\
+		  FP_DECL_##fs (_FP_PACK_CANONICAL_T);			\
+		  _FP_FRAC_COPY_##wc (_FP_PACK_CANONICAL_T, X);		\
+		  _FP_PACK_CANONICAL_T##_s = X##_s;			\
+		  _FP_PACK_CANONICAL_T##_e = X##_e;			\
+		  _FP_ROUND (wc, _FP_PACK_CANONICAL_T);			\
+		  if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_CANONICAL_T))	\
+		    _FP_PACK_CANONICAL_is_tiny = 0;			\
+		}							\
 	      X##_e = -X##_e + 1;					\
 	      if (X##_e <= _FP_WFRACBITS_##fs)				\
 		{							\
@@ -296,8 +321,10 @@
 		      X##_e = 0;					\
 		      _FP_FRAC_SRL_##wc (X, _FP_WORKBITS);		\
 		    }							\
-		  if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)		\
-		      || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))	\
+		  if (_FP_PACK_CANONICAL_is_tiny			\
+		      && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)		\
+			  || (FP_TRAPPING_EXCEPTIONS			\
+			      & FP_EX_UNDERFLOW)))			\
 		    FP_SET_EXCEPTION (FP_EX_UNDERFLOW);			\
 		}							\
 	      else							\
diff --git a/soft-fp/soft-fp.h b/soft-fp/soft-fp.h
index c8a98948f8..8d0efa58e7 100644
--- a/soft-fp/soft-fp.h
+++ b/soft-fp/soft-fp.h
@@ -161,6 +161,9 @@
 # undef FP_ROUNDMODE
 # define FP_ROUNDMODE FP_RND_ZERO
 
+# undef _FP_TININESS_AFTER_ROUNDING
+# define _FP_TININESS_AFTER_ROUNDING 0
+
 #endif
 
 #define _FP_ROUND_NEAREST(wc, X)				\
diff --git a/sysdeps/aarch64/soft-fp/sfp-machine.h b/sysdeps/aarch64/soft-fp/sfp-machine.h
index 9bb94e5ccc..3e969952fa 100644
--- a/sysdeps/aarch64/soft-fp/sfp-machine.h
+++ b/sysdeps/aarch64/soft-fp/sfp-machine.h
@@ -60,6 +60,8 @@
 #define FP_EX_DIVZERO		FE_DIVBYZERO
 #define FP_EX_INEXACT		FE_INEXACT
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #define FP_INIT_ROUNDMODE			\
 do {						\
   _FPU_GETCW (_fcw);				\
diff --git a/sysdeps/alpha/soft-fp/sfp-machine.h b/sysdeps/alpha/soft-fp/sfp-machine.h
index cceccafe26..e11a8dd7ca 100644
--- a/sysdeps/alpha/soft-fp/sfp-machine.h
+++ b/sysdeps/alpha/soft-fp/sfp-machine.h
@@ -74,6 +74,8 @@
 #define FP_EX_DIVZERO		FE_DIVBYZERO
 #define FP_EX_INEXACT		FE_INEXACT
 
+#define _FP_TININESS_AFTER_ROUNDING 1
+
 #define FP_INIT_ROUNDMODE					\
 do {								\
   if (__builtin_expect (_round == 4, 0))			\
diff --git a/sysdeps/arm/soft-fp/sfp-machine.h b/sysdeps/arm/soft-fp/sfp-machine.h
index eba6e35ced..52a08b5298 100644
--- a/sysdeps/arm/soft-fp/sfp-machine.h
+++ b/sysdeps/arm/soft-fp/sfp-machine.h
@@ -47,3 +47,5 @@
       }								\
     R##_c = FP_CLS_NAN;						\
   } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0
diff --git a/sysdeps/mips/mips64/soft-fp/sfp-machine.h b/sysdeps/mips/mips64/soft-fp/sfp-machine.h
index 5be50927d0..708afc783e 100644
--- a/sysdeps/mips/mips64/soft-fp/sfp-machine.h
+++ b/sysdeps/mips/mips64/soft-fp/sfp-machine.h
@@ -77,6 +77,8 @@
 #define FP_EX_DIVZERO		FE_DIVBYZERO
 #define FP_EX_INEXACT		FE_INEXACT
 
+#define _FP_TININESS_AFTER_ROUNDING 1
+
 #ifdef __mips_hard_float
 #define FP_INIT_ROUNDMODE			\
 do {						\
diff --git a/sysdeps/mips/soft-fp/sfp-machine.h b/sysdeps/mips/soft-fp/sfp-machine.h
index fff3b3c613..4e23aa8b26 100644
--- a/sysdeps/mips/soft-fp/sfp-machine.h
+++ b/sysdeps/mips/soft-fp/sfp-machine.h
@@ -64,3 +64,5 @@
 #define FP_EX_OVERFLOW          (1 << 2)
 #define FP_EX_UNDERFLOW         (1 << 1)
 #define FP_EX_INEXACT           (1 << 0)
+
+#define _FP_TININESS_AFTER_ROUNDING 1
diff --git a/sysdeps/powerpc/soft-fp/sfp-machine.h b/sysdeps/powerpc/soft-fp/sfp-machine.h
index 35a38b0031..d92a90e3e2 100644
--- a/sysdeps/powerpc/soft-fp/sfp-machine.h
+++ b/sysdeps/powerpc/soft-fp/sfp-machine.h
@@ -41,6 +41,8 @@
     R##_c = FP_CLS_NAN;						\
   } while (0)
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #if defined __NO_FPRS__ && !defined _SOFT_FLOAT
 
 /* Exception flags.  We use the bit positions of the appropriate bits
diff --git a/sysdeps/sh/soft-fp/sfp-machine.h b/sysdeps/sh/soft-fp/sfp-machine.h
index 9b9074860f..81474e8a7c 100644
--- a/sysdeps/sh/soft-fp/sfp-machine.h
+++ b/sysdeps/sh/soft-fp/sfp-machine.h
@@ -53,3 +53,5 @@
 #define FP_EX_OVERFLOW          (1 << 4)
 #define FP_EX_UNDERFLOW         (1 << 3)
 #define FP_EX_INEXACT           (1 << 2)
+
+#define _FP_TININESS_AFTER_ROUNDING 1
diff --git a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
index 025b3ab196..b6baa8185f 100644
--- a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
@@ -185,6 +185,8 @@
 #define FP_EX_DIVZERO		(1 << 1)
 #define FP_EX_INEXACT		(1 << 0)
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #define _FP_DECL_EX \
   fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
 
diff --git a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
index 9a0384b1d8..80c1ac5d52 100644
--- a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
@@ -93,6 +93,8 @@ do {								\
 #define FP_EX_DIVZERO		(1 << 1)
 #define FP_EX_INEXACT		(1 << 0)
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #define _FP_DECL_EX \
   fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
 
diff --git a/sysdeps/tile/sfp-machine.h b/sysdeps/tile/sfp-machine.h
index ff8beeffa7..7a1993ea61 100644
--- a/sysdeps/tile/sfp-machine.h
+++ b/sysdeps/tile/sfp-machine.h
@@ -95,3 +95,5 @@
       }								\
     R##_c = FP_CLS_NAN;						\
   } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0