about summary refs log tree commit diff
path: root/soft-fp
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@codesourcery.com>2013-05-16 23:33:55 +0100
committerMaciej W. Rozycki <macro@codesourcery.com>2013-05-16 23:33:55 +0100
commit2848b105856e49d98f3c5026b6d8d790f9723c0c (patch)
tree66e6cc9d3c1c6d95324e50ceb1140d0eed52ec37 /soft-fp
parentc58b274f01658400ba75886b04cb044ba9467a94 (diff)
downloadglibc-2848b105856e49d98f3c5026b6d8d790f9723c0c.tar.gz
glibc-2848b105856e49d98f3c5026b6d8d790f9723c0c.tar.xz
glibc-2848b105856e49d98f3c5026b6d8d790f9723c0c.zip
MIPS: soft-fp NaN representation corrections
[BZ #15442] This adds support for the inverse interpretation of the
quiet bit of IEEE 754 floating-point NaN data that some processors
use.  This includes in particular MIPS architecture processors; the
payload used for the canonical qNaN encoding is updated accordingly
so as not to interfere with the quiet bit.
Diffstat (limited to 'soft-fp')
-rw-r--r--soft-fp/op-common.h57
-rw-r--r--soft-fp/testit.c8
2 files changed, 54 insertions, 11 deletions
diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index a9d94d7f16..8b73b58c52 100644
--- a/soft-fp/op-common.h
+++ b/soft-fp/op-common.h
@@ -35,6 +35,16 @@
   _FP_I_TYPE X##_e;				\
   _FP_FRAC_DECL_##wc(X)
 
+/* Test whether the qNaN bit denotes a signaling NaN.  */
+#define _FP_FRAC_SNANP(fs, X)						\
+  ((_FP_QNANNEGATEDP)							\
+   ? (_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)			\
+   : !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))
+#define _FP_FRAC_SNANP_SEMIRAW(fs, X)					\
+  ((_FP_QNANNEGATEDP)							\
+   ? (_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs)			\
+   : !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs))
+
 /*
  * Finish truely unpacking a native fp value by classifying the kind
  * of fp value and normalizing both the exponent and the fraction.
@@ -74,7 +84,7 @@ do {									\
       {									\
 	X##_c = FP_CLS_NAN;						\
 	/* Check for signaling NaN */					\
-	if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))		\
+	if (_FP_FRAC_SNANP(fs, X))					\
 	  FP_SET_EXCEPTION(FP_EX_INVALID);				\
       }									\
     break;								\
@@ -112,7 +122,7 @@ do {							\
 do {								\
   if (X##_e == _FP_EXPMAX_##fs					\
       && !_FP_FRAC_ZEROP_##wc(X)				\
-      && !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs))	\
+      && _FP_FRAC_SNANP_SEMIRAW(fs, X))				\
     FP_SET_EXCEPTION(FP_EX_INVALID);				\
 } while (0)
 
@@ -127,6 +137,39 @@ do {									\
   _FP_FRAC_SLL_##wc(R, _FP_WORKBITS);					\
 } while (0)
 
+/* Make the fractional part a quiet NaN, preserving the payload
+   if possible, otherwise make it the canonical quiet NaN and set
+   the sign bit accordingly.  */
+#define _FP_SETQNAN(fs, wc, X)						\
+do {									\
+  if (_FP_QNANNEGATEDP)							\
+    {									\
+      _FP_FRAC_HIGH_RAW_##fs(X) &= _FP_QNANBIT_##fs - 1;		\
+      if (_FP_FRAC_ZEROP_##wc(X))					\
+	{								\
+	  X##_s = _FP_NANSIGN_##fs;					\
+	  _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
+	}								\
+    }									\
+  else									\
+    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;			\
+} while (0)
+#define _FP_SETQNAN_SEMIRAW(fs, wc, X)					\
+do {									\
+  if (_FP_QNANNEGATEDP)							\
+    {									\
+      _FP_FRAC_HIGH_##fs(X) &= _FP_QNANBIT_SH_##fs - 1;			\
+      if (_FP_FRAC_ZEROP_##wc(X))					\
+	{								\
+	  X##_s = _FP_NANSIGN_##fs;					\
+	  _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
+	  _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);				\
+	}								\
+    }									\
+  else									\
+    _FP_FRAC_HIGH_##fs(X) |= _FP_QNANBIT_SH_##fs;			\
+} while (0)
+
 /* Test whether a biased exponent is normal (not zero or maximum).  */
 #define _FP_EXP_NORMAL(fs, wc, X)	(((X##_e + 1) & _FP_EXPMAX_##fs) > 1)
 
@@ -159,7 +202,7 @@ do {								\
 	  X##_s = _FP_NANSIGN_##fs;				\
 	}							\
       else							\
-	_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;		\
+	_FP_SETQNAN(fs, wc, X);					\
     }								\
 } while (0)
 
@@ -273,7 +316,7 @@ do {								\
 	X##_s = _FP_NANSIGN_##fs;				\
       }								\
     else							\
-      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;		\
+      _FP_SETQNAN(fs, wc, X);					\
     break;							\
   }								\
 } while (0)
@@ -287,7 +330,7 @@ do {								\
   if (X##_e == _FP_EXPMAX_##fs)					\
     {								\
       if (!_FP_FRAC_ZEROP_##wc(X)				\
-	  && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
+	  && _FP_FRAC_SNANP(fs, X))				\
 	__ret = 1;						\
     }								\
   __ret;							\
@@ -1199,7 +1242,7 @@ do {									 \
 	  D##_e = _FP_EXPMAX_##dfs;					 \
 	  if (!_FP_FRAC_ZEROP_##swc(S))					 \
 	    {								 \
-	      if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs))	 \
+	      if (_FP_FRAC_SNANP(sfs, S))				 \
 		FP_SET_EXCEPTION(FP_EX_INVALID);			 \
 	      _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs			 \
 				     - _FP_FRACBITS_##sfs));		 \
@@ -1286,7 +1329,7 @@ do {									     \
 	      /* Semi-raw NaN must have all workbits cleared.  */	     \
 	      _FP_FRAC_LOW_##dwc(D)					     \
 		&= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1);		     \
-	      _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs;		     \
+	      _FP_SETQNAN_SEMIRAW(dfs, dwc, D);				     \
 	    }								     \
 	}								     \
     }									     \
diff --git a/soft-fp/testit.c b/soft-fp/testit.c
index 46a50c4401..f1e9b54758 100644
--- a/soft-fp/testit.c
+++ b/soft-fp/testit.c
@@ -200,17 +200,17 @@ double gen_special_double(int i)
       case 0:
 	X_c = FP_CLS_NAN;
 #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
-	__FP_FRAC_SET_2(X, _FP_QNANBIT_D, 0x1234);
+	__FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1234);
 #else
-	_FP_FRAC_SET_1(X, _FP_QNANBIT_D | 0x1234);
+	_FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1234);
 #endif
 	break;
       case 2:
 	X_c = FP_CLS_NAN;
 #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
-	__FP_FRAC_SET_2(X, _FP_QNANBIT_D, 0x1);
+	__FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1);
 #else
-	_FP_FRAC_SET_1(X, _FP_QNANBIT_D | 0x1);
+	_FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1);
 #endif
 	break;
       case 4: