mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-12-24 00:18:36 -07:00
softfloat: Allow 2-operand NaN propagation rule to be set at runtime
IEEE 758 does not define a fixed rule for which NaN to pick as the result if both operands of a 2-operand operation are NaNs. As a result different architectures have ended up with different rules for propagating NaNs. QEMU currently hardcodes the NaN propagation logic into the binary because pickNaN() has an ifdef ladder for different targets. We want to make the propagation rule instead be selectable at runtime, because: * this will let us have multiple targets in one QEMU binary * the Arm FEAT_AFP architectural feature includes letting the guest select a NaN propagation rule at runtime * x86 specifies different propagation rules for x87 FPU ops and for SSE ops, and specifying the rule in the float_status would let us emulate this, instead of wrongly using the x87 rules everywhere In this commit we add an enum for the propagation rule, the field in float_status, and the corresponding getters and setters. We change pickNaN to honour this, but because all targets still leave this field at its default 0 value, the fallback logic will pick the rule type with the old ifdef ladder. It's valid not to set a propagation rule if default_nan_mode is enabled, because in that case there's no need to pick a NaN; all the callers of pickNaN() catch this case and skip calling it. So we can already assert that we don't get into the "no rule defined" codepath for our four targets which always set default_nan_mode: Hexagon, RiscV, SH4 and Tricore, and for the one target which does not have FP at all: avr. These targets will not need to be updated to call set_float_2nan_prop_rule(). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20241025141254.2141506-2-peter.maydell@linaro.org
This commit is contained in:
parent
11b8920ed2
commit
8a132968b2
3 changed files with 185 additions and 97 deletions
|
|
@ -75,6 +75,12 @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
|
|||
status->floatx80_rounding_precision = val;
|
||||
}
|
||||
|
||||
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
|
||||
float_status *status)
|
||||
{
|
||||
status->float_2nan_prop_rule = rule;
|
||||
}
|
||||
|
||||
static inline void set_flush_to_zero(bool val, float_status *status)
|
||||
{
|
||||
status->flush_to_zero = val;
|
||||
|
|
@ -126,6 +132,11 @@ get_floatx80_rounding_precision(float_status *status)
|
|||
return status->floatx80_rounding_precision;
|
||||
}
|
||||
|
||||
static inline Float2NaNPropRule get_float_2nan_prop_rule(float_status *status)
|
||||
{
|
||||
return status->float_2nan_prop_rule;
|
||||
}
|
||||
|
||||
static inline bool get_flush_to_zero(float_status *status)
|
||||
{
|
||||
return status->flush_to_zero;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue