patch-2.4.19 linux-2.4.19/arch/mips/math-emu/ieee754dp.c

Next file: linux-2.4.19/arch/mips/math-emu/ieee754int.h
Previous file: linux-2.4.19/arch/mips/math-emu/ieee754d.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/arch/mips/math-emu/ieee754dp.c linux-2.4.19/arch/mips/math-emu/ieee754dp.c
@@ -42,9 +42,7 @@
 int ieee754dp_issnan(ieee754dp x)
 {
 	assert(ieee754dp_isnan(x));
-	if (ieee754_csr.noq)
-		return 1;
-	return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1));
+	return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1));
 }
 
 
@@ -73,10 +71,11 @@
 
 	if (!SETCX(IEEE754_INVALID_OPERATION)) {
 		/* not enabled convert to a quiet NaN */
-		if (ieee754_csr.noq)
+		DPMANT(r) &= (~DP_MBIT(DP_MBITS-1));
+		if (ieee754dp_isnan(r))
 			return r;
-		DPMANT(r) |= DP_MBIT(DP_MBITS - 1);
-		return r;
+		else
+			return ieee754dp_indef();
 	}
 
 	ax.op = op;
@@ -99,6 +98,32 @@
 }
 
 
+static unsigned long long get_rounding(int sn, unsigned long long xm)
+{
+	/* inexact must round of 3 bits 
+	 */
+	if (xm & (DP_MBIT(3) - 1)) {
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+	}
+	return xm;
+}
+
+
 /* generate a normal/denormal number with over,under handeling
  * sn is sign
  * xe is an unbiased exponent
@@ -117,40 +142,59 @@
 
 		if (ieee754_csr.nod) {
 			SETCX(IEEE754_UNDERFLOW);
-			return ieee754dp_zero(sn);
-		}
+			SETCX(IEEE754_INEXACT);
 
-		/* sticky right shift es bits 
-		 */
-		xm = XDPSRS(xm, es);
-		xe += es;
+			switch(ieee754_csr.rm) {
+			case IEEE754_RN:
+				return ieee754dp_zero(sn);
+			case IEEE754_RZ:
+				return ieee754dp_zero(sn);
+			case IEEE754_RU:    /* toward +Infinity */
+				if(sn == 0)
+					return ieee754dp_min(0);
+				else
+					return ieee754dp_zero(1);
+			case IEEE754_RD:    /* toward -Infinity */
+				if(sn == 0)
+					return ieee754dp_zero(0);
+				else
+					return ieee754dp_min(1);
+			}
+		}
 
-		assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
-		assert(xe == DP_EMIN);
+		if (xe == DP_EMIN - 1
+				&& get_rounding(sn, xm) >> (DP_MBITS + 1 + 3))
+		{
+			/* Not tiny after rounding */
+			SETCX(IEEE754_INEXACT);
+			xm = get_rounding(sn, xm);
+			xm >>= 1;
+			/* Clear grs bits */
+			xm &= ~(DP_MBIT(3) - 1);
+			xe++;
+		}
+		else {
+			/* sticky right shift es bits 
+			 */
+			xm = XDPSRS(xm, es);
+			xe += es;
+			assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+			assert(xe == DP_EMIN);
+		}
 	}
 	if (xm & (DP_MBIT(3) - 1)) {
 		SETCX(IEEE754_INEXACT);
+		if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
+			SETCX(IEEE754_UNDERFLOW);
+		}
+
 		/* inexact must round of 3 bits 
 		 */
-		switch (ieee754_csr.rm) {
-		case IEEE754_RZ:
-			break;
-		case IEEE754_RN:
-			xm += 0x3 + ((xm >> 3) & 1);
-			/* xm += (xm&0x8)?0x4:0x3 */
-			break;
-		case IEEE754_RU:	/* toward +Infinity */
-			if (!sn)	/* ?? */
-				xm += 0x8;
-			break;
-		case IEEE754_RD:	/* toward -Infinity */
-			if (sn)	/* ?? */
-				xm += 0x8;
-			break;
-		}
+		xm = get_rounding(sn, xm);
 		/* adjust exponent for rounding add overflowing 
 		 */
-		if (xm >> (DP_MBITS + 3 + 1)) {	/* add causes mantissa overflow */
+		if (xm >> (DP_MBITS + 3 + 1)) {
+			/* add causes mantissa overflow */
 			xm >>= 1;
 			xe++;
 		}
@@ -163,6 +207,7 @@
 
 	if (xe > DP_EMAX) {
 		SETCX(IEEE754_OVERFLOW);
+		SETCX(IEEE754_INEXACT);
 		/* -O can be table indexed by (rm,sn) */
 		switch (ieee754_csr.rm) {
 		case IEEE754_RN:
@@ -186,7 +231,8 @@
 	if ((xm & DP_HIDDEN_BIT) == 0) {
 		/* we underflow (tiny/zero) */
 		assert(xe == DP_EMIN);
-		SETCX(IEEE754_UNDERFLOW);
+		if (ieee754_csr.mx & IEEE754_UNDERFLOW)
+			SETCX(IEEE754_UNDERFLOW);
 		return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
 	} else {
 		assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)