diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 758b625d95e00616976cb56a07356e2c8b866216..937e6534b8a0415cf3ae315b6914a677b02bf32d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -113,6 +113,8 @@ static void cpu_set_nofpu_id(struct cpuinfo_mips *c) if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 | MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W; + if (c->options & MIPS_CPU_NAN_2008) + value |= MIPS_FPIR_HAS2008; c->fpu_id = value; } diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 6ffc336c530e3e11c48c1dcb8ab9eb50224b7ff4..f3985617ce31526c7de1d1fb19a0af3a207bd925 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -38,10 +38,13 @@ int ieee754dp_tint(union ieee754dp x) switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_indef(); + case IEEE754_CLASS_INF: + ieee754_setcx(IEEE754_INVALID_OPERATION); + return ieee754si_overflow(xs); + case IEEE754_CLASS_ZERO: return 0; @@ -53,7 +56,7 @@ int ieee754dp_tint(union ieee754dp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_indef(); + return ieee754si_overflow(xs); } /* oh gawd */ if (xe > DP_FBITS) { @@ -93,7 +96,7 @@ int ieee754dp_tint(union ieee754dp x) if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_indef(); + return ieee754si_overflow(xs); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index 9cdc145b75e012d75a22f146c1e3c3b5c65a4e7f..748fa10ed4cf63d3e0995a3d6ae6860b6c432d7b 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -38,10 +38,13 @@ s64 ieee754dp_tlong(union ieee754dp x) switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_indef(); + case IEEE754_CLASS_INF: + ieee754_setcx(IEEE754_INVALID_OPERATION); + return ieee754di_overflow(xs); + case IEEE754_CLASS_ZERO: return 0; @@ -56,7 +59,7 @@ s64 ieee754dp_tlong(union ieee754dp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_indef(); + return ieee754di_overflow(xs); } /* oh gawd */ if (xe > DP_FBITS) { @@ -97,7 +100,7 @@ s64 ieee754dp_tlong(union ieee754dp x) if ((xm >> 63) != 0) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_indef(); + return ieee754di_overflow(xs); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 8e97acbbe22ceb96789d36c44b98500f9885154a..e16ae7b75dbb775c9af078994e785c257a454f39 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -59,7 +59,8 @@ const union ieee754dp __ieee754dp_spcvals[] = { DPCNST(1, 3, 0x4000000000000ULL), /* - 10.0 */ DPCNST(0, DP_EMAX + 1, 0x0000000000000ULL), /* + infinity */ DPCNST(1, DP_EMAX + 1, 0x0000000000000ULL), /* - infinity */ - DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL), /* + indef quiet Nan */ + DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL), /* + ind legacy qNaN */ + DPCNST(0, DP_EMAX + 1, 0x8000000000000ULL), /* + indef 2008 qNaN */ DPCNST(0, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* + max */ DPCNST(1, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* - max */ DPCNST(0, DP_EMIN, 0x0000000000000ULL), /* + min normal */ @@ -82,7 +83,8 @@ const union ieee754sp __ieee754sp_spcvals[] = { SPCNST(1, 3, 0x200000), /* - 10.0 */ SPCNST(0, SP_EMAX + 1, 0x000000), /* + infinity */ SPCNST(1, SP_EMAX + 1, 0x000000), /* - infinity */ - SPCNST(0, SP_EMAX + 1, 0x3FFFFF), /* + indef quiet Nan */ + SPCNST(0, SP_EMAX + 1, 0x3FFFFF), /* + indef legacy quiet NaN */ + SPCNST(0, SP_EMAX + 1, 0x400000), /* + indef 2008 quiet NaN */ SPCNST(0, SP_EMAX, 0x7FFFFF), /* + max normal */ SPCNST(1, SP_EMAX, 0x7FFFFF), /* - max normal */ SPCNST(0, SP_EMIN, 0x000000), /* + min normal */ diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index df94720714c73cc95736544f7b05804d607d27ca..d3be351aed151305396723ddfff661837a114cde 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -221,15 +221,16 @@ union ieee754dp ieee754dp_dump(char *s, union ieee754dp x); #define IEEE754_SPCVAL_NTEN 5 /* -10.0 */ #define IEEE754_SPCVAL_PINFINITY 6 /* +inf */ #define IEEE754_SPCVAL_NINFINITY 7 /* -inf */ -#define IEEE754_SPCVAL_INDEF 8 /* quiet NaN */ -#define IEEE754_SPCVAL_PMAX 9 /* +max norm */ -#define IEEE754_SPCVAL_NMAX 10 /* -max norm */ -#define IEEE754_SPCVAL_PMIN 11 /* +min norm */ -#define IEEE754_SPCVAL_NMIN 12 /* -min norm */ -#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ -#define IEEE754_SPCVAL_NMIND 14 /* -min denorm */ -#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ -#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ +#define IEEE754_SPCVAL_INDEF_LEG 8 /* legacy quiet NaN */ +#define IEEE754_SPCVAL_INDEF_2008 9 /* IEEE 754-2008 quiet NaN */ +#define IEEE754_SPCVAL_PMAX 10 /* +max norm */ +#define IEEE754_SPCVAL_NMAX 11 /* -max norm */ +#define IEEE754_SPCVAL_PMIN 12 /* +min norm */ +#define IEEE754_SPCVAL_NMIN 13 /* -min norm */ +#define IEEE754_SPCVAL_PMIND 14 /* +min denorm */ +#define IEEE754_SPCVAL_NMIND 15 /* -min denorm */ +#define IEEE754_SPCVAL_P1E31 16 /* + 1.0e31 */ +#define IEEE754_SPCVAL_P1E63 17 /* + 1.0e63 */ extern const union ieee754dp __ieee754dp_spcvals[]; extern const union ieee754sp __ieee754sp_spcvals[]; @@ -243,7 +244,8 @@ extern const union ieee754sp __ieee754sp_spcvals[]; #define ieee754dp_zero(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) #define ieee754dp_one(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) #define ieee754dp_ten(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) -#define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF]) +#define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF_LEG + \ + ieee754_csr.nan2008]) #define ieee754dp_max(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) #define ieee754dp_min(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) #define ieee754dp_mind(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) @@ -254,7 +256,8 @@ extern const union ieee754sp __ieee754sp_spcvals[]; #define ieee754sp_zero(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) #define ieee754sp_one(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) #define ieee754sp_ten(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) -#define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF]) +#define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF_LEG + \ + ieee754_csr.nan2008]) #define ieee754sp_max(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) #define ieee754sp_min(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) #define ieee754sp_mind(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) @@ -266,12 +269,25 @@ extern const union ieee754sp __ieee754sp_spcvals[]; */ static inline int ieee754si_indef(void) { - return INT_MAX; + return ieee754_csr.nan2008 ? 0 : INT_MAX; } static inline s64 ieee754di_indef(void) { - return S64_MAX; + return ieee754_csr.nan2008 ? 0 : S64_MAX; +} + +/* + * Overflow integer value + */ +static inline int ieee754si_overflow(int xs) +{ + return ieee754_csr.nan2008 && xs ? INT_MIN : INT_MAX; +} + +static inline s64 ieee754di_overflow(int xs) +{ + return ieee754_csr.nan2008 && xs ? S64_MIN : S64_MAX; } /* result types for xctx.rt */ diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 522d843f2ffd04a47873328724a9d45965dce0ce..ad3c73436777f0c3103c887827c4547d888f5941 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -37,8 +37,11 @@ static inline int ieee754dp_isnan(union ieee754dp x) static inline int ieee754dp_issnan(union ieee754dp x) { + int qbit; + assert(ieee754dp_isnan(x)); - return (DPMANT(x) & DP_MBIT(DP_FBITS - 1)) == DP_MBIT(DP_FBITS - 1); + qbit = (DPMANT(x) & DP_MBIT(DP_FBITS - 1)) == DP_MBIT(DP_FBITS - 1); + return ieee754_csr.nan2008 ^ qbit; } @@ -51,7 +54,12 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r) assert(ieee754dp_issnan(r)); ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_indef(); + if (ieee754_csr.nan2008) + DPMANT(r) |= DP_MBIT(DP_FBITS - 1); + else + r = ieee754dp_indef(); + + return r; } static u64 ieee754dp_get_rounding(int sn, u64 xm) diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 6383e2c5c1adb5d527fe1023eb173f06e3776dc7..ed7bb277b3e05e224315508f32396fd37c239641 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -63,10 +63,10 @@ static inline int ieee754_class_nan(int xc) if (ve == SP_EMAX+1+SP_EBIAS) { \ if (vm == 0) \ vc = IEEE754_CLASS_INF; \ - else if (vm & SP_MBIT(SP_FBITS-1)) \ - vc = IEEE754_CLASS_SNAN; \ - else \ + else if (ieee754_csr.nan2008 ^ !(vm & SP_MBIT(SP_FBITS - 1))) \ vc = IEEE754_CLASS_QNAN; \ + else \ + vc = IEEE754_CLASS_SNAN; \ } else if (ve == SP_EMIN-1+SP_EBIAS) { \ if (vm) { \ ve = SP_EMIN; \ @@ -97,10 +97,10 @@ static inline int ieee754_class_nan(int xc) if (ve == DP_EMAX+1+DP_EBIAS) { \ if (vm == 0) \ vc = IEEE754_CLASS_INF; \ - else if (vm & DP_MBIT(DP_FBITS-1)) \ - vc = IEEE754_CLASS_SNAN; \ - else \ + else if (ieee754_csr.nan2008 ^ !(vm & DP_MBIT(DP_FBITS - 1))) \ vc = IEEE754_CLASS_QNAN; \ + else \ + vc = IEEE754_CLASS_SNAN; \ } else if (ve == DP_EMIN-1+DP_EBIAS) { \ if (vm) { \ ve = DP_EMIN; \ diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index ca8e35e33bf790f594156268e320ce866b2ed5c2..def00ffc50fcc7bc4740933215cdf5872940a450 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -37,8 +37,11 @@ static inline int ieee754sp_isnan(union ieee754sp x) static inline int ieee754sp_issnan(union ieee754sp x) { + int qbit; + assert(ieee754sp_isnan(x)); - return SPMANT(x) & SP_MBIT(SP_FBITS - 1); + qbit = (SPMANT(x) & SP_MBIT(SP_FBITS - 1)) == SP_MBIT(SP_FBITS - 1); + return ieee754_csr.nan2008 ^ qbit; } @@ -51,7 +54,12 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r) assert(ieee754sp_issnan(r)); ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_indef(); + if (ieee754_csr.nan2008) + SPMANT(r) |= SP_MBIT(SP_FBITS - 1); + else + r = ieee754sp_indef(); + + return r; } static unsigned ieee754sp_get_rounding(int sn, unsigned xm) diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index 3797148893adb62c10a989dc78e5e9dce56e1e9e..5060e8fdcb0b8817c5f6836e0a20273f08a79b52 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -44,13 +44,16 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) switch (xc) { case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(ieee754sp_nan_fdp(xs, xm)); - + x = ieee754dp_nanxcpt(x); + EXPLODEXDP; + /* Fall through. */ case IEEE754_CLASS_QNAN: y = ieee754sp_nan_fdp(xs, xm); - EXPLODEYSP; - if (!ieee754_class_nan(yc)) - y = ieee754sp_indef(); + if (!ieee754_csr.nan2008) { + EXPLODEYSP; + if (!ieee754_class_nan(yc)) + y = ieee754sp_indef(); + } return y; case IEEE754_CLASS_INF: diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 091299a317980b6bf0cfd84f0958b1f271d2bf9d..f4b4cabfe2e11740e17b4c77c913e6762ac26b71 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -38,10 +38,13 @@ int ieee754sp_tint(union ieee754sp x) switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_indef(); + case IEEE754_CLASS_INF: + ieee754_setcx(IEEE754_INVALID_OPERATION); + return ieee754si_overflow(xs); + case IEEE754_CLASS_ZERO: return 0; @@ -56,7 +59,7 @@ int ieee754sp_tint(union ieee754sp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_indef(); + return ieee754si_overflow(xs); } /* oh gawd */ if (xe > SP_FBITS) { @@ -97,7 +100,7 @@ int ieee754sp_tint(union ieee754sp x) if ((xm >> 31) != 0) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_indef(); + return ieee754si_overflow(xs); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index 9f3c742c1cea6ac264d1d4d66ef56b6916f675cb..a2450c7e452a672fdeba96bba5a7c262c1b6e876 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -39,10 +39,13 @@ s64 ieee754sp_tlong(union ieee754sp x) switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_indef(); + case IEEE754_CLASS_INF: + ieee754_setcx(IEEE754_INVALID_OPERATION); + return ieee754di_overflow(xs); + case IEEE754_CLASS_ZERO: return 0; @@ -57,7 +60,7 @@ s64 ieee754sp_tlong(union ieee754sp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_indef(); + return ieee754di_overflow(xs); } /* oh gawd */ if (xe > SP_FBITS) { @@ -94,7 +97,7 @@ s64 ieee754sp_tlong(union ieee754sp x) if ((xm >> 63) != 0) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_indef(); + return ieee754di_overflow(xs); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT);