According to Intel's x87 FPU specification (Table 8-10, Vol. 1), arithmetic
operations on operands in unsupported formats (including pseudo-NaNs) must
return the QNaN floating-point indefinite value.
The helper functions for FPATAN, FYL2XP1, and FYL2X incorrectly check for
signaling NaN before checking for invalid encodings. This causes pseudo-NaNs
to be treated as valid signaling NaNs and silenced, rather than being
rejected as unsupported formats.
Reorder the checks to test floatx80_invalid_encoding before
floatx80_is_signaling_nan, matching the correct behavior already
implemented in helper_fscale.
Signed-off-by: Max Chou <max.chou@sifive.com>
---
target/i386/tcg/fpu_helper.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index b3b23823fd..37c83ded38 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1377,16 +1377,16 @@ void helper_fpatan(CPUX86State *env)
int32_t arg1_exp = extractFloatx80Exp(ST1);
bool arg1_sign = extractFloatx80Sign(ST1);
- if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
+ if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
+ float_raise(float_flag_invalid, &env->fp_status);
+ ST1 = floatx80_default_nan(&env->fp_status);
+ } else if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_silence_nan(ST0, &env->fp_status);
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
- } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
- floatx80_invalid_encoding(ST1, &env->fp_status)) {
- float_raise(float_flag_invalid, &env->fp_status);
- ST1 = floatx80_default_nan(&env->fp_status);
} else if (floatx80_is_any_nan(ST0)) {
ST1 = ST0;
} else if (floatx80_is_any_nan(ST1)) {
@@ -2061,16 +2061,16 @@ void helper_fyl2xp1(CPUX86State *env)
int32_t arg1_exp = extractFloatx80Exp(ST1);
bool arg1_sign = extractFloatx80Sign(ST1);
- if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
+ if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
+ float_raise(float_flag_invalid, &env->fp_status);
+ ST1 = floatx80_default_nan(&env->fp_status);
+ } else if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_silence_nan(ST0, &env->fp_status);
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
- } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
- floatx80_invalid_encoding(ST1, &env->fp_status)) {
- float_raise(float_flag_invalid, &env->fp_status);
- ST1 = floatx80_default_nan(&env->fp_status);
} else if (floatx80_is_any_nan(ST0)) {
ST1 = ST0;
} else if (floatx80_is_any_nan(ST1)) {
@@ -2159,16 +2159,16 @@ void helper_fyl2x(CPUX86State *env)
int32_t arg1_exp = extractFloatx80Exp(ST1);
bool arg1_sign = extractFloatx80Sign(ST1);
- if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
+ if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
+ float_raise(float_flag_invalid, &env->fp_status);
+ ST1 = floatx80_default_nan(&env->fp_status);
+ } else if (floatx80_is_signaling_nan(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_silence_nan(ST0, &env->fp_status);
} else if (floatx80_is_signaling_nan(ST1, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
- } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
- floatx80_invalid_encoding(ST1, &env->fp_status)) {
- float_raise(float_flag_invalid, &env->fp_status);
- ST1 = floatx80_default_nan(&env->fp_status);
} else if (floatx80_is_any_nan(ST0)) {
ST1 = ST0;
} else if (floatx80_is_any_nan(ST1)) {
--
2.52.0