>>>>> On Thu, 21 Apr 2005 16:19:45 +0900 (JST), Atsushi Nemoto <anemo@xxxxxxxxxxxxx> said: >>> So file a bug against glibc, but we should fix the emulator so it >>> correctly imitates the MIPS instruction set... ralf> As a matter of defensive design I think we should try to follow ralf> the establish behaviour if nothing more specific is defined ralf> anywhere. anemo> OK, I sent a bug reoport to glibc bugzilla. (Bug# 864) The bug was resolved ... marked as WONTFIX. glibc developers said math-emu should be fixed. Please look at: http://sourceware.org/bugzilla/show_bug.cgi?id=864 for their comments. So I send a patch for math-emu again. Description: It looks glibc's pow() assume an unary '-' operation for any number (including NaNs) always invert its sign bit (though IEEE754 does not specify the sign bit for NaNs). This patch make the kernel math-emu emulates real MIPS neg.[ds] instruction. Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx> diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index 495c1ac..1c555e6 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -48,16 +48,22 @@ ieee754dp ieee754dp_neg(ieee754dp x) CLEARCX; FLUSHXDP; + /* + * Invert the sign ALWAYS to prevent an endless recursion on + * pow() in libc. + */ + /* quick fix up */ + DPSIGN(x) ^= 1; + if (xc == IEEE754_CLASS_SNAN) { + ieee754dp y = ieee754dp_indef(); SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); + DPSIGN(y) = DPSIGN(x); + return ieee754dp_nanxcpt(y, "neg"); } if (ieee754dp_isnan(x)) /* but not infinity */ return ieee754dp_nanxcpt(x, "neg", x); - - /* quick fix up */ - DPSIGN(x) ^= 1; return x; } diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index c809830..770f0f4 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -48,16 +48,22 @@ ieee754sp ieee754sp_neg(ieee754sp x) CLEARCX; FLUSHXSP; + /* + * Invert the sign ALWAYS to prevent an endless recursion on + * pow() in libc. + */ + /* quick fix up */ + SPSIGN(x) ^= 1; + if (xc == IEEE754_CLASS_SNAN) { + ieee754sp y = ieee754sp_indef(); SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "neg"); + SPSIGN(y) = SPSIGN(x); + return ieee754sp_nanxcpt(y, "neg"); } if (ieee754sp_isnan(x)) /* but not infinity */ return ieee754sp_nanxcpt(x, "neg", x); - - /* quick fix up */ - SPSIGN(x) ^= 1; return x; }