--- zzzz-none-000/linux-2.4.17/arch/mips/math-emu/ieee754sp.c 2001-04-14 03:26:07.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/arch/mips/math-emu/ieee754sp.c 2004-11-24 13:22:41.000000000 +0000 @@ -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 */