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

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

diff -urN linux-2.4.18/arch/mips/math-emu/ieee754sp.c linux-2.4.19/arch/mips/math-emu/ieee754sp.c
@@ -42,9 +42,7 @@
 int ieee754sp_issnan(ieee754sp x)
 {
 	assert(ieee754sp_isnan(x));
-	if (ieee754_csr.noq)
-		return 1;
-	return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1));
+	return (SPMANT(x) & SP_MBIT(SP_MBITS-1));
 }
 
 
@@ -74,10 +72,11 @@
 
 	if (!SETCX(IEEE754_INVALID_OPERATION)) {
 		/* not enabled convert to a quiet NaN */
-		if (ieee754_csr.noq)
+		SPMANT(r) &= (~SP_MBIT(SP_MBITS-1));
+		if (ieee754sp_isnan(r))
 			return r;
-		SPMANT(r) |= SP_MBIT(SP_MBITS - 1);
-		return r;
+		else
+			return ieee754sp_indef();
 	}
 
 	ax.op = op;
@@ -100,6 +99,32 @@
 }
 
 
+static unsigned get_rounding(int sn, unsigned xm)
+{
+	/* inexact must round of 3 bits 
+	 */
+	if (xm & (SP_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
@@ -118,39 +143,58 @@
 
 		if (ieee754_csr.nod) {
 			SETCX(IEEE754_UNDERFLOW);
-			return ieee754sp_zero(sn);
-		}
+			SETCX(IEEE754_INEXACT);
 
-		/* sticky right shift es bits 
-		 */
-		SPXSRSXn(es);
+			switch(ieee754_csr.rm) {
+			case IEEE754_RN:
+				return ieee754sp_zero(sn);
+			case IEEE754_RZ:
+				return ieee754sp_zero(sn);
+			case IEEE754_RU:      /* toward +Infinity */
+				if(sn == 0)
+					return ieee754sp_min(0);
+				else
+					return ieee754sp_zero(1);
+			case IEEE754_RD:      /* toward -Infinity */
+				if(sn == 0)
+					return ieee754sp_zero(0);
+				else
+					return ieee754sp_min(1);
+			}
+		}
 
-		assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
-		assert(xe == SP_EMIN);
+		if (xe == SP_EMIN - 1
+				&& get_rounding(sn, xm) >> (SP_MBITS + 1 + 3))
+		{
+			/* Not tiny after rounding */
+			SETCX(IEEE754_INEXACT);
+			xm = get_rounding(sn, xm);
+			xm >>= 1;
+			/* Clear grs bits */
+			xm &= ~(SP_MBIT(3) - 1);
+			xe++;
+		}
+		else {
+			/* sticky right shift es bits 
+			 */
+			SPXSRSXn(es);
+			assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+			assert(xe == SP_EMIN);
+		}
 	}
 	if (xm & (SP_MBIT(3) - 1)) {
 		SETCX(IEEE754_INEXACT);
+		if ((xm & (SP_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 >> (SP_MBITS + 1 + 3)) {	/* add causes mantissa overflow */
+		if (xm >> (SP_MBITS + 1 + 3)) {
+			/* add causes mantissa overflow */
 			xm >>= 1;
 			xe++;
 		}
@@ -163,6 +207,7 @@
 
 	if (xe > SP_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 & SP_HIDDEN_BIT) == 0) {
 		/* we underflow (tiny/zero) */
 		assert(xe == SP_EMIN);
-		SETCX(IEEE754_UNDERFLOW);
+		if (ieee754_csr.mx & IEEE754_UNDERFLOW)
+			SETCX(IEEE754_UNDERFLOW);
 		return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
 	} else {
 		assert((xm >> (SP_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)