From 18fc17ca250a792aec250ec34695d3c473e7d4ae Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 15 Jun 2020 13:02:22 -0400 Subject: [PATCH] target/i386: implement special cases for fxtract The implementation of the fxtract instruction treats all nonzero operands as normal numbers, so yielding incorrect results for invalid formats, infinities, NaNs and subnormal and pseudo-denormal operands. Implement appropriate handling of all those cases. Backports commit c415f2c58296d86e9abb7e4a133111acf7031da3 from qemu --- qemu/target/i386/fpu_helper.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/qemu/target/i386/fpu_helper.c b/qemu/target/i386/fpu_helper.c index 3671d158..da730b1c 100644 --- a/qemu/target/i386/fpu_helper.c +++ b/qemu/target/i386/fpu_helper.c @@ -733,10 +733,33 @@ void helper_fxtract(CPUX86State *env) &env->fp_status); fpush(env); ST0 = temp.d; + } else if (floatx80_invalid_encoding(ST0)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_default_nan(&env->fp_status); + fpush(env); + ST0 = ST1; + } else if (floatx80_is_any_nan(ST0)) { + if (floatx80_is_signaling_nan(ST0, &env->fp_status)) { + float_raise(float_flag_invalid, &env->fp_status); + ST0 = floatx80_silence_nan(ST0, &env->fp_status); + } + fpush(env); + ST0 = ST1; + } else if (floatx80_is_infinity(ST0)) { + fpush(env); + ST0 = ST1; + ST1 = floatx80_infinity; } else { int expdif; - expdif = EXPD(temp) - EXPBIAS; + if (EXPD(temp) == 0) { + int shift = clz64(temp.l.lower); + temp.l.lower <<= shift; + expdif = 1 - EXPBIAS - shift; + float_raise(float_flag_input_denormal, &env->fp_status); + } else { + expdif = EXPD(temp) - EXPBIAS; + } /* DP exponent bias */ ST0 = int32_to_floatx80(expdif, &env->fp_status); fpush(env);