--- zzzz-none-000/linux-2.4.17/arch/mips/math-emu/dp_tint.c 2001-04-14 03:26:07.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/arch/mips/math-emu/dp_tint.c 2004-11-24 13:22:40.000000000 +0000 @@ -35,38 +35,76 @@ CLEARCX; EXPLODEXDP; + FLUSHXDP; switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); case IEEE754_CLASS_ZERO: return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fixdp", x); + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; } if (xe >= 31) { - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fix", x); - } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fix", x); + /* look for valid corner case */ + if (xe == 31 && xs && xm == DP_HIDDEN_BIT) + return -2147483648; + /* Set invalid. We will only use overflow for floating + point overflow */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); } /* oh gawd */ if (xe > DP_MBITS) { xm <<= xe - DP_MBITS; } else if (xe < DP_MBITS) { - /* XXX no rounding - */ - xm >>= DP_MBITS - xe; + unsigned long long residue; + int round; + int sticky; + int odd; + + if (xe < -1) { + residue = xm; + round = 0; + sticky = residue != 0; + xm = 0; + } + else { + residue = xm << (64 - DP_MBITS + xe); + round = (residue >> 63) != 0; + sticky = (residue << 1) != 0; + xm >>= DP_MBITS - xe; + } + /* Note: At this point upper 32 bits of xm are guaranteed + to be zero */ + odd = (xm & 0x1) != 0x0; + switch (ieee754_csr.rm) { + case IEEE754_RN: + if (round && (sticky || odd)) + xm++; + break; + case IEEE754_RZ: + break; + case IEEE754_RU: /* toward +Infinity */ + if ((round || sticky) && !xs) + xm++; + break; + case IEEE754_RD: /* toward -Infinity */ + if ((round || sticky) && xs) + xm++; + break; + } + if ((xm >> 31) != 0) { + /* This can happen after rounding */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); + } + if (round || sticky) + SETCX(IEEE754_INEXACT); } if (xs) return -xm;