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]

soft-fp: Support rsigned == 2 in _FP_TO_INT


Continuing the addition of soft-fp features in the Linux kernel
version, this patch adds _FP_TO_INT support for rsigned == 2 (reduce
overflowing results modulo 2^rsize to fit in the destination, used for
alpha emulation).  (This patch is relative to a tree with
<https://sourceware.org/ml/libc-alpha/2014-09/msg00411.html>,
<https://sourceware.org/ml/libc-alpha/2014-09/msg00442.html>,
<https://sourceware.org/ml/libc-alpha/2014-09/msg00461.html>,
<https://sourceware.org/ml/libc-alpha/2014-09/msg00463.html>,
<https://sourceware.org/ml/libc-alpha/2014-09/msg00464.html> and
<https://sourceware.org/ml/libc-alpha/2014-09/msg00488.html> applied;
there are actual dependencies on at least the fourth and fifth of
those patches.)

The kernel version is buggy; it can left shift by a negative amount
when right shifting is required in an overflow case (the kernel
version also has other bugs fixed long ago in glibc; at least,
spurious exceptions converting to the most negative integer).  This
version avoids that by handling overflow (other than to 0) for rsigned
== 2 along with the normal non-overflow case, which already properly
determines the direction in which to shift.

Tested for powerpc-nofpu.  Some functions get slightly bigger and some
get slightly smaller, no doubt as a result of the change to where in
the macro "inexact" is raised, but I don't think those changes are
significant.  Also tested for powerpc-nofpu with the relevant __fix*
functions changed to use rsigned == 2 (which is after all just as
valid as rsigned == 1 in IEEE terms), including verifying the results
and exceptions for various cases of conversions.

With these seven patches, the one remaining feature to add for the
soft-fp code to have all the features of the kernel version is
_FP_TO_INT_ROUND.

2014-09-23  Joseph Myers  <joseph@codesourcery.com>

	* soft-fp/op-common.h (_FP_TO_INT): Handle rsigned == 2.

diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index 3deb9b1..cab6fba 100644
--- a/soft-fp/op-common.h
+++ b/soft-fp/op-common.h
@@ -1390,6 +1390,8 @@
    1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not,
        NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
        depending on the sign in such case.
+   2:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not,
+       NV is set plus the result is reduced modulo 2^rsize.
    -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
        set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
        depending on the sign in such case.  */
@@ -1411,10 +1413,28 @@
 	  else								\
 	    FP_SET_EXCEPTION (FP_EX_INEXACT);				\
 	}								\
-      else if (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + rsize	\
-			 ? _FP_EXPMAX_##fs				\
-			 : _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s)) \
-	       || (!rsigned && X##_s))					\
+      else if (rsigned == 2						\
+	       && (X##_e						\
+		   >= ((_FP_EXPMAX_##fs					\
+			< _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + rsize - 1) \
+		       ? _FP_EXPMAX_##fs				\
+		       : _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + rsize - 1))) \
+	{								\
+	  /* Overflow resulting in 0.  */				\
+	  r = 0;							\
+	  FP_SET_EXCEPTION (FP_EX_INVALID				\
+			    | FP_EX_INVALID_CVI				\
+			    | ((FP_EX_INVALID_SNAN			\
+				&& _FP_ISSIGNAN (fs, wc, X))		\
+			       ? FP_EX_INVALID_SNAN			\
+			       : 0));					\
+	}								\
+      else if (rsigned != 2						\
+	       && (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + rsize	\
+			     ? _FP_EXPMAX_##fs				\
+			     : (_FP_EXPBIAS_##fs + rsize		\
+				- (rsigned > 0 || X##_s)))		\
+		   || (!rsigned && X##_s)))				\
 	{								\
 	  /* Overflow or converting to the most negative integer.  */	\
 	  if (rsigned)							\
@@ -1461,6 +1481,7 @@
 	}								\
       else								\
 	{								\
+	  int _FP_TO_INT_inexact = 0;					\
 	  _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs;		\
 	  if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1)	\
 	    {								\
@@ -1469,17 +1490,27 @@
 	    }								\
 	  else								\
 	    {								\
-	      int _FP_TO_INT_inexact;					\
 	      _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact,		\
 				  (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \
 				   - X##_e),				\
 				  _FP_FRACBITS_##fs);			\
-	      if (_FP_TO_INT_inexact)					\
-		FP_SET_EXCEPTION (FP_EX_INEXACT);			\
 	      _FP_FRAC_ASSEMBLE_##wc (r, X, rsize);			\
 	    }								\
 	  if (rsigned && X##_s)						\
 	    r = -r;							\
+	  if (rsigned == 2 && X##_e >= _FP_EXPBIAS_##fs + rsize - 1)	\
+	    {								\
+	      /* Overflow or converting to the most negative integer.  */ \
+	      if (X##_e > _FP_EXPBIAS_##fs + rsize - 1			\
+		  || !X##_s						\
+		  || r != (((typeof (r)) 1) << (rsize - 1)))		\
+		{							\
+		  _FP_TO_INT_inexact = 0;				\
+		  FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI);	\
+		}							\
+	    }								\
+	  if (_FP_TO_INT_inexact)					\
+	    FP_SET_EXCEPTION (FP_EX_INEXACT);				\
 	}								\
     }									\
   while (0)

-- 
Joseph S. Myers
joseph@codesourcery.com


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