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: fix _FP_DIV_MEAT_* returning results with wrong exponent (bug 16032)


Linux kernel commit 930cc144a043ff95e56b6888fa51c618b33f89e7,
"math-emu: Fix signalling of underflow and inexact while packing
result.", makes soft-fp packing changes that I said in
<https://sourceware.org/ml/libc-alpha/2012-05/msg01825.html> would
appear to be working around a bug in FP_DIV macros rather than
correctly needed if the packing macros were used with correct input.

This patch fixes what I believe is that division macro bug: a test of
> rather than >= meant that in certain cases division macros returned
an exact result with the overflow bit set and the wrong exponent.
This patch makes _FP_DIV_MEAT_2_udiv and _FP_DIV_MEAT_4_udiv duly use
>= as the condition so that the exponent is the correct one for the
infinite-precision division.

_FP_DIV_MEAT_2_gmp appears to have a similar bug, which is fixed,
mechanically, in this patch - but it increments the exponent in one
case, instead of decrementing it in the other, which is obviously
wrong for the interface to these macros, and so is also fixed.  But in
fact, as far as I can see this macro is (a) unused and (b) otherwise
bogus.  Both soft-fp and GMP use little-endian representation, so word
0 is the low part of the mantissa.  But the shifts in
_FP_DIV_MEAT_2_gmp look rather like it's expecting big-endian; they
only make sense at all if X##_f0 and _x[1] are high parts, and X##_f1
and _x[2] are low parts (and even then, the shift amount doesn't make
sense and nor does it appear to be following the mpn_divrem interface
in other ways).  If other people agree with this analysis, it may be
appropriate to remove this macro completely (in a separate patch).

Tested for powerpc-nofpu.  David, SPARC testing would be useful as
well (especially sparc32 to confirm the absence of regressions from
the change to _FP_DIV_MEAT_4_udiv).

2013-10-09  Joseph Myers  <joseph@codesourcery.com>

	[BZ #16032]
	* soft-fp/op-2.h (_FP_DIV_MEAT_2_udiv): Shift numerator right
	without decrementing exponent if mantissa >= that for the
	denominator, not >.
	(_FP_DIV_MEAT_2_gmp): Test numerator mantissa >= that for the
	denominator, not >.  Decrement exponent in < case instead of
	incrementing in >= case.
	* soft-fp/op-4.h (_FP_DIV_MEAT_4_udiv): Shift numerator right
	without decrementing exponent if mantissa >= that for the
	denominator, not >.

diff --git a/soft-fp/op-2.h b/soft-fp/op-2.h
index 2008822..2892d3b 100644
--- a/soft-fp/op-2.h
+++ b/soft-fp/op-2.h
@@ -469,7 +469,7 @@
 #define _FP_DIV_MEAT_2_udiv(fs, R, X, Y)				\
   do {									\
     _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0;		\
-    if (_FP_FRAC_GT_2(X, Y))						\
+    if (_FP_FRAC_GE_2(X, Y))						\
       {									\
 	_n_f2 = X##_f1 >> 1;						\
 	_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
@@ -539,9 +539,8 @@
     _FP_W_TYPE _x[4], _y[2], _z[4];					\
     _y[0] = Y##_f0; _y[1] = Y##_f1;					\
     _x[0] = _x[3] = 0;							\
-    if (_FP_FRAC_GT_2(X, Y))						\
+    if (_FP_FRAC_GE_2(X, Y))						\
       {									\
-	R##_e++;							\
 	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) |	\
 		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
 			    (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE)));	\
@@ -549,6 +548,7 @@
       }									\
     else								\
       {									\
+	R##_e--;							\
 	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) |	\
 		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
 			    (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE)));	\
diff --git a/soft-fp/op-4.h b/soft-fp/op-4.h
index f16870d..8319254 100644
--- a/soft-fp/op-4.h
+++ b/soft-fp/op-4.h
@@ -381,7 +381,7 @@
     int _i;								    \
     _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m);				    \
     _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4);					    \
-    if (_FP_FRAC_GT_4(X, Y))						    \
+    if (_FP_FRAC_GE_4(X, Y))						    \
       {									    \
 	_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1);			    \
 	_FP_FRAC_SRL_4(X, 1);						    \

-- 
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]