This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix underflow and inexact signalling in soft-fp whenpacking.


This fixes the long double math testsuite regressions that started
showing up on Sparc with Joseph's recent change to check underflow.

The corresponding changes needed in glibc-ports for powerpc/nofp,
mips, and alpha should be pretty straightforward.

In the main glibc tree, sparc is the only consumer of this code.

Ok to commit?

	* soft-fp/op-common.h (_FP_PACK_CANONICAL): Only set underflow if
	the underflow exception is enabled and the non-zero result is
	tiny, or the non-zero result is tiny and there will be a loss of
	accuracy.  Set inexact if overflow is detected after rounding, but
	not if it is detected before.
	* soft-fp/soft-fp.h (FP_CUR_EXCEPTIONS): Define.
	(FP_TRAPPING_EXCEPTIONS): Provide default define.
	* sysdeps/sparc/sparc32/soft-fp/sfp-machine.h (_FP_DECL_EX):
	Initialize _fcw to zero.
	(FP_TRAPPING_EXCEPTIONS): Define.
	(FP_HANDLE_EXCEPTIONS): Add dummy use of _fcw.
	* sysdeps/sparc/sparc64/soft-fp/sfp-machine.h (_FP_DECL_EX):
	Initialize _fcw to zero.
	(FP_TRAPPING_EXCEPTIONS): Define.
	(FP_HANDLE_EXCEPTIONS): Add dummy use of _fcw.

diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index b70026f..4b0fd6c 100644
--- a/soft-fp/op-common.h
+++ b/soft-fp/op-common.h
@@ -220,7 +220,6 @@ do {								\
 	if (X##_e <= _FP_WFRACBITS_##fs)			\
 	  {							\
 	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
-	    _FP_ROUND(wc, X);					\
 	    if (_FP_FRAC_HIGH_##fs(X)				\
 		& (_FP_OVERFLOW_##fs >> 1))			\
 	      {							\
@@ -229,10 +228,23 @@ do {								\
 	      }							\
 	    else						\
 	      {							\
-		X##_e = 0;					\
-		_FP_FRAC_SRL_##wc(X, _FP_WORKBITS);		\
-		FP_SET_EXCEPTION(FP_EX_UNDERFLOW);		\
+		_FP_ROUND(wc, X);				\
+		if (_FP_FRAC_HIGH_##fs(X)			\
+		   & (_FP_OVERFLOW_##fs >> 1))			\
+		  {						\
+		    X##_e = 1;					\
+		    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
+		    FP_SET_EXCEPTION(FP_EX_INEXACT);		\
+		  }						\
+		else						\
+		  {						\
+		    X##_e = 0;					\
+		    _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);		\
+		  }						\
 	      }							\
+	    if ((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 46cb1cf..750c7fe 100644
--- a/soft-fp/soft-fp.h
+++ b/soft-fp/soft-fp.h
@@ -128,6 +128,13 @@
 #define FP_CLEAR_EXCEPTIONS				\
   _fex = 0
 
+#define FP_CUR_EXCEPTIONS				\
+  (_fex)
+
+#ifndef FP_TRAPPING_EXCEPTIONS
+#define FP_TRAPPING_EXCEPTIONS 0
+#endif
+
 #define _FP_ROUND_NEAREST(wc, X)			\
 do {							\
     if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND)	\
diff --git a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
index 8cdc7c2..fb8c723 100644
--- a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
@@ -184,18 +184,21 @@
 #define FP_EX_DIVZERO		(1 << 1)
 #define FP_EX_INEXACT		(1 << 0)
 
-#define _FP_DECL_EX	fpu_control_t _fcw
+#define _FP_DECL_EX	fpu_control_t _fcw = 0
 
 #define FP_INIT_ROUNDMODE					\
 do {								\
   _FPU_GETCW(_fcw);						\
 } while (0)
 
+#define FP_TRAPPING_EXCEPTIONS ((_fcw >> 23) & 0x1f)
+
 /* Simulate exceptions using double arithmetics. */
 extern double ___Q_simulate_exceptions(int exc);
 
 #define FP_HANDLE_EXCEPTIONS					\
 do {								\
+  (void) (_fcw);						\
   if (!_fex)							\
     {								\
       /* This is the common case, so we do it inline.		\
diff --git a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
index 7ec804d..1f10dbb 100644
--- a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
@@ -92,13 +92,14 @@ do {								\
 #define FP_EX_DIVZERO		(1 << 1)
 #define FP_EX_INEXACT		(1 << 0)
 
-#define _FP_DECL_EX	fpu_control_t _fcw
+#define _FP_DECL_EX	fpu_control_t _fcw = 0
 
 #define FP_INIT_ROUNDMODE					\
 do {								\
   _FPU_GETCW(_fcw);						\
 } while (0)
 
+#define FP_TRAPPING_EXCEPTIONS ((_fcw >> 23) & 0x1f)
 #define FP_INHIBIT_RESULTS ((_fcw >> 23) & _fex)
 
 /* Simulate exceptions using double arithmetics. */
@@ -106,6 +107,7 @@ extern double __Qp_handle_exceptions(int exc);
 
 #define FP_HANDLE_EXCEPTIONS					\
 do {								\
+  (void) (_fcw);						\
   if (!_fex)							\
     {								\
       /* This is the common case, so we do it inline.		\


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]