From a1f1c731c6515313d81630eff8867f0cba27dec5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 17 Dec 2021 17:57:16 +0100 Subject: [PATCH] target/ppc: Use helper_todouble/tosingle in helper_xststdcsp MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When computing the predicate "is this value currently formatted for single precision", we do not want to round the value according to the current rounding mode, nor perform a floating-point equality. We want to see if the N bits that make up single-precision are the only ones set within the register, and then a bitwise equality. Fixes a bug in which a single-precision NaN is considered !SP, because float64_eq(nan, nan) is always false. Signed-off-by: Richard Henderson Message-Id: <20211119160502.17432-35-richard.henderson@linaro.org> Signed-off-by: Cédric Le Goater --- target/ppc/fpu_helper.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index c955b20739..1e9a161540 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -3163,26 +3163,25 @@ void helper_xststdcsp(CPUPPCState *env, uint32_t opcode, ppc_vsr_t *xb) { uint32_t dcmx, sign, exp; uint32_t cc, match = 0, not_sp = 0; + float64 arg = xb->VsrD(0); + float64 arg_sp; dcmx = DCMX(opcode); - exp = (xb->VsrD(0) >> 52) & 0x7FF; + exp = (arg >> 52) & 0x7FF; + sign = float64_is_neg(arg); - sign = float64_is_neg(xb->VsrD(0)); - if (float64_is_any_nan(xb->VsrD(0))) { + if (float64_is_any_nan(arg)) { match = extract32(dcmx, 6, 1); - } else if (float64_is_infinity(xb->VsrD(0))) { + } else if (float64_is_infinity(arg)) { match = extract32(dcmx, 4 + !sign, 1); - } else if (float64_is_zero(xb->VsrD(0))) { + } else if (float64_is_zero(arg)) { match = extract32(dcmx, 2 + !sign, 1); - } else if (float64_is_zero_or_denormal(xb->VsrD(0)) || - (exp > 0 && exp < 0x381)) { + } else if (float64_is_zero_or_denormal(arg) || (exp > 0 && exp < 0x381)) { match = extract32(dcmx, 0 + !sign, 1); } - not_sp = !float64_eq(xb->VsrD(0), - float32_to_float64( - float64_to_float32(xb->VsrD(0), &env->fp_status), - &env->fp_status), &env->fp_status); + arg_sp = helper_todouble(helper_tosingle(arg)); + not_sp = arg != arg_sp; cc = sign << CRF_LT_BIT | match << CRF_EQ_BIT | not_sp << CRF_SO_BIT; env->fpscr &= ~FP_FPCC; -- 2.11.4.GIT