mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-26 20:03:54 -06:00
fpu: Implement float_flag_input_denormal_used
For the x86 and the Arm FEAT_AFP semantics, we need to be able to tell the target code that the FPU operation has used an input denormal. Implement this; when it happens we set the new float_flag_denormal_input_used. Note that we only set this when an input denormal is actually used by the operation: if the operation results in Invalid Operation or Divide By Zero or the result is a NaN because some other input was a NaN then we never needed to look at the input denormal and do not set denormal_input_used. We mostly do not need to adjust the hardfloat codepaths to deal with this flag, because almost all hardfloat operations are already gated on the input not being a denormal, and will fall back to softfloat for a denormal input. The only exception is the comparison operations, where we need to add the check for input denormals, which must now fall back to softfloat where they did not before. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
7ad6a56757
commit
029a2083a2
3 changed files with 107 additions and 6 deletions
|
@ -2718,8 +2718,10 @@ static void parts_float_to_ahp(FloatParts64 *a, float_status *s)
|
|||
float16_params_ahp.frac_size + 1);
|
||||
break;
|
||||
|
||||
case float_class_normal:
|
||||
case float_class_denormal:
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
break;
|
||||
case float_class_normal:
|
||||
case float_class_zero:
|
||||
break;
|
||||
|
||||
|
@ -2733,6 +2735,9 @@ static void parts64_float_to_float(FloatParts64 *a, float_status *s)
|
|||
if (is_nan(a->cls)) {
|
||||
parts_return_nan(a, s);
|
||||
}
|
||||
if (a->cls == float_class_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void parts128_float_to_float(FloatParts128 *a, float_status *s)
|
||||
|
@ -2740,6 +2745,9 @@ static void parts128_float_to_float(FloatParts128 *a, float_status *s)
|
|||
if (is_nan(a->cls)) {
|
||||
parts_return_nan(a, s);
|
||||
}
|
||||
if (a->cls == float_class_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
}
|
||||
|
||||
#define parts_float_to_float(P, S) \
|
||||
|
@ -2752,12 +2760,21 @@ static void parts_float_to_float_narrow(FloatParts64 *a, FloatParts128 *b,
|
|||
a->sign = b->sign;
|
||||
a->exp = b->exp;
|
||||
|
||||
if (is_anynorm(a->cls)) {
|
||||
switch (a->cls) {
|
||||
case float_class_denormal:
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
/* fall through */
|
||||
case float_class_normal:
|
||||
frac_truncjam(a, b);
|
||||
} else if (is_nan(a->cls)) {
|
||||
break;
|
||||
case float_class_snan:
|
||||
case float_class_qnan:
|
||||
/* Discard the low bits of the NaN. */
|
||||
a->frac = b->frac_hi;
|
||||
parts_return_nan(a, s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2772,6 +2789,9 @@ static void parts_float_to_float_widen(FloatParts128 *a, FloatParts64 *b,
|
|||
if (is_nan(a->cls)) {
|
||||
parts_return_nan(a, s);
|
||||
}
|
||||
if (a->cls == float_class_denormal) {
|
||||
float_raise(float_flag_input_denormal_used, s);
|
||||
}
|
||||
}
|
||||
|
||||
float32 float16_to_float32(float16 a, bool ieee, float_status *s)
|
||||
|
@ -4411,7 +4431,11 @@ float32_hs_compare(float32 xa, float32 xb, float_status *s, bool is_quiet)
|
|||
goto soft;
|
||||
}
|
||||
|
||||
float32_input_flush2(&ua.s, &ub.s, s);
|
||||
if (unlikely(float32_is_denormal(ua.s) || float32_is_denormal(ub.s))) {
|
||||
/* We may need to set the input_denormal_used flag */
|
||||
goto soft;
|
||||
}
|
||||
|
||||
if (isgreaterequal(ua.h, ub.h)) {
|
||||
if (isgreater(ua.h, ub.h)) {
|
||||
return float_relation_greater;
|
||||
|
@ -4461,7 +4485,11 @@ float64_hs_compare(float64 xa, float64 xb, float_status *s, bool is_quiet)
|
|||
goto soft;
|
||||
}
|
||||
|
||||
float64_input_flush2(&ua.s, &ub.s, s);
|
||||
if (unlikely(float64_is_denormal(ua.s) || float64_is_denormal(ub.s))) {
|
||||
/* We may need to set the input_denormal_used flag */
|
||||
goto soft;
|
||||
}
|
||||
|
||||
if (isgreaterequal(ua.h, ub.h)) {
|
||||
if (isgreater(ua.h, ub.h)) {
|
||||
return float_relation_greater;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue