* [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 18:09 ` Richard Henderson
2025-02-21 14:42 ` Philippe Mathieu-Daudé
2025-02-17 12:50 ` [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const Peter Maydell
` (11 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Currently we hardcode at compile time whether the floatx80 default
Infinity value has the explicit integer bit set or not (x86 sets it;
m68k does not). To be able to compile softfloat once for all targets
we'd like to move this setting to runtime.
Define a new FloatX80Behaviour enum which is a set of flags that
define the target's floatx80 handling. Initially we define just one
flag, for whether the default Infinity has the Integer bit set or
not, but we will expand this in future commits to cover the other
floatx80 target specifics that we currently make compile-time
settings.
Define a new function floatx80_default_inf() which returns the
appropriate default Infinity value of the given sign, and use it in
the code that was previously directly using the compile-time constant
floatx80_infinity_{low,high} values when packing an infinity into a
floatx80.
Since floatx80 is highly unlikely to be supported in any new
architecture, and the existing code is generally written as "default
to like x87, with an ifdef for m68k", we make the default value for
the floatx80 behaviour flags be "what x87 does". This means we only
need to change the m68k target to specify the behaviour flags.
(Other users of floatx80 are the Arm NWFPE emulation, which is
obsolete and probably not actually doing the right thing anyway, and
the PPC xsrqpxp insn. Making the default be "like x87" avoids our
needing to review and test for behaviour changes there.)
We will clean up the remaining uses of the floatx80_infinity global
constant in subsequent commits.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/fpu/softfloat-helpers.h | 12 ++++++++++++
include/fpu/softfloat-types.h | 13 +++++++++++++
include/fpu/softfloat.h | 1 +
fpu/softfloat.c | 7 +++----
target/m68k/cpu.c | 6 ++++++
fpu/softfloat-specialize.c.inc | 10 ++++++++++
6 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 8983c2748ec..90862f5cd22 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -75,6 +75,12 @@ static inline void set_floatx80_rounding_precision(FloatX80RoundPrec val,
status->floatx80_rounding_precision = val;
}
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
+ float_status *status)
+{
+ status->floatx80_behaviour = b;
+}
+
static inline void set_float_2nan_prop_rule(Float2NaNPropRule rule,
float_status *status)
{
@@ -151,6 +157,12 @@ get_floatx80_rounding_precision(const float_status *status)
return status->floatx80_rounding_precision;
}
+static inline FloatX80Behaviour
+get_floatx80_behaviour(const float_status *status)
+{
+ return status->floatx80_behaviour;
+}
+
static inline Float2NaNPropRule
get_float_2nan_prop_rule(const float_status *status)
{
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index 53d5eb85210..dd22ecdbe60 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -320,6 +320,18 @@ typedef enum __attribute__((__packed__)) {
float_ftz_before_rounding = 1,
} FloatFTZDetection;
+/*
+ * floatx80 is primarily used by x86 and m68k, and there are
+ * differences in the handling, largely related to the explicit
+ * Integer bit which floatx80 has and the other float formats do not.
+ * These flag values allow specification of the target's requirements
+ * and can be ORed together to set floatx80_behaviour.
+ */
+typedef enum __attribute__((__packed__)) {
+ /* In the default Infinity value, is the Integer bit 0 ? */
+ floatx80_default_inf_int_bit_is_zero = 1,
+} FloatX80Behaviour;
+
/*
* Floating Point Status. Individual architectures may maintain
* several versions of float_status for different functions. The
@@ -331,6 +343,7 @@ typedef struct float_status {
uint16_t float_exception_flags;
FloatRoundMode float_rounding_mode;
FloatX80RoundPrec floatx80_rounding_precision;
+ FloatX80Behaviour floatx80_behaviour;
Float2NaNPropRule float_2nan_prop_rule;
Float3NaNPropRule float_3nan_prop_rule;
FloatInfZeroNaNRule float_infzeronan_rule;
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 09a40b43106..afae3906024 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -961,6 +961,7 @@ float128 floatx80_to_float128(floatx80, float_status *status);
| The pattern for an extended double-precision inf.
*----------------------------------------------------------------------------*/
extern const floatx80 floatx80_infinity;
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index f4fed9bfda9..b12ad2b42a9 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1860,7 +1860,8 @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
case float_class_inf:
/* x86 and m68k differ in the setting of the integer bit. */
- frac = floatx80_infinity_low;
+ frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
+ 0 : (1ULL << 63);
exp = fmt->exp_max;
break;
@@ -5144,9 +5145,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
) {
return packFloatx80( zSign, 0x7FFE, ~ roundMask );
}
- return packFloatx80(zSign,
- floatx80_infinity_high,
- floatx80_infinity_low);
+ return floatx80_default_inf(zSign, status);
}
if ( zExp <= 0 ) {
isTiny = status->tininess_before_rounding
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 41dfdf58045..df66e8ba22a 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -107,6 +107,12 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
set_float_2nan_prop_rule(float_2nan_prop_ab, &env->fp_status);
/* Default NaN: sign bit clear, all frac bits set */
set_float_default_nan_pattern(0b01111111, &env->fp_status);
+ /*
+ * m68k-specific floatx80 behaviour:
+ * * default Infinity values have a zero Integer bit
+ */
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
+ &env->fp_status);
nan = floatx80_default_nan(&env->fp_status);
for (i = 0; i < 8; i++) {
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index cbbbab52ba3..73789e97d77 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -227,6 +227,16 @@ floatx80 floatx80_default_nan(float_status *status)
| The pattern for a default generated extended double-precision inf.
*----------------------------------------------------------------------------*/
+floatx80 floatx80_default_inf(bool zSign, float_status *status)
+{
+ /*
+ * Whether the Integer bit is set in the default Infinity is
+ * target dependent.
+ */
+ bool z = status->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero;
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
+}
+
#define floatx80_infinity_high 0x7FFF
#if defined(TARGET_M68K)
#define floatx80_infinity_low UINT64_C(0x0000000000000000)
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime
2025-02-17 12:50 ` [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime Peter Maydell
@ 2025-02-17 18:09 ` Richard Henderson
2025-02-21 14:42 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 18:09 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> Currently we hardcode at compile time whether the floatx80 default
> Infinity value has the explicit integer bit set or not (x86 sets it;
> m68k does not). To be able to compile softfloat once for all targets
> we'd like to move this setting to runtime.
>
> Define a new FloatX80Behaviour enum which is a set of flags that
> define the target's floatx80 handling. Initially we define just one
> flag, for whether the default Infinity has the Integer bit set or
> not, but we will expand this in future commits to cover the other
> floatx80 target specifics that we currently make compile-time
> settings.
>
> Define a new function floatx80_default_inf() which returns the
> appropriate default Infinity value of the given sign, and use it in
> the code that was previously directly using the compile-time constant
> floatx80_infinity_{low,high} values when packing an infinity into a
> floatx80.
>
> Since floatx80 is highly unlikely to be supported in any new
> architecture, and the existing code is generally written as "default
> to like x87, with an ifdef for m68k", we make the default value for
> the floatx80 behaviour flags be "what x87 does". This means we only
> need to change the m68k target to specify the behaviour flags.
>
> (Other users of floatx80 are the Arm NWFPE emulation, which is
> obsolete and probably not actually doing the right thing anyway, and
> the PPC xsrqpxp insn. Making the default be "like x87" avoids our
> needing to review and test for behaviour changes there.)
>
> We will clean up the remaining uses of the floatx80_infinity global
> constant in subsequent commits.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> include/fpu/softfloat-helpers.h | 12 ++++++++++++
> include/fpu/softfloat-types.h | 13 +++++++++++++
> include/fpu/softfloat.h | 1 +
> fpu/softfloat.c | 7 +++----
> target/m68k/cpu.c | 6 ++++++
> fpu/softfloat-specialize.c.inc | 10 ++++++++++
> 6 files changed, 45 insertions(+), 4 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime
2025-02-17 12:50 ` [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime Peter Maydell
2025-02-17 18:09 ` Richard Henderson
@ 2025-02-21 14:42 ` Philippe Mathieu-Daudé
2025-02-21 15:16 ` Peter Maydell
1 sibling, 1 reply; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 14:42 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> Currently we hardcode at compile time whether the floatx80 default
> Infinity value has the explicit integer bit set or not (x86 sets it;
> m68k does not). To be able to compile softfloat once for all targets
> we'd like to move this setting to runtime.
>
> Define a new FloatX80Behaviour enum which is a set of flags that
> define the target's floatx80 handling. Initially we define just one
> flag, for whether the default Infinity has the Integer bit set or
> not, but we will expand this in future commits to cover the other
> floatx80 target specifics that we currently make compile-time
> settings.
>
> Define a new function floatx80_default_inf() which returns the
> appropriate default Infinity value of the given sign, and use it in
> the code that was previously directly using the compile-time constant
> floatx80_infinity_{low,high} values when packing an infinity into a
> floatx80.
>
> Since floatx80 is highly unlikely to be supported in any new
> architecture, and the existing code is generally written as "default
> to like x87, with an ifdef for m68k", we make the default value for
> the floatx80 behaviour flags be "what x87 does". This means we only
> need to change the m68k target to specify the behaviour flags.
>
> (Other users of floatx80 are the Arm NWFPE emulation, which is
> obsolete and probably not actually doing the right thing anyway, and
> the PPC xsrqpxp insn. Making the default be "like x87" avoids our
> needing to review and test for behaviour changes there.)
>
> We will clean up the remaining uses of the floatx80_infinity global
> constant in subsequent commits.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> include/fpu/softfloat-helpers.h | 12 ++++++++++++
> include/fpu/softfloat-types.h | 13 +++++++++++++
> include/fpu/softfloat.h | 1 +
> fpu/softfloat.c | 7 +++----
> target/m68k/cpu.c | 6 ++++++
> fpu/softfloat-specialize.c.inc | 10 ++++++++++
> 6 files changed, 45 insertions(+), 4 deletions(-)
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index f4fed9bfda9..b12ad2b42a9 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -1860,7 +1860,8 @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
>
> case float_class_inf:
> /* x86 and m68k differ in the setting of the integer bit. */
> - frac = floatx80_infinity_low;
> + frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
> + 0 : (1ULL << 63);
Indent off, otherwise:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime
2025-02-21 14:42 ` Philippe Mathieu-Daudé
@ 2025-02-21 15:16 ` Peter Maydell
0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-21 15:16 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On Fri, 21 Feb 2025 at 14:42, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> On 17/2/25 13:50, Peter Maydell wrote:
> > Currently we hardcode at compile time whether the floatx80 default
> > Infinity value has the explicit integer bit set or not (x86 sets it;
> > m68k does not). To be able to compile softfloat once for all targets
> > we'd like to move this setting to runtime.
> >
> > Define a new FloatX80Behaviour enum which is a set of flags that
> > define the target's floatx80 handling. Initially we define just one
> > flag, for whether the default Infinity has the Integer bit set or
> > not, but we will expand this in future commits to cover the other
> > floatx80 target specifics that we currently make compile-time
> > settings.
> >
> > Define a new function floatx80_default_inf() which returns the
> > appropriate default Infinity value of the given sign, and use it in
> > the code that was previously directly using the compile-time constant
> > floatx80_infinity_{low,high} values when packing an infinity into a
> > floatx80.
> >
> > Since floatx80 is highly unlikely to be supported in any new
> > architecture, and the existing code is generally written as "default
> > to like x87, with an ifdef for m68k", we make the default value for
> > the floatx80 behaviour flags be "what x87 does". This means we only
> > need to change the m68k target to specify the behaviour flags.
> >
> > (Other users of floatx80 are the Arm NWFPE emulation, which is
> > obsolete and probably not actually doing the right thing anyway, and
> > the PPC xsrqpxp insn. Making the default be "like x87" avoids our
> > needing to review and test for behaviour changes there.)
> >
> > We will clean up the remaining uses of the floatx80_infinity global
> > constant in subsequent commits.
> >
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> > include/fpu/softfloat-helpers.h | 12 ++++++++++++
> > include/fpu/softfloat-types.h | 13 +++++++++++++
> > include/fpu/softfloat.h | 1 +
> > fpu/softfloat.c | 7 +++----
> > target/m68k/cpu.c | 6 ++++++
> > fpu/softfloat-specialize.c.inc | 10 ++++++++++
> > 6 files changed, 45 insertions(+), 4 deletions(-)
>
>
> > diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> > index f4fed9bfda9..b12ad2b42a9 100644
> > --- a/fpu/softfloat.c
> > +++ b/fpu/softfloat.c
> > @@ -1860,7 +1860,8 @@ static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
> >
> > case float_class_inf:
> > /* x86 and m68k differ in the setting of the integer bit. */
> > - frac = floatx80_infinity_low;
> > + frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
> > + 0 : (1ULL << 63);
>
> Indent off
This is the indent emacs uses here, and it's the usual
"4 spaces in for an expression continued onto the next line"
I think.
-- PMM
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
2025-02-17 12:50 ` [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 18:10 ` Richard Henderson
2025-02-21 13:51 ` Philippe Mathieu-Daudé
2025-02-17 12:50 ` [PATCH 03/10] target/i386: " Peter Maydell
` (10 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
The global const floatx80_infinity is (unlike all the other
float*_infinity values) target-specific, because whether the explicit
Integer bit is set or not varies between m68k and i386. We want to
be able to compile softfloat once for multiple targets, so we can't
continue to use a single global whose value needs to be different
between targets.
Replace the direct uses of floatx80_infinity in target/m68k with
calls to the new floatx80_default_inf() function.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
1 file changed, 16 insertions(+), 31 deletions(-)
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 02dcc03d15d..d1f150e641f 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -142,8 +142,7 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
if ((uint64_t) (aSig << 1)) {
return propagateFloatx80NaN(a, b, status);
}
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
}
if (aExp == 0) {
if (aSig == 0) {
@@ -245,7 +244,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
- return packFloatx80(0, floatx80_infinity.high, floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
if (aExp == 0 && aSig == 0) {
@@ -255,8 +254,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
if (aSign && aExp >= one_exp) {
if (aExp == one_exp && aSig == one_sig) {
float_raise(float_flag_divbyzero, status);
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
}
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
@@ -442,8 +440,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
propagateFloatx80NaNOneArg(a, status);
}
if (aSign == 0) {
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
}
@@ -452,8 +449,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
if (aExp == 0) {
if (aSig == 0) { /* zero */
float_raise(float_flag_divbyzero, status);
- return packFloatx80(1, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(1, status);
}
if ((aSig & one_sig) == 0) { /* denormal */
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
@@ -610,15 +606,13 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
propagateFloatx80NaNOneArg(a, status);
}
if (aSign == 0) {
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
}
if (aExp == 0 && aSig == 0) {
float_raise(float_flag_divbyzero, status);
- return packFloatx80(1, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(1, status);
}
if (aSign) {
@@ -668,16 +662,14 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
propagateFloatx80NaNOneArg(a, status);
}
if (aSign == 0) {
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
}
if (aExp == 0) {
if (aSig == 0) {
float_raise(float_flag_divbyzero, status);
- return packFloatx80(1, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(1, status);
}
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
}
@@ -740,8 +732,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
if (aSign) {
return packFloatx80(0, 0, 0);
}
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
if (aExp == 0 && aSig == 0) {
@@ -924,8 +915,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
if (aSign) {
return packFloatx80(0, 0, 0);
}
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
if (aExp == 0 && aSig == 0) {
@@ -1075,8 +1065,7 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
if (aSign) {
return packFloatx80(0, 0, 0);
}
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
if (aExp == 0 && aSig == 0) {
@@ -2260,8 +2249,7 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
if (compact >= 0x3FFF8000) { /* |X| >= 1 */
if (aExp == one_exp && aSig == one_sig) { /* |X| == 1 */
float_raise(float_flag_divbyzero, status);
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
} else { /* |X| > 1 */
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
@@ -2320,8 +2308,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
if (aSign) {
return packFloatx80(aSign, one_exp, one_sig);
}
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
if (aExp == 0 && aSig == 0) {
@@ -2687,8 +2674,7 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
if ((uint64_t) (aSig << 1)) {
return propagateFloatx80NaNOneArg(a, status);
}
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
}
if (aExp == 0 && aSig == 0) {
@@ -2774,8 +2760,7 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
if ((uint64_t) (aSig << 1)) {
return propagateFloatx80NaNOneArg(a, status);
}
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
}
if (aExp == 0 && aSig == 0) {
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const
2025-02-17 12:50 ` [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const Peter Maydell
@ 2025-02-17 18:10 ` Richard Henderson
2025-02-21 13:51 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 18:10 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> The global const floatx80_infinity is (unlike all the other
> float*_infinity values) target-specific, because whether the explicit
> Integer bit is set or not varies between m68k and i386. We want to
> be able to compile softfloat once for multiple targets, so we can't
> continue to use a single global whose value needs to be different
> between targets.
>
> Replace the direct uses of floatx80_infinity in target/m68k with
> calls to the new floatx80_default_inf() function.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
> 1 file changed, 16 insertions(+), 31 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const
2025-02-17 12:50 ` [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const Peter Maydell
2025-02-17 18:10 ` Richard Henderson
@ 2025-02-21 13:51 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 13:51 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> The global const floatx80_infinity is (unlike all the other
> float*_infinity values) target-specific, because whether the explicit
> Integer bit is set or not varies between m68k and i386. We want to
> be able to compile softfloat once for multiple targets, so we can't
> continue to use a single global whose value needs to be different
> between targets.
>
> Replace the direct uses of floatx80_infinity in target/m68k with
> calls to the new floatx80_default_inf() function.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> target/m68k/softfloat.c | 47 ++++++++++++++---------------------------
> 1 file changed, 16 insertions(+), 31 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 03/10] target/i386: Avoid using floatx80_infinity global const
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
2025-02-17 12:50 ` [PATCH 01/10] fpu: Make targets specify floatx80 default Inf at runtime Peter Maydell
2025-02-17 12:50 ` [PATCH 02/10] target/m68k: Avoid using floatx80_infinity global const Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 18:10 ` Richard Henderson
2025-02-21 13:40 ` Philippe Mathieu-Daudé
2025-02-17 12:50 ` [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear Peter Maydell
` (9 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
The global const floatx80_infinity is (unlike all the other
float*_infinity values) target-specific, because whether the explicit
Integer bit is set or not varies between m68k and i386. We want to
be able to compile softfloat once for multiple targets, so we can't
continue to use a single global whose value needs to be different
between targets.
Replace the direct uses of floatx80_infinity in target/i386 with
calls to the new floatx80_default_inf() function.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/i386/tcg/fpu_helper.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index f112c6c6737..741af09f908 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1832,7 +1832,7 @@ void helper_fxtract(CPUX86State *env)
} else if (floatx80_is_infinity(ST0)) {
fpush(env);
ST0 = ST1;
- ST1 = floatx80_infinity;
+ ST1 = floatx80_default_inf(0, &env->fp_status);
} else {
int expdif;
@@ -2358,9 +2358,8 @@ void helper_fscale(CPUX86State *env)
float_raise(float_flag_invalid, &env->fp_status);
ST0 = floatx80_default_nan(&env->fp_status);
} else {
- ST0 = (floatx80_is_neg(ST0) ?
- floatx80_chs(floatx80_infinity) :
- floatx80_infinity);
+ ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
+ &env->fp_status);
}
}
} else {
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 03/10] target/i386: Avoid using floatx80_infinity global const
2025-02-17 12:50 ` [PATCH 03/10] target/i386: " Peter Maydell
@ 2025-02-17 18:10 ` Richard Henderson
2025-02-21 13:40 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 18:10 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> The global const floatx80_infinity is (unlike all the other
> float*_infinity values) target-specific, because whether the explicit
> Integer bit is set or not varies between m68k and i386. We want to
> be able to compile softfloat once for multiple targets, so we can't
> continue to use a single global whose value needs to be different
> between targets.
>
> Replace the direct uses of floatx80_infinity in target/i386 with
> calls to the new floatx80_default_inf() function.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> target/i386/tcg/fpu_helper.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 03/10] target/i386: Avoid using floatx80_infinity global const
2025-02-17 12:50 ` [PATCH 03/10] target/i386: " Peter Maydell
2025-02-17 18:10 ` Richard Henderson
@ 2025-02-21 13:40 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 13:40 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> The global const floatx80_infinity is (unlike all the other
> float*_infinity values) target-specific, because whether the explicit
> Integer bit is set or not varies between m68k and i386. We want to
> be able to compile softfloat once for multiple targets, so we can't
> continue to use a single global whose value needs to be different
> between targets.
>
> Replace the direct uses of floatx80_infinity in target/i386 with
> calls to the new floatx80_default_inf() function.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> target/i386/tcg/fpu_helper.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
> @@ -2358,9 +2358,8 @@ void helper_fscale(CPUX86State *env)
> float_raise(float_flag_invalid, &env->fp_status);
> ST0 = floatx80_default_nan(&env->fp_status);
> } else {
> - ST0 = (floatx80_is_neg(ST0) ?
> - floatx80_chs(floatx80_infinity) :
> - floatx80_infinity);
> + ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
> + &env->fp_status);
Which expand to:
{
.low = floatx80_default_inf_int_bit_is_zero ? 0 : (1ULL << 63),
.high = (((uint16_t)zSign) << 15) + 0x7fff
}
Effectively equivalent of toggling the sign with floatx80_chs
(the floatx80_chs removal was not obvious, worth mentioning?).
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Review note, as softfloat API methods names are verbose,
float*_chs() could be renamed as _change_sign().
Regards,
Phil.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (2 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 03/10] target/i386: " Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 18:13 ` Richard Henderson
2025-02-21 13:12 ` Philippe Mathieu-Daudé
2025-02-17 12:50 ` [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime Peter Maydell
` (8 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
In Intel terminology, a floatx80 Infinity with the explicit integer
bit clear is a "pseudo-infinity"; for x86 these are not valid
infinity values. m68k is looser and does not care whether the
Integer bit is set or clear in an infinity.
Move this setting to runtime rather than using an ifdef in
floatx80_is_infinity(). (This requires us to pass in the
float_status to that function now.)
Since this was the last use of the floatx80_infinity global constant,
we remove it and its definition here.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/fpu/softfloat-types.h | 5 +++++
include/fpu/softfloat.h | 20 ++++++++++++--------
target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
target/m68k/cpu.c | 4 +++-
target/m68k/fpu_helper.c | 2 +-
fpu/softfloat-specialize.c.inc | 10 ----------
6 files changed, 32 insertions(+), 29 deletions(-)
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index dd22ecdbe60..e1732beba4f 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -330,6 +330,11 @@ typedef enum __attribute__((__packed__)) {
typedef enum __attribute__((__packed__)) {
/* In the default Infinity value, is the Integer bit 0 ? */
floatx80_default_inf_int_bit_is_zero = 1,
+ /*
+ * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
+ * If so, floatx80_is_infinity() will return true for them.
+ */
+ floatx80_pseudo_inf_valid = 2,
} FloatX80Behaviour;
/*
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index afae3906024..07259c59303 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -960,7 +960,6 @@ float128 floatx80_to_float128(floatx80, float_status *status);
/*----------------------------------------------------------------------------
| The pattern for an extended double-precision inf.
*----------------------------------------------------------------------------*/
-extern const floatx80 floatx80_infinity;
floatx80 floatx80_default_inf(bool zSign, float_status *status);
/*----------------------------------------------------------------------------
@@ -996,14 +995,19 @@ static inline floatx80 floatx80_chs(floatx80 a)
return a;
}
-static inline bool floatx80_is_infinity(floatx80 a)
+static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
{
-#if defined(TARGET_M68K)
- return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
-#else
- return (a.high & 0x7fff) == floatx80_infinity.high &&
- a.low == floatx80_infinity.low;
-#endif
+ /*
+ * It's target-specific whether the Integer bit is permitted
+ * to be 0 in a valid Infinity value. (x86 says no, m68k says yes).
+ */
+ bool intbit = a.low >> 63;
+
+ if (!intbit &&
+ !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
+ return false;
+ }
+ return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
}
static inline bool floatx80_is_neg(floatx80 a)
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 741af09f908..3b79bc049d1 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1393,7 +1393,8 @@ void helper_fpatan(CPUX86State *env)
/* Pass this NaN through. */
} else if (floatx80_is_zero(ST1) && !arg0_sign) {
/* Pass this zero through. */
- } else if (((floatx80_is_infinity(ST0) && !floatx80_is_infinity(ST1)) ||
+ } else if (((floatx80_is_infinity(ST0, &env->fp_status) &&
+ !floatx80_is_infinity(ST1, &env->fp_status)) ||
arg0_exp - arg1_exp >= 80) &&
!arg0_sign) {
/*
@@ -1442,8 +1443,8 @@ void helper_fpatan(CPUX86State *env)
rexp = pi_exp;
rsig0 = pi_sig_high;
rsig1 = pi_sig_low;
- } else if (floatx80_is_infinity(ST1)) {
- if (floatx80_is_infinity(ST0)) {
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
if (arg0_sign) {
rexp = pi_34_exp;
rsig0 = pi_34_sig_high;
@@ -1462,7 +1463,8 @@ void helper_fpatan(CPUX86State *env)
rexp = pi_2_exp;
rsig0 = pi_2_sig_high;
rsig1 = pi_2_sig_low;
- } else if (floatx80_is_infinity(ST0) || arg0_exp - arg1_exp >= 80) {
+ } else if (floatx80_is_infinity(ST0, &env->fp_status) ||
+ arg0_exp - arg1_exp >= 80) {
/* ST0 is negative. */
rexp = pi_exp;
rsig0 = pi_sig_high;
@@ -1829,7 +1831,7 @@ void helper_fxtract(CPUX86State *env)
}
fpush(env);
ST0 = ST1;
- } else if (floatx80_is_infinity(ST0)) {
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
fpush(env);
ST0 = ST1;
ST1 = floatx80_default_inf(0, &env->fp_status);
@@ -2173,7 +2175,7 @@ void helper_fyl2x(CPUX86State *env)
} else if (arg0_sign && !floatx80_is_zero(ST0)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_default_nan(&env->fp_status);
- } else if (floatx80_is_infinity(ST1)) {
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
FloatRelation cmp = floatx80_compare(ST0, floatx80_one,
&env->fp_status);
switch (cmp) {
@@ -2188,7 +2190,7 @@ void helper_fyl2x(CPUX86State *env)
ST1 = floatx80_default_nan(&env->fp_status);
break;
}
- } else if (floatx80_is_infinity(ST0)) {
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
if (floatx80_is_zero(ST1)) {
float_raise(float_flag_invalid, &env->fp_status);
ST1 = floatx80_default_nan(&env->fp_status);
@@ -2341,11 +2343,11 @@ void helper_fscale(CPUX86State *env)
float_raise(float_flag_invalid, &env->fp_status);
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
}
- } else if (floatx80_is_infinity(ST1) &&
+ } else if (floatx80_is_infinity(ST1, &env->fp_status) &&
!floatx80_invalid_encoding(ST0) &&
!floatx80_is_any_nan(ST0)) {
if (floatx80_is_neg(ST1)) {
- if (floatx80_is_infinity(ST0)) {
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST0 = floatx80_default_nan(&env->fp_status);
} else {
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index df66e8ba22a..56b23de21fe 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -110,8 +110,10 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
/*
* m68k-specific floatx80 behaviour:
* * default Infinity values have a zero Integer bit
+ * * input Infinities may have the Integer bit either 0 or 1
*/
- set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
+ floatx80_pseudo_inf_valid,
&env->fp_status);
nan = floatx80_default_nan(&env->fp_status);
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 339b73ad7dc..eb1cb8c6872 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -455,7 +455,7 @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
if (floatx80_is_any_nan(val->d)) {
cc |= FPSR_CC_A;
- } else if (floatx80_is_infinity(val->d)) {
+ } else if (floatx80_is_infinity(val->d, &env->fp_status)) {
cc |= FPSR_CC_I;
} else if (floatx80_is_zero(val->d)) {
cc |= FPSR_CC_Z;
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 73789e97d77..8327f727861 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -237,16 +237,6 @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
}
-#define floatx80_infinity_high 0x7FFF
-#if defined(TARGET_M68K)
-#define floatx80_infinity_low UINT64_C(0x0000000000000000)
-#else
-#define floatx80_infinity_low UINT64_C(0x8000000000000000)
-#endif
-
-const floatx80 floatx80_infinity
- = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
-
/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear
2025-02-17 12:50 ` [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear Peter Maydell
@ 2025-02-17 18:13 ` Richard Henderson
2025-02-21 13:12 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 18:13 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> In Intel terminology, a floatx80 Infinity with the explicit integer
> bit clear is a "pseudo-infinity"; for x86 these are not valid
> infinity values. m68k is looser and does not care whether the
> Integer bit is set or clear in an infinity.
>
> Move this setting to runtime rather than using an ifdef in
> floatx80_is_infinity(). (This requires us to pass in the
> float_status to that function now.)
>
> Since this was the last use of the floatx80_infinity global constant,
> we remove it and its definition here.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> include/fpu/softfloat-types.h | 5 +++++
> include/fpu/softfloat.h | 20 ++++++++++++--------
> target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
> target/m68k/cpu.c | 4 +++-
> target/m68k/fpu_helper.c | 2 +-
> fpu/softfloat-specialize.c.inc | 10 ----------
> 6 files changed, 32 insertions(+), 29 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear
2025-02-17 12:50 ` [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear Peter Maydell
2025-02-17 18:13 ` Richard Henderson
@ 2025-02-21 13:12 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 13:12 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> In Intel terminology, a floatx80 Infinity with the explicit integer
> bit clear is a "pseudo-infinity"; for x86 these are not valid
> infinity values. m68k is looser and does not care whether the
> Integer bit is set or clear in an infinity.
>
> Move this setting to runtime rather than using an ifdef in
> floatx80_is_infinity(). (This requires us to pass in the
> float_status to that function now.)
>
> Since this was the last use of the floatx80_infinity global constant,
> we remove it and its definition here.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
> include/fpu/softfloat-types.h | 5 +++++
> include/fpu/softfloat.h | 20 ++++++++++++--------
> target/i386/tcg/fpu_helper.c | 20 +++++++++++---------
> target/m68k/cpu.c | 4 +++-
> target/m68k/fpu_helper.c | 2 +-
> fpu/softfloat-specialize.c.inc | 10 ----------
> 6 files changed, 32 insertions(+), 29 deletions(-)
Passing float_status argument to floatx80_is_infinity in a preliminary
patch, this becomes simpler (to my taste...):
4 files changed, 19 insertions(+), 18 deletions(-)
-- >8 --
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index dd22ecdbe60..e1732beba4f 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -332,0 +333,5 @@ typedef enum __attribute__((__packed__)) {
+ /*
+ * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
+ * If so, floatx80_is_infinity() will return true for them.
+ */
+ floatx80_pseudo_inf_valid = 2,
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 1fa759779ea..1c8f3cbb78d 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -963 +962,0 @@ float128 floatx80_to_float128(floatx80, float_status
*status);
-extern const floatx80 floatx80_infinity;
@@ -1001,6 +1000,11 @@ static inline bool floatx80_is_infinity(floatx80
a, float_status *status)
-#if defined(TARGET_M68K)
- return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
-#else
- return (a.high & 0x7fff) == floatx80_infinity.high &&
- a.low == floatx80_infinity.low;
-#endif
+ /*
+ * It's target-specific whether the Integer bit is permitted
+ * to be 0 in a valid Infinity value. (x86 says no, m68k says yes).
+ */
+ bool intbit = a.low >> 63;
+
+ if (!intbit &&
+ !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
+ return false;
+ }
+ return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index df66e8ba22a..56b23de21fe 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -112,0 +113 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType
type)
+ * * input Infinities may have the Integer bit either 0 or 1
@@ -114 +115,2 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType
type)
- set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
+ floatx80_pseudo_inf_valid,
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 73789e97d77..8327f727861 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -240,10 +239,0 @@ floatx80 floatx80_default_inf(bool zSign,
float_status *status)
-#define floatx80_infinity_high 0x7FFF
-#if defined(TARGET_M68K)
-#define floatx80_infinity_low UINT64_C(0x0000000000000000)
-#else
-#define floatx80_infinity_low UINT64_C(0x8000000000000000)
-#endif
-
-const floatx80 floatx80_infinity
- = make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
-
---
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (3 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 04/10] fpu: Make targets specify whether floatx80 Inf can have Int bit clear Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 18:45 ` Richard Henderson
2025-02-21 13:14 ` Philippe Mathieu-Daudé
2025-02-17 12:50 ` [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour Peter Maydell
` (7 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Because floatx80 has an explicit integer bit, this permits some
odd encodings where the integer bit is not set correctly for the
floating point value type. In In Intel terminology the
categories are:
exp == 0, int = 0, mantissa == 0 : zeroes
exp == 0, int = 0, mantissa != 0 : denormals
exp == 0, int = 1 : pseudo-denormals
0 < exp < 0x7fff, int = 0 : unnormals
0 < exp < 0x7fff, int = 1 : normals
exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
exp == 0x7fff, int = 1, mantissa == 0 : infinities
exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
exp == 0x7fff, int = 1, mantissa == 0 : NaNs
The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
x87 permits as input also pseudo-denormals.
m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
Currently we have an ifdef in floatx80_invalid_encoding() to select
the x86 vs m68k behaviour. Add new floatx80_behaviour flags to
select whether pseudo-NaN and unnormal are valid, and use these
(plus the existing pseudo_inf_valid flag) to decide whether these
encodings are invalid at runtime.
We leave pseudo-denormals as always-valid, since both x86 and m68k
accept them.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/fpu/softfloat-types.h | 14 +++++++
include/fpu/softfloat.h | 70 ++++++++++++++++++-----------------
fpu/softfloat.c | 2 +-
target/i386/tcg/fpu_helper.c | 24 ++++++------
target/m68k/cpu.c | 28 +++++++++++++-
5 files changed, 92 insertions(+), 46 deletions(-)
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index e1732beba4f..b1941384aef 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -333,8 +333,22 @@ typedef enum __attribute__((__packed__)) {
/*
* Are Pseudo-infinities (Inf with the Integer bit zero) valid?
* If so, floatx80_is_infinity() will return true for them.
+ * If not, floatx80_invalid_encoding will return false for them,
+ * and using them as inputs to a float op will raise Invalid.
*/
floatx80_pseudo_inf_valid = 2,
+ /*
+ * Are Pseudo-NaNs (NaNs where the Integer bit is zero) valid?
+ * If not, floatx80_invalid_encoding() will return false for them,
+ * and using them as inputs to a float op will raise Invalid.
+ */
+ floatx80_pseudo_nan_valid = 4,
+ /*
+ * Are Unnormals (0 < exp < 0x7fff, Integer bit zero) valid?
+ * If not, floatx80_invalid_encoding() will return false for them,
+ * and using them as inputs to a float op will raise Invalid.
+ */
+ floatx80_unnormal_valid = 8,
} FloatX80Behaviour;
/*
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 07259c59303..c18ab2cb609 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -1073,41 +1073,45 @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
/*----------------------------------------------------------------------------
| Return whether the given value is an invalid floatx80 encoding.
-| Invalid floatx80 encodings arise when the integer bit is not set, but
-| the exponent is not zero. The only times the integer bit is permitted to
-| be zero is in subnormal numbers and the value zero.
-| This includes what the Intel software developer's manual calls pseudo-NaNs,
-| pseudo-infinities and un-normal numbers. It does not include
-| pseudo-denormals, which must still be correctly handled as inputs even
-| if they are never generated as outputs.
+| Invalid floatx80 encodings may arise when the integer bit is not set
+| correctly; this is target-specific. In Intel terminology the
+| categories are:
+| exp == 0, int = 0, mantissa == 0 : zeroes
+| exp == 0, int = 0, mantissa != 0 : denormals
+| exp == 0, int = 1 : pseudo-denormals
+| 0 < exp < 0x7fff, int = 0 : unnormals
+| 0 < exp < 0x7fff, int = 1 : normals
+| exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
+| exp == 0x7fff, int = 1, mantissa == 0 : infinities
+| exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
+| exp == 0x7fff, int = 1, mantissa == 0 : NaNs
+|
+| The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
+| x87 permits as input also pseudo-denormals.
+| m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
+|
+| Since we don't have a target that handles floatx80 but prohibits
+| pseudo-denormals in input, we don't currently have a floatx80_behaviour
+| flag for that case, but instead always accept it. Conveniently this
+| means that all cases with either exponent 0 or the integer bit set are
+| valid for all targets.
*----------------------------------------------------------------------------*/
-static inline bool floatx80_invalid_encoding(floatx80 a)
+static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
{
-#if defined(TARGET_M68K)
- /*-------------------------------------------------------------------------
- | With m68k, the explicit integer bit can be zero in the case of:
- | - zeros (exp == 0, mantissa == 0)
- | - denormalized numbers (exp == 0, mantissa != 0)
- | - unnormalized numbers (exp != 0, exp < 0x7FFF)
- | - infinities (exp == 0x7FFF, mantissa == 0)
- | - not-a-numbers (exp == 0x7FFF, mantissa != 0)
- |
- | For infinities and NaNs, the explicit integer bit can be either one or
- | zero.
- |
- | The IEEE 754 standard does not define a zero integer bit. Such a number
- | is an unnormalized number. Hardware does not directly support
- | denormalized and unnormalized numbers, but implicitly supports them by
- | trapping them as unimplemented data types, allowing efficient conversion
- | in software.
- |
- | See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
- | "1.6 FLOATING-POINT DATA TYPES"
- *------------------------------------------------------------------------*/
- return false;
-#else
- return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0;
-#endif
+ if ((a.low >> 63) || (a.high & 0x7fff) == 0) {
+ /* Anything with the Integer bit set or the exponent 0 is valid */
+ return false;
+ }
+
+ if ((a.high & 0x7fff) == 0x7fff) {
+ if (a.low) {
+ return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
+ } else {
+ return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
+ }
+ } else {
+ return !(s->floatx80_behaviour & floatx80_unnormal_valid);
+ }
}
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b12ad2b42a9..2a20ae871eb 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1810,7 +1810,7 @@ static bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f,
g_assert_not_reached();
}
- if (unlikely(floatx80_invalid_encoding(f))) {
+ if (unlikely(floatx80_invalid_encoding(f, s))) {
float_raise(float_flag_invalid, s);
return false;
}
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 3b79bc049d1..4858ae9a5fb 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1141,7 +1141,7 @@ void helper_f2xm1(CPUX86State *env)
int32_t exp = extractFloatx80Exp(ST0);
bool sign = extractFloatx80Sign(ST0);
- if (floatx80_invalid_encoding(ST0)) {
+ if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST0 = floatx80_default_nan(&env->fp_status);
} else if (floatx80_is_any_nan(ST0)) {
@@ -1383,8 +1383,8 @@ void helper_fpatan(CPUX86State *env)
} 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) ||
- floatx80_invalid_encoding(ST1)) {
+ } 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)) {
@@ -1819,7 +1819,7 @@ void helper_fxtract(CPUX86State *env)
&env->fp_status);
fpush(env);
ST0 = temp.d;
- } else if (floatx80_invalid_encoding(ST0)) {
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST0 = floatx80_default_nan(&env->fp_status);
fpush(env);
@@ -1870,7 +1870,8 @@ static void helper_fprem_common(CPUX86State *env, bool mod)
env->fpus &= ~0x4700; /* (C3,C2,C1,C0) <-- 0000 */
if (floatx80_is_zero(ST0) || floatx80_is_zero(ST1) ||
exp0 == 0x7fff || exp1 == 0x7fff ||
- floatx80_invalid_encoding(ST0) || floatx80_invalid_encoding(ST1)) {
+ floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
ST0 = floatx80_modrem(ST0, ST1, mod, "ient, &env->fp_status);
} else {
if (exp0 == 0) {
@@ -2066,8 +2067,8 @@ void helper_fyl2xp1(CPUX86State *env)
} 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) ||
- floatx80_invalid_encoding(ST1)) {
+ } 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)) {
@@ -2164,8 +2165,8 @@ void helper_fyl2x(CPUX86State *env)
} 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) ||
- floatx80_invalid_encoding(ST1)) {
+ } 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)) {
@@ -2331,7 +2332,8 @@ void helper_frndint(CPUX86State *env)
void helper_fscale(CPUX86State *env)
{
uint8_t old_flags = save_exception_flags(env);
- if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) {
+ if (floatx80_invalid_encoding(ST1, &env->fp_status) ||
+ floatx80_invalid_encoding(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
ST0 = floatx80_default_nan(&env->fp_status);
} else if (floatx80_is_any_nan(ST1)) {
@@ -2344,7 +2346,7 @@ void helper_fscale(CPUX86State *env)
ST0 = floatx80_silence_nan(ST0, &env->fp_status);
}
} else if (floatx80_is_infinity(ST1, &env->fp_status) &&
- !floatx80_invalid_encoding(ST0) &&
+ !floatx80_invalid_encoding(ST0, &env->fp_status) &&
!floatx80_is_any_nan(ST0)) {
if (floatx80_is_neg(ST1)) {
if (floatx80_is_infinity(ST0, &env->fp_status)) {
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 56b23de21fe..505fa97a53f 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -111,9 +111,35 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
* m68k-specific floatx80 behaviour:
* * default Infinity values have a zero Integer bit
* * input Infinities may have the Integer bit either 0 or 1
+ * * pseudo-denormals supported for input and output
+ * * don't raise Invalid for pseudo-NaN/pseudo-Inf/Unnormal
+ *
+ * With m68k, the explicit integer bit can be zero in the case of:
+ * - zeros (exp == 0, mantissa == 0)
+ * - denormalized numbers (exp == 0, mantissa != 0)
+ * - unnormalized numbers (exp != 0, exp < 0x7FFF)
+ * - infinities (exp == 0x7FFF, mantissa == 0)
+ * - not-a-numbers (exp == 0x7FFF, mantissa != 0)
+ *
+ * For infinities and NaNs, the explicit integer bit can be either one or
+ * zero.
+ *
+ * The IEEE 754 standard does not define a zero integer bit. Such a number
+ * is an unnormalized number. Hardware does not directly support
+ * denormalized and unnormalized numbers, but implicitly supports them by
+ * trapping them as unimplemented data types, allowing efficient conversion
+ * in software.
+ *
+ * See "M68000 FAMILY PROGRAMMER’S REFERENCE MANUAL",
+ * "1.6 FLOATING-POINT DATA TYPES"
+ *
+ * Note though that QEMU's fp emulation does directly handle both
+ * denormal and unnormal values, and does not trap to guest software.
*/
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
- floatx80_pseudo_inf_valid,
+ floatx80_pseudo_inf_valid |
+ floatx80_pseudo_nan_valid |
+ floatx80_unnormal_valid,
&env->fp_status);
nan = floatx80_default_nan(&env->fp_status);
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime
2025-02-17 12:50 ` [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime Peter Maydell
@ 2025-02-17 18:45 ` Richard Henderson
2025-02-21 13:14 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 18:45 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> Because floatx80 has an explicit integer bit, this permits some
> odd encodings where the integer bit is not set correctly for the
> floating point value type. In In Intel terminology the
> categories are:
> exp == 0, int = 0, mantissa == 0 : zeroes
> exp == 0, int = 0, mantissa != 0 : denormals
> exp == 0, int = 1 : pseudo-denormals
> 0 < exp < 0x7fff, int = 0 : unnormals
> 0 < exp < 0x7fff, int = 1 : normals
> exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
> exp == 0x7fff, int = 1, mantissa == 0 : infinities
> exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
> exp == 0x7fff, int = 1, mantissa == 0 : NaNs
>
> The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
> x87 permits as input also pseudo-denormals.
> m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
>
> Currently we have an ifdef in floatx80_invalid_encoding() to select
> the x86 vs m68k behaviour. Add new floatx80_behaviour flags to
> select whether pseudo-NaN and unnormal are valid, and use these
> (plus the existing pseudo_inf_valid flag) to decide whether these
> encodings are invalid at runtime.
>
> We leave pseudo-denormals as always-valid, since both x86 and m68k
> accept them.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> include/fpu/softfloat-types.h | 14 +++++++
> include/fpu/softfloat.h | 70 ++++++++++++++++++-----------------
> fpu/softfloat.c | 2 +-
> target/i386/tcg/fpu_helper.c | 24 ++++++------
> target/m68k/cpu.c | 28 +++++++++++++-
> 5 files changed, 92 insertions(+), 46 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime
2025-02-17 12:50 ` [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime Peter Maydell
2025-02-17 18:45 ` Richard Henderson
@ 2025-02-21 13:14 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 13:14 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> Because floatx80 has an explicit integer bit, this permits some
> odd encodings where the integer bit is not set correctly for the
> floating point value type. In In Intel terminology the
> categories are:
> exp == 0, int = 0, mantissa == 0 : zeroes
> exp == 0, int = 0, mantissa != 0 : denormals
> exp == 0, int = 1 : pseudo-denormals
> 0 < exp < 0x7fff, int = 0 : unnormals
> 0 < exp < 0x7fff, int = 1 : normals
> exp == 0x7fff, int = 0, mantissa == 0 : pseudo-infinities
> exp == 0x7fff, int = 1, mantissa == 0 : infinities
> exp == 0x7fff, int = 0, mantissa != 0 : pseudo-NaNs
> exp == 0x7fff, int = 1, mantissa == 0 : NaNs
>
> The usual IEEE cases of zero, denormal, normal, inf and NaN are always valid.
> x87 permits as input also pseudo-denormals.
> m68k permits all those and also pseudo-infinities, pseudo-NaNs and unnormals.
>
> Currently we have an ifdef in floatx80_invalid_encoding() to select
> the x86 vs m68k behaviour. Add new floatx80_behaviour flags to
> select whether pseudo-NaN and unnormal are valid, and use these
> (plus the existing pseudo_inf_valid flag) to decide whether these
> encodings are invalid at runtime.
>
> We leave pseudo-denormals as always-valid, since both x86 and m68k
> accept them.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
> include/fpu/softfloat-types.h | 14 +++++++
> include/fpu/softfloat.h | 70 ++++++++++++++++++-----------------
> fpu/softfloat.c | 2 +-
> target/i386/tcg/fpu_helper.c | 24 ++++++------
> target/m68k/cpu.c | 28 +++++++++++++-
> 5 files changed, 92 insertions(+), 46 deletions(-)
Again, passing float_status argument to floatx80_invalid_encoding
in a preliminary patch:
3 files changed, 77 insertions(+), 33 deletions(-)
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (4 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 05/10] fpu: Make floatx80 invalid encoding settable at runtime Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 19:14 ` Richard Henderson
2025-02-17 12:50 ` [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime Peter Maydell
` (6 subsequent siblings)
12 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
for floatx80 for m68k. This controls our handling of what the Intel
documentation calls a "pseudo-denormal": a value where the exponent
field is zero and the explicit integer bit is set.
For x86, the x87 FPU is supposed to accept a pseudo-denormal as
input, but never generate one on output. For m68k, these values are
permitted on input and may be produced on output.
Replace the flag in the FloatFmt with a flag indicating whether the
float format has an explicit bit (which will be true for floatx80 for
all targets, and false for every other float type). Then we can gate
the handling of these pseudo-denormals on the setting of a
floatx80_behaviour flag.
As far as I can see from the code we don't actually handle the
x86-mandated "accept on input but don't generate" behaviour, because
the handling in partsN(canonicalize) looked at fmt->m68k_denormal.
So I have added TODO comments to that effect.
This commit doesn't change any behaviour for any target.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
I'm confident this commit preserves existing behaviour, but
somewhat less confident that I've correctly analysed what our
current code does, in particular that it doesn't do the x86
mandated "handle pseudo-denormals on input" part.
---
include/fpu/softfloat-types.h | 10 ++++++++++
fpu/softfloat.c | 9 ++++-----
target/m68k/cpu.c | 3 ++-
fpu/softfloat-parts.c.inc | 20 +++++++++++++++++---
4 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index b1941384aef..f57c7193653 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -349,6 +349,16 @@ typedef enum __attribute__((__packed__)) {
* and using them as inputs to a float op will raise Invalid.
*/
floatx80_unnormal_valid = 8,
+ /*
+ * If the exponent is 0 and the Integer bit is set, Intel call
+ * this a "pseudo-denormal"; x86 supports that only on input
+ * (treating them as denormals). m68k calls these a type of
+ * normalized number, and may both input and output them.
+ * TODO: currently we only support "handle on both input and
+ * output" or "don't handle and don't generate".
+ * floatx80_invalid_encoding() will always accept them.
+ */
+ floatx80_pseudo_denormal_output_valid = 16,
} FloatX80Behaviour;
/*
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 2a20ae871eb..b299cfaf860 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -537,7 +537,8 @@ typedef struct {
* round_mask: bits below lsb which must be rounded
* The following optional modifiers are available:
* arm_althp: handle ARM Alternative Half Precision
- * m68k_denormal: explicit integer bit for extended precision may be 1
+ * has_explicit_bit: has an explicit integer bit; this affects whether
+ * the float_status floatx80_behaviour handling applies
*/
typedef struct {
int exp_size;
@@ -547,7 +548,7 @@ typedef struct {
int frac_size;
int frac_shift;
bool arm_althp;
- bool m68k_denormal;
+ bool has_explicit_bit;
uint64_t round_mask;
} FloatFmt;
@@ -600,9 +601,7 @@ static const FloatFmt floatx80_params[3] = {
[floatx80_precision_d] = { FLOATX80_PARAMS(52) },
[floatx80_precision_x] = {
FLOATX80_PARAMS(64),
-#ifdef TARGET_M68K
- .m68k_denormal = true,
-#endif
+ .has_explicit_bit = true,
},
};
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 505fa97a53f..b21813a1b96 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -139,7 +139,8 @@ static void m68k_cpu_reset_hold(Object *obj, ResetType type)
set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero |
floatx80_pseudo_inf_valid |
floatx80_pseudo_nan_valid |
- floatx80_unnormal_valid,
+ floatx80_unnormal_valid |
+ floatx80_pseudo_denormal_output_valid,
&env->fp_status);
nan = floatx80_default_nan(&env->fp_status);
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 1d09f066c5d..6abd6b28b85 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -195,6 +195,18 @@ static FloatPartsN *partsN(pick_nan_muladd)(FloatPartsN *a, FloatPartsN *b,
static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
const FloatFmt *fmt)
{
+ /*
+ * It's target-dependent whether exponent 0 and Integer bit set
+ * is valid. TODO: the x86 manual says that the x87 FPU will
+ * accept these on inputs, treating them as denormals, but will
+ * never output them. However we seem to not handle them on
+ * either input or output. Also we think of them as denormal
+ * numbers for m68k, though that doesn't matter since m68k doesn't
+ * use the input_denormal_used flag.
+ */
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
+ (status->floatx80_behaviour & floatx80_pseudo_denormal_output_valid);
+
if (unlikely(p->exp == 0)) {
if (likely(frac_eqz(p))) {
p->cls = float_class_zero;
@@ -206,7 +218,7 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
int shift = frac_normalize(p);
p->cls = float_class_denormal;
p->exp = fmt->frac_shift - fmt->exp_bias
- - shift + !fmt->m68k_denormal;
+ - shift + !has_pseudo_denormals;
}
} else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) {
p->cls = float_class_normal;
@@ -342,13 +354,15 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
frac_clear(p);
} else {
bool is_tiny = s->tininess_before_rounding || exp < 0;
+ bool has_pseudo_denormals = fmt->has_explicit_bit &&
+ (s->floatx80_behaviour & floatx80_pseudo_denormal_output_valid);
if (!is_tiny) {
FloatPartsN discard;
is_tiny = !frac_addi(&discard, p, inc);
}
- frac_shrjam(p, !fmt->m68k_denormal - exp);
+ frac_shrjam(p, !has_pseudo_denormals - exp);
if (p->frac_lo & round_mask) {
/* Need to recompute round-to-even/round-to-odd. */
@@ -379,7 +393,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
p->frac_lo &= ~round_mask;
}
- exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !fmt->m68k_denormal;
+ exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) && !has_pseudo_denormals;
frac_shr(p, frac_shift);
if (is_tiny) {
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-17 12:50 ` [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour Peter Maydell
@ 2025-02-17 19:14 ` Richard Henderson
2025-02-20 17:12 ` Peter Maydell
0 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 19:14 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
> for floatx80 for m68k. This controls our handling of what the Intel
> documentation calls a "pseudo-denormal": a value where the exponent
> field is zero and the explicit integer bit is set.
>
> For x86, the x87 FPU is supposed to accept a pseudo-denormal as
> input, but never generate one on output. For m68k, these values are
> permitted on input and may be produced on output.
>
> Replace the flag in the FloatFmt with a flag indicating whether the
> float format has an explicit bit (which will be true for floatx80 for
> all targets, and false for every other float type). Then we can gate
> the handling of these pseudo-denormals on the setting of a
> floatx80_behaviour flag.
>
> As far as I can see from the code we don't actually handle the
> x86-mandated "accept on input but don't generate" behaviour, because
> the handling in partsN(canonicalize) looked at fmt->m68k_denormal.
> So I have added TODO comments to that effect.
>
> This commit doesn't change any behaviour for any target.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> I'm confident this commit preserves existing behaviour, but
> somewhat less confident that I've correctly analysed what our
> current code does, in particular that it doesn't do the x86
> mandated "handle pseudo-denormals on input" part.
Test case:
#include <stdio.h>
int main()
{
union {
struct {
unsigned long long m;
unsigned short e;
} i;
long double f;
} u[2] = { };
unsigned short sw;
asm volatile("fnclex" : : : "memory");
u[0].i.m = 0xc000000000000000ull;
u[0].f += u[1].f; /* denormal + zero -> renormalize */
asm volatile("fstsw %w0" : "=a"(sw) : : "memory");
printf("%04x %016llx %04x\n", u[0].i.e, u[0].i.m, sw);
return 0;
}
Expected behaviour is setting DE for consuming a denormal.
As you say, this patch preserves existing behaviour so,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-17 19:14 ` Richard Henderson
@ 2025-02-20 17:12 ` Peter Maydell
2025-02-20 18:39 ` Richard Henderson
0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2025-02-20 17:12 UTC (permalink / raw)
To: Richard Henderson
Cc: qemu-devel, Alex Bennée, Paolo Bonzini, Eduardo Habkost,
Laurent Vivier
On Mon, 17 Feb 2025 at 19:14, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 2/17/25 04:50, Peter Maydell wrote:
> > Currently we compile-time set an 'm68k_denormal' flag in the FloatFmt
> > for floatx80 for m68k. This controls our handling of what the Intel
> > documentation calls a "pseudo-denormal": a value where the exponent
> > field is zero and the explicit integer bit is set.
> >
> > For x86, the x87 FPU is supposed to accept a pseudo-denormal as
> > input, but never generate one on output. For m68k, these values are
> > permitted on input and may be produced on output.
> >
> > Replace the flag in the FloatFmt with a flag indicating whether the
> > float format has an explicit bit (which will be true for floatx80 for
> > all targets, and false for every other float type). Then we can gate
> > the handling of these pseudo-denormals on the setting of a
> > floatx80_behaviour flag.
> >
> > As far as I can see from the code we don't actually handle the
> > x86-mandated "accept on input but don't generate" behaviour, because
> > the handling in partsN(canonicalize) looked at fmt->m68k_denormal.
> > So I have added TODO comments to that effect.
> >
> > This commit doesn't change any behaviour for any target.
> >
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> > I'm confident this commit preserves existing behaviour, but
> > somewhat less confident that I've correctly analysed what our
> > current code does, in particular that it doesn't do the x86
> > mandated "handle pseudo-denormals on input" part.
>
> Test case:
>
> #include <stdio.h>
>
> int main()
> {
> union {
> struct {
> unsigned long long m;
> unsigned short e;
> } i;
> long double f;
> } u[2] = { };
> unsigned short sw;
>
> asm volatile("fnclex" : : : "memory");
>
> u[0].i.m = 0xc000000000000000ull;
> u[0].f += u[1].f; /* denormal + zero -> renormalize */
>
> asm volatile("fstsw %w0" : "=a"(sw) : : "memory");
>
> printf("%04x %016llx %04x\n", u[0].i.e, u[0].i.m, sw);
> return 0;
> }
>
> Expected behaviour is setting DE for consuming a denormal.
So, on real hardware I see
0001 c000000000000000 0002
and on QEMU, with the patchset that fixes the DE bit handling
https://patchew.org/QEMU/20250213142613.151308-1-peter.maydell@linaro.org/
I also see the same thing.
That suggests that we are correctly implementing the x87
required behaviour in QEMU, and so that the TODO comment
I add in this patch isn't right. But then I'm a bit confused
about what the code is actually doing. Why do we need to look
at fmt->m68k_denormal in the input (canonicalize) code (i.e.
to have different behaviour here for x86 and m68k), if
both x86 and m68k accept these pseudodenormals as input?
Is the difference that for x86 we accept but canonicalize
into the equivalent normal number immediately on input,
whereas for m68k we accept and leave the pseudodenormal
as a pseudodenormal (well, m68k calls these a kind of
normal number) ?
thanks
-- PMM
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-20 17:12 ` Peter Maydell
@ 2025-02-20 18:39 ` Richard Henderson
2025-02-20 18:54 ` Peter Maydell
0 siblings, 1 reply; 43+ messages in thread
From: Richard Henderson @ 2025-02-20 18:39 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Alex Bennée, Paolo Bonzini, Eduardo Habkost,
Laurent Vivier
On 2/20/25 09:12, Peter Maydell wrote:
> That suggests that we are correctly implementing the x87
> required behaviour in QEMU, and so that the TODO comment
> I add in this patch isn't right. But then I'm a bit confused
> about what the code is actually doing. Why do we need to look
> at fmt->m68k_denormal in the input (canonicalize) code (i.e.
> to have different behaviour here for x86 and m68k), if
> both x86 and m68k accept these pseudodenormals as input?
>
> Is the difference that for x86 we accept but canonicalize
> into the equivalent normal number immediately on input,
> whereas for m68k we accept and leave the pseudodenormal
> as a pseudodenormal (well, m68k calls these a kind of
> normal number) ?
The difference is in interpretation: x86 ignores the explicit integer bit of the
pseudo-denormal, m68k considers it part of the input value. This gives m68k one extra bit
of range in their denormal, which allows representation of smaller numbers.
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-20 18:39 ` Richard Henderson
@ 2025-02-20 18:54 ` Peter Maydell
2025-02-21 14:14 ` Philippe Mathieu-Daudé
2025-02-21 22:24 ` Richard Henderson
0 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-20 18:54 UTC (permalink / raw)
To: Richard Henderson
Cc: qemu-devel, Alex Bennée, Paolo Bonzini, Eduardo Habkost,
Laurent Vivier
On Thu, 20 Feb 2025 at 18:39, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 2/20/25 09:12, Peter Maydell wrote:
> > That suggests that we are correctly implementing the x87
> > required behaviour in QEMU, and so that the TODO comment
> > I add in this patch isn't right. But then I'm a bit confused
> > about what the code is actually doing. Why do we need to look
> > at fmt->m68k_denormal in the input (canonicalize) code (i.e.
> > to have different behaviour here for x86 and m68k), if
> > both x86 and m68k accept these pseudodenormals as input?
> >
> > Is the difference that for x86 we accept but canonicalize
> > into the equivalent normal number immediately on input,
> > whereas for m68k we accept and leave the pseudodenormal
> > as a pseudodenormal (well, m68k calls these a kind of
> > normal number) ?
> The difference is in interpretation: x86 ignores the explicit integer bit of the
> pseudo-denormal, m68k considers it part of the input value. This gives m68k one extra bit
> of range in their denormal, which allows representation of smaller numbers.
Ah, I see. So I suppose:
(1) we should call the floatx80_status flag
"floatx80_pseudo_denormal_valid" since it affects both inputs
and outputs, and document it in the enum like:
+ /*
+ * If the exponent is 0 and the Integer bit is set, Intel call
+ * this a "pseudo-denormal"; x86 supports that only on input
+ * (treating them as denormals by ignoring the Integer bit).
+ * For m68k, the integer bit is considered validly part of the
+ * input value when the exponent is 0, and may be 0 or 1,
+ * giving extra range. They may also be generated as outputs.
+ * (The m68k manual actually calls these values part of the
+ * normalized number range, not the denormalized number range.)
+ *
+ * By default you get the Intel behaviour where the Integer
+ * bit is ignored; if this is set then the Integer bit value
+ * is honoured, m68k-style.
+ *
+ * Either way, floatx80_invalid_encoding() will always accept
+ * pseudo-denormals.
+ */
+ floatx80_pseudo_denormal_valid = 16,
(2) the comment I add in canonicalize should instead read:
+ /*
+ * It's target-dependent how to handle the case of exponent 0
+ * and Integer bit set. Intel calls these "pseudodenormals",
+ * and treats them as if the integer bit was 0, and never
+ * produces them on output. This is the default behaviour for QEMU.
+ * For m68k, the integer bit is considered validly part of the
+ * input value when the exponent is 0, and may be 0 or 1,
+ * giving extra range. They may also be generated as outputs.
+ * (The m68k manual actually calls these values part of the
+ * normalized number range, not the denormalized number range,
+ * but that distinction is not important for us, because
+ * m68k doesn't care about the input_denormal_used status flag.)
+ * floatx80_pseudo_denormal_valid selects the m68k behaviour,
+ * which changes both how we canonicalize such a value and
+ * how we uncanonicalize results.
+ */
?
thanks
-- PMM
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-20 18:54 ` Peter Maydell
@ 2025-02-21 14:14 ` Philippe Mathieu-Daudé
2025-02-21 22:24 ` Richard Henderson
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 14:14 UTC (permalink / raw)
To: Peter Maydell, Richard Henderson
Cc: qemu-devel, Alex Bennée, Paolo Bonzini, Eduardo Habkost,
Laurent Vivier
On 20/2/25 19:54, Peter Maydell wrote:
> On Thu, 20 Feb 2025 at 18:39, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> On 2/20/25 09:12, Peter Maydell wrote:
>>> That suggests that we are correctly implementing the x87
>>> required behaviour in QEMU, and so that the TODO comment
>>> I add in this patch isn't right. But then I'm a bit confused
>>> about what the code is actually doing. Why do we need to look
>>> at fmt->m68k_denormal in the input (canonicalize) code (i.e.
>>> to have different behaviour here for x86 and m68k), if
>>> both x86 and m68k accept these pseudodenormals as input?
>>>
>>> Is the difference that for x86 we accept but canonicalize
>>> into the equivalent normal number immediately on input,
>>> whereas for m68k we accept and leave the pseudodenormal
>>> as a pseudodenormal (well, m68k calls these a kind of
>>> normal number) ?
>> The difference is in interpretation: x86 ignores the explicit integer bit of the
>> pseudo-denormal, m68k considers it part of the input value. This gives m68k one extra bit
>> of range in their denormal, which allows representation of smaller numbers.
>
> Ah, I see. So I suppose:
>
> (1) we should call the floatx80_status flag
> "floatx80_pseudo_denormal_valid" since it affects both inputs
> and outputs, and document it in the enum like:
>
> + /*
> + * If the exponent is 0 and the Integer bit is set, Intel call
> + * this a "pseudo-denormal"; x86 supports that only on input
> + * (treating them as denormals by ignoring the Integer bit).
> + * For m68k, the integer bit is considered validly part of the
> + * input value when the exponent is 0, and may be 0 or 1,
> + * giving extra range. They may also be generated as outputs.
> + * (The m68k manual actually calls these values part of the
> + * normalized number range, not the denormalized number range.)
> + *
> + * By default you get the Intel behaviour where the Integer
> + * bit is ignored; if this is set then the Integer bit value
> + * is honoured, m68k-style.
> + *
> + * Either way, floatx80_invalid_encoding() will always accept
> + * pseudo-denormals.
> + */
> + floatx80_pseudo_denormal_valid = 16,
>
>
> (2) the comment I add in canonicalize should instead read:
>
> + /*
> + * It's target-dependent how to handle the case of exponent 0
> + * and Integer bit set. Intel calls these "pseudodenormals",
> + * and treats them as if the integer bit was 0, and never
> + * produces them on output. This is the default behaviour for QEMU.
> + * For m68k, the integer bit is considered validly part of the
> + * input value when the exponent is 0, and may be 0 or 1,
> + * giving extra range. They may also be generated as outputs.
> + * (The m68k manual actually calls these values part of the
> + * normalized number range, not the denormalized number range,
> + * but that distinction is not important for us, because
> + * m68k doesn't care about the input_denormal_used status flag.)
> + * floatx80_pseudo_denormal_valid selects the m68k behaviour,
> + * which changes both how we canonicalize such a value and
> + * how we uncanonicalize results.
> + */
Both changes LGTM but I'm no expert here ;) To the best of my
FPU knowledge:
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour
2025-02-20 18:54 ` Peter Maydell
2025-02-21 14:14 ` Philippe Mathieu-Daudé
@ 2025-02-21 22:24 ` Richard Henderson
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-21 22:24 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Alex Bennée, Paolo Bonzini, Eduardo Habkost,
Laurent Vivier
On 2/20/25 10:54, Peter Maydell wrote:
> On Thu, 20 Feb 2025 at 18:39, Richard Henderson
> <richard.henderson@linaro.org> wrote:
>>
>> On 2/20/25 09:12, Peter Maydell wrote:
>>> That suggests that we are correctly implementing the x87
>>> required behaviour in QEMU, and so that the TODO comment
>>> I add in this patch isn't right. But then I'm a bit confused
>>> about what the code is actually doing. Why do we need to look
>>> at fmt->m68k_denormal in the input (canonicalize) code (i.e.
>>> to have different behaviour here for x86 and m68k), if
>>> both x86 and m68k accept these pseudodenormals as input?
>>>
>>> Is the difference that for x86 we accept but canonicalize
>>> into the equivalent normal number immediately on input,
>>> whereas for m68k we accept and leave the pseudodenormal
>>> as a pseudodenormal (well, m68k calls these a kind of
>>> normal number) ?
>> The difference is in interpretation: x86 ignores the explicit integer bit of the
>> pseudo-denormal, m68k considers it part of the input value. This gives m68k one extra bit
>> of range in their denormal, which allows representation of smaller numbers.
>
> Ah, I see. So I suppose:
>
> (1) we should call the floatx80_status flag
> "floatx80_pseudo_denormal_valid" since it affects both inputs
> and outputs, and document it in the enum like:
>
> + /*
> + * If the exponent is 0 and the Integer bit is set, Intel call
> + * this a "pseudo-denormal"; x86 supports that only on input
> + * (treating them as denormals by ignoring the Integer bit).
> + * For m68k, the integer bit is considered validly part of the
> + * input value when the exponent is 0, and may be 0 or 1,
> + * giving extra range. They may also be generated as outputs.
> + * (The m68k manual actually calls these values part of the
> + * normalized number range, not the denormalized number range.)
> + *
> + * By default you get the Intel behaviour where the Integer
> + * bit is ignored; if this is set then the Integer bit value
> + * is honoured, m68k-style.
> + *
> + * Either way, floatx80_invalid_encoding() will always accept
> + * pseudo-denormals.
> + */
> + floatx80_pseudo_denormal_valid = 16,
>
>
> (2) the comment I add in canonicalize should instead read:
>
> + /*
> + * It's target-dependent how to handle the case of exponent 0
> + * and Integer bit set. Intel calls these "pseudodenormals",
> + * and treats them as if the integer bit was 0, and never
> + * produces them on output. This is the default behaviour for QEMU.
> + * For m68k, the integer bit is considered validly part of the
> + * input value when the exponent is 0, and may be 0 or 1,
> + * giving extra range. They may also be generated as outputs.
> + * (The m68k manual actually calls these values part of the
> + * normalized number range, not the denormalized number range,
> + * but that distinction is not important for us, because
> + * m68k doesn't care about the input_denormal_used status flag.)
> + * floatx80_pseudo_denormal_valid selects the m68k behaviour,
> + * which changes both how we canonicalize such a value and
> + * how we uncanonicalize results.
> + */
>
Looks good.
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (5 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 06/10] fpu: Move m68k_denormal fmt flag into floatx80_behaviour Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 13:13 ` Philippe Mathieu-Daudé
2025-02-17 19:25 ` Richard Henderson
2025-02-17 12:50 ` [PATCH 08/10] fpu: Always decide snan_bit_is_one() " Peter Maydell
` (5 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Currently we have a compile-time shortcut where we
return false from no_signaling_nans() on everything except
Xtensa, because we know that's the only target that
might ever set status->no_signaling_nans.
Remove the ifdef, so we always look at the status flag;
this has no behavioural change, but will be necessary
if we want to build softfloat once for all targets.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
fpu/softfloat-specialize.c.inc | 4 ----
1 file changed, 4 deletions(-)
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 8327f727861..a2c6afad5da 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -85,11 +85,7 @@ this code that are retained.
*/
static inline bool no_signaling_nans(float_status *status)
{
-#if defined(TARGET_XTENSA)
return status->no_signaling_nans;
-#else
- return false;
-#endif
}
/* Define how the architecture discriminates signaling NaNs.
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime
2025-02-17 12:50 ` [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime Peter Maydell
@ 2025-02-17 13:13 ` Philippe Mathieu-Daudé
2025-02-17 19:25 ` Richard Henderson
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-17 13:13 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> Currently we have a compile-time shortcut where we
> return false from no_signaling_nans() on everything except
> Xtensa, because we know that's the only target that
> might ever set status->no_signaling_nans.
>
> Remove the ifdef, so we always look at the status flag;
> this has no behavioural change, but will be necessary
> if we want to build softfloat once for all targets.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> fpu/softfloat-specialize.c.inc | 4 ----
> 1 file changed, 4 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime
2025-02-17 12:50 ` [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime Peter Maydell
2025-02-17 13:13 ` Philippe Mathieu-Daudé
@ 2025-02-17 19:25 ` Richard Henderson
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 19:25 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> Currently we have a compile-time shortcut where we
> return false from no_signaling_nans() on everything except
> Xtensa, because we know that's the only target that
> might ever set status->no_signaling_nans.
>
> Remove the ifdef, so we always look at the status flag;
> this has no behavioural change, but will be necessary
> if we want to build softfloat once for all targets.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> fpu/softfloat-specialize.c.inc | 4 ----
> 1 file changed, 4 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 08/10] fpu: Always decide snan_bit_is_one() at runtime
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (6 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 07/10] fpu: Always decide no_signaling_nans() at runtime Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 13:15 ` Philippe Mathieu-Daudé
2025-02-17 19:26 ` Richard Henderson
2025-02-17 12:50 ` [PATCH 09/10] fpu: Don't compile-time disable hardfloat for PPC targets Peter Maydell
` (4 subsequent siblings)
12 siblings, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Currently we have a compile-time shortcut where we return a hardcode
value from snan_bit_is_one() on everything except MIPS, because we
know that's the only target that needs to change
status->no_signaling_nans at runtime.
Remove the ifdef, so we always look at the status flag. This means
we must update the two targets (HPPA and SH4) that were previously
hardcoded to return true so that they set the status flag correctly.
This has no behavioural change, but will be necessary if we want to
build softfloat once for all targets.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/hppa/fpu_helper.c | 1 +
target/sh4/cpu.c | 1 +
fpu/softfloat-specialize.c.inc | 7 -------
3 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
index 8ff4b448049..a62d9d30831 100644
--- a/target/hppa/fpu_helper.c
+++ b/target/hppa/fpu_helper.c
@@ -67,6 +67,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
/* Default NaN: sign bit clear, msb-1 frac bit set */
set_float_default_nan_pattern(0b00100000, &env->fp_status);
+ set_snan_bit_is_one(true, &env->fp_status);
/*
* "PA-RISC 2.0 Architecture" says it is IMPDEF whether the flushing
* enabled by FPSR.D happens before or after rounding. We pick "before"
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 4ac693d99bd..ccfe222bdf3 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -128,6 +128,7 @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
set_flush_to_zero(1, &env->fp_status);
#endif
set_default_nan_mode(1, &env->fp_status);
+ set_snan_bit_is_one(true, &env->fp_status);
/* sign bit clear, set all frac bits other than msb */
set_float_default_nan_pattern(0b00111111, &env->fp_status);
/*
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index a2c6afad5da..ba4fa08b7be 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -93,17 +93,10 @@ static inline bool no_signaling_nans(float_status *status)
* In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
* the msb must be zero. MIPS is (so far) unique in supporting both the
* 2008 revision and backward compatibility with their original choice.
- * Thus for MIPS we must make the choice at runtime.
*/
static inline bool snan_bit_is_one(float_status *status)
{
-#if defined(TARGET_MIPS)
return status->snan_bit_is_one;
-#elif defined(TARGET_HPPA) || defined(TARGET_SH4)
- return 1;
-#else
- return 0;
-#endif
}
/*----------------------------------------------------------------------------
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 08/10] fpu: Always decide snan_bit_is_one() at runtime
2025-02-17 12:50 ` [PATCH 08/10] fpu: Always decide snan_bit_is_one() " Peter Maydell
@ 2025-02-17 13:15 ` Philippe Mathieu-Daudé
2025-02-17 19:26 ` Richard Henderson
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-17 13:15 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> Currently we have a compile-time shortcut where we return a hardcode
> value from snan_bit_is_one() on everything except MIPS, because we
> know that's the only target that needs to change
> status->no_signaling_nans at runtime.
>
> Remove the ifdef, so we always look at the status flag. This means
> we must update the two targets (HPPA and SH4) that were previously
> hardcoded to return true so that they set the status flag correctly.
>
> This has no behavioural change, but will be necessary if we want to
> build softfloat once for all targets.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> target/hppa/fpu_helper.c | 1 +
> target/sh4/cpu.c | 1 +
> fpu/softfloat-specialize.c.inc | 7 -------
> 3 files changed, 2 insertions(+), 7 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 08/10] fpu: Always decide snan_bit_is_one() at runtime
2025-02-17 12:50 ` [PATCH 08/10] fpu: Always decide snan_bit_is_one() " Peter Maydell
2025-02-17 13:15 ` Philippe Mathieu-Daudé
@ 2025-02-17 19:26 ` Richard Henderson
1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 19:26 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> Currently we have a compile-time shortcut where we return a hardcode
> value from snan_bit_is_one() on everything except MIPS, because we
> know that's the only target that needs to change
> status->no_signaling_nans at runtime.
Pasto from the previous patch on the variable name.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
>
> Remove the ifdef, so we always look at the status flag. This means
> we must update the two targets (HPPA and SH4) that were previously
> hardcoded to return true so that they set the status flag correctly.
>
> This has no behavioural change, but will be necessary if we want to
> build softfloat once for all targets.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> target/hppa/fpu_helper.c | 1 +
> target/sh4/cpu.c | 1 +
> fpu/softfloat-specialize.c.inc | 7 -------
> 3 files changed, 2 insertions(+), 7 deletions(-)
>
> diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
> index 8ff4b448049..a62d9d30831 100644
> --- a/target/hppa/fpu_helper.c
> +++ b/target/hppa/fpu_helper.c
> @@ -67,6 +67,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
> set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
> /* Default NaN: sign bit clear, msb-1 frac bit set */
> set_float_default_nan_pattern(0b00100000, &env->fp_status);
> + set_snan_bit_is_one(true, &env->fp_status);
> /*
> * "PA-RISC 2.0 Architecture" says it is IMPDEF whether the flushing
> * enabled by FPSR.D happens before or after rounding. We pick "before"
> diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
> index 4ac693d99bd..ccfe222bdf3 100644
> --- a/target/sh4/cpu.c
> +++ b/target/sh4/cpu.c
> @@ -128,6 +128,7 @@ static void superh_cpu_reset_hold(Object *obj, ResetType type)
> set_flush_to_zero(1, &env->fp_status);
> #endif
> set_default_nan_mode(1, &env->fp_status);
> + set_snan_bit_is_one(true, &env->fp_status);
> /* sign bit clear, set all frac bits other than msb */
> set_float_default_nan_pattern(0b00111111, &env->fp_status);
> /*
> diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
> index a2c6afad5da..ba4fa08b7be 100644
> --- a/fpu/softfloat-specialize.c.inc
> +++ b/fpu/softfloat-specialize.c.inc
> @@ -93,17 +93,10 @@ static inline bool no_signaling_nans(float_status *status)
> * In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
> * the msb must be zero. MIPS is (so far) unique in supporting both the
> * 2008 revision and backward compatibility with their original choice.
> - * Thus for MIPS we must make the choice at runtime.
> */
> static inline bool snan_bit_is_one(float_status *status)
> {
> -#if defined(TARGET_MIPS)
> return status->snan_bit_is_one;
> -#elif defined(TARGET_HPPA) || defined(TARGET_SH4)
> - return 1;
> -#else
> - return 0;
> -#endif
> }
>
> /*----------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 09/10] fpu: Don't compile-time disable hardfloat for PPC targets
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (7 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 08/10] fpu: Always decide snan_bit_is_one() " Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 19:27 ` Richard Henderson
2025-02-17 12:50 ` [PATCH 10/10] fpu: Build only once Peter Maydell
` (3 subsequent siblings)
12 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
We happen to know that for the PPC target the FP status flags (and in
particular float_flag_inexact) will always be cleared before a
floating point operation, and so can_use_fpu() will always return
false. So we speed things up a little by forcing QEMU_NO_HARDFLOAT
to true on that target.
We would like to build softfloat once for all targets; that means
removing target-specific ifdefs. Remove the check for TARGET_PPC;
this won't change behaviour because can_use_fpu() will see that
float_flag_inexact is clear and take the softfloat path anyway.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
fpu/softfloat.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b299cfaf860..b38eea8d879 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -220,11 +220,9 @@ GEN_INPUT_FLUSH3(float64_input_flush3, float64)
* the use of hardfloat, since hardfloat relies on the inexact flag being
* already set.
*/
-#if defined(TARGET_PPC) || defined(__FAST_MATH__)
# if defined(__FAST_MATH__)
# warning disabling hardfloat due to -ffast-math: hardfloat requires an exact \
IEEE implementation
-# endif
# define QEMU_NO_HARDFLOAT 1
# define QEMU_SOFTFLOAT_ATTR QEMU_FLATTEN
#else
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 09/10] fpu: Don't compile-time disable hardfloat for PPC targets
2025-02-17 12:50 ` [PATCH 09/10] fpu: Don't compile-time disable hardfloat for PPC targets Peter Maydell
@ 2025-02-17 19:27 ` Richard Henderson
0 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 19:27 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> We happen to know that for the PPC target the FP status flags (and in
> particular float_flag_inexact) will always be cleared before a
> floating point operation, and so can_use_fpu() will always return
> false. So we speed things up a little by forcing QEMU_NO_HARDFLOAT
> to true on that target.
>
> We would like to build softfloat once for all targets; that means
> removing target-specific ifdefs. Remove the check for TARGET_PPC;
> this won't change behaviour because can_use_fpu() will see that
> float_flag_inexact is clear and take the softfloat path anyway.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> fpu/softfloat.c | 2 --
> 1 file changed, 2 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This makes ppc no different from the many other targets which clear out softfloat
exception flags after every operation.
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 10/10] fpu: Build only once
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (8 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 09/10] fpu: Don't compile-time disable hardfloat for PPC targets Peter Maydell
@ 2025-02-17 12:50 ` Peter Maydell
2025-02-17 19:28 ` Richard Henderson
2025-02-20 8:48 ` [PATCH 00/10] fpu: Remove remaining target ifdefs and build " Philippe Mathieu-Daudé
` (2 subsequent siblings)
12 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2025-02-17 12:50 UTC (permalink / raw)
To: qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Now we have removed all the target-specifics from the softfloat code,
we can switch to building it once for the whole system rather than
once per target.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
fpu/softfloat.c | 3 ---
fpu/meson.build | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b38eea8d879..34c962d6bd9 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -79,9 +79,6 @@ this code that are retained.
* version 2 or later. See the COPYING file in the top-level directory.
*/
-/* softfloat (and in particular the code in softfloat-specialize.h) is
- * target-dependent and needs the TARGET_* macros.
- */
#include "qemu/osdep.h"
#include <math.h>
#include "qemu/bitops.h"
diff --git a/fpu/meson.build b/fpu/meson.build
index 1a9992ded56..646c76f0c69 100644
--- a/fpu/meson.build
+++ b/fpu/meson.build
@@ -1 +1 @@
-specific_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
+common_ss.add(when: 'CONFIG_TCG', if_true: files('softfloat.c'))
--
2.43.0
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 10/10] fpu: Build only once
2025-02-17 12:50 ` [PATCH 10/10] fpu: Build only once Peter Maydell
@ 2025-02-17 19:28 ` Richard Henderson
0 siblings, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2025-02-17 19:28 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Paolo Bonzini, Eduardo Habkost, Laurent Vivier
On 2/17/25 04:50, Peter Maydell wrote:
> Now we have removed all the target-specifics from the softfloat code,
> we can switch to building it once for the whole system rather than
> once per target.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> fpu/softfloat.c | 3 ---
> fpu/meson.build | 2 +-
> 2 files changed, 1 insertion(+), 4 deletions(-)
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (9 preceding siblings ...)
2025-02-17 12:50 ` [PATCH 10/10] fpu: Build only once Peter Maydell
@ 2025-02-20 8:48 ` Philippe Mathieu-Daudé
2025-02-20 9:00 ` Philippe Mathieu-Daudé
2025-02-21 10:48 ` Philippe Mathieu-Daudé
2025-02-21 13:05 ` Philippe Mathieu-Daudé
2025-02-21 14:41 ` Philippe Mathieu-Daudé
12 siblings, 2 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-20 8:48 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier, Thomas Huth
On 17/2/25 13:50, Peter Maydell wrote:
> The work I needed to do to make various softfloat emulation behaviours
> runtime-selectable for Arm FEAT_AFP has left the fpu code with very
> few remaning target ifdefs. So this series turns the last remaning
> ones into runtime behaviour choices and switches the fpu code into
> "build once" rather than "build per target". The main driver of this
> is that we're going to want to do this for the "multiple targets in
> one binary" work.
Indeed the following 332 symbols are now removed for each target:
bfloat16_add
bfloat16_compare
bfloat16_compare_quiet
bfloat16_default_nan
bfloat16_div
bfloat16_is_quiet_nan
bfloat16_is_signaling_nan
bfloat16_max
bfloat16_maximum_number
bfloat16_maxnum
bfloat16_maxnummag
bfloat16_min
bfloat16_minimum_number
bfloat16_minnum
bfloat16_minnummag
bfloat16_mul
bfloat16_muladd
bfloat16_round_to_int
bfloat16_scalbn
bfloat16_silence_nan
bfloat16_sqrt
bfloat16_squash_input_denormal
bfloat16_sub
bfloat16_to_float32
bfloat16_to_float64
bfloat16_to_int16
bfloat16_to_int16_round_to_zero
bfloat16_to_int16_scalbn
bfloat16_to_int32
bfloat16_to_int32_round_to_zero
bfloat16_to_int32_scalbn
bfloat16_to_int64
bfloat16_to_int64_round_to_zero
bfloat16_to_int64_scalbn
bfloat16_to_int8
bfloat16_to_int8_round_to_zero
bfloat16_to_int8_scalbn
bfloat16_to_uint16
bfloat16_to_uint16_round_to_zero
bfloat16_to_uint16_scalbn
bfloat16_to_uint32
bfloat16_to_uint32_round_to_zero
bfloat16_to_uint32_scalbn
bfloat16_to_uint64
bfloat16_to_uint64_round_to_zero
bfloat16_to_uint64_scalbn
bfloat16_to_uint8
bfloat16_to_uint8_round_to_zero
bfloat16_to_uint8_scalbn
float128_add
float128_compare
float128_compare_quiet
float128_default_nan
float128_div
float128_is_quiet_nan
float128_is_signaling_nan
float128_max
float128_maximum_number
float128_maxnum
float128_maxnummag
float128_min
float128_minimum_number
float128_minnum
float128_minnummag
float128_mul
float128_muladd
float128_rem
float128_round_to_int
float128_scalbn
float128_silence_nan
float128_sqrt
float128_sub
float128_to_float32
float128_to_float64
float128_to_floatx80
float128_to_int128
float128_to_int128_round_to_zero
float128_to_int32
float128_to_int32_round_to_zero
float128_to_int64
float128_to_int64_round_to_zero
float128_to_uint128
float128_to_uint128_round_to_zero
float128_to_uint32
float128_to_uint32_round_to_zero
float128_to_uint64
float128_to_uint64_round_to_zero
float16_add
float16_compare
float16_compare_quiet
float16_default_nan
float16_div
float16_is_quiet_nan
float16_is_signaling_nan
float16_max
float16_maximum_number
float16_maxnum
float16_maxnummag
float16_min
float16_minimum_number
float16_minnum
float16_minnummag
float16_mul
float16_muladd
float16_muladd_scalbn
float16_round_to_int
float16_scalbn
float16_silence_nan
float16_sqrt
float16_squash_input_denormal
float16_sub
float16_to_float32
float16_to_float64
float16_to_int16
float16_to_int16_round_to_zero
float16_to_int16_scalbn
float16_to_int32
float16_to_int32_round_to_zero
float16_to_int32_scalbn
float16_to_int64
float16_to_int64_round_to_zero
float16_to_int64_scalbn
float16_to_int8
float16_to_int8_scalbn
float16_to_uint16
float16_to_uint16_round_to_zero
float16_to_uint16_scalbn
float16_to_uint32
float16_to_uint32_round_to_zero
float16_to_uint32_scalbn
float16_to_uint64
float16_to_uint64_round_to_zero
float16_to_uint64_scalbn
float16_to_uint8
float16_to_uint8_scalbn
float32_add
float32_compare
float32_compare_quiet
float32_default_nan
float32_div
float32_exp2
float32_is_quiet_nan
float32_is_signaling_nan
float32_log2
float32_max
float32_maximum_number
float32_maxnum
float32_maxnummag
float32_min
float32_minimum_number
float32_minnum
float32_minnummag
float32_mul
float32_muladd
float32_muladd_scalbn
float32_rem
float32_round_to_int
float32_scalbn
float32_silence_nan
float32_sqrt
float32_squash_input_denormal
float32_sub
float32_to_bfloat16
float32_to_float128
float32_to_float16
float32_to_float64
float32_to_floatx80
float32_to_int16
float32_to_int16_round_to_zero
float32_to_int16_scalbn
float32_to_int32
float32_to_int32_round_to_zero
float32_to_int32_scalbn
float32_to_int64
float32_to_int64_round_to_zero
float32_to_int64_scalbn
float32_to_uint16
float32_to_uint16_round_to_zero
float32_to_uint16_scalbn
float32_to_uint32
float32_to_uint32_round_to_zero
float32_to_uint32_scalbn
float32_to_uint64
float32_to_uint64_round_to_zero
float32_to_uint64_scalbn
float64_add
float64_compare
float64_compare_quiet
float64_default_nan
float64_div
float64_is_quiet_nan
float64_is_signaling_nan
float64_log2
float64_max
float64_maximum_number
float64_maxnum
float64_maxnummag
float64_min
float64_minimum_number
float64_minnum
float64_minnummag
float64_mul
float64_muladd
float64_muladd_scalbn
float64_rem
float64_round_to_int
float64_scalbn
float64_silence_nan
float64_sqrt
float64_squash_input_denormal
float64_sub
float64_to_bfloat16
float64_to_float128
float64_to_float16
float64_to_float32
float64_to_floatx80
float64_to_int16
float64_to_int16_round_to_zero
float64_to_int16_scalbn
float64_to_int32
float64_to_int32_modulo
float64_to_int32_round_to_zero
float64_to_int32_scalbn
float64_to_int64
float64_to_int64_modulo
float64_to_int64_round_to_zero
float64_to_int64_scalbn
float64_to_uint16
float64_to_uint16_round_to_zero
float64_to_uint16_scalbn
float64_to_uint32
float64_to_uint32_round_to_zero
float64_to_uint32_scalbn
float64_to_uint64
float64_to_uint64_round_to_zero
float64_to_uint64_scalbn
float64r32_add
float64r32_div
float64r32_mul
float64r32_muladd
float64r32_sqrt
float64r32_sub
floatx80_add
floatx80_compare
floatx80_compare_quiet
floatx80_default_nan
floatx80_div
floatx80_infinity
floatx80_is_quiet_nan
floatx80_is_signaling_nan
floatx80_mod
floatx80_modrem
floatx80_mul
floatx80_rem
floatx80_round
floatx80_round_to_int
floatx80_scalbn
floatx80_silence_nan
floatx80_sqrt
floatx80_sub
floatx80_to_float128
floatx80_to_float32
floatx80_to_float64
floatx80_to_int32
floatx80_to_int32_round_to_zero
floatx80_to_int64
floatx80_to_int64_round_to_zero
int128_to_float128
int16_to_bfloat16
int16_to_bfloat16_scalbn
int16_to_float16
int16_to_float16_scalbn
int16_to_float32
int16_to_float32_scalbn
int16_to_float64
int16_to_float64_scalbn
int32_to_bfloat16
int32_to_bfloat16_scalbn
int32_to_float128
int32_to_float16
int32_to_float16_scalbn
int32_to_float32
int32_to_float32_scalbn
int32_to_float64
int32_to_float64_scalbn
int32_to_floatx80
int64_to_bfloat16
int64_to_bfloat16_scalbn
int64_to_float128
int64_to_float16
int64_to_float16_scalbn
int64_to_float32
int64_to_float32_scalbn
int64_to_float64
int64_to_float64_scalbn
int64_to_floatx80
int8_to_bfloat16
int8_to_bfloat16_scalbn
int8_to_float16
normalizeFloatx80Subnormal
normalizeRoundAndPackFloatx80
propagateFloatx80NaN
roundAndPackFloatx80
uint128_to_float128
uint16_to_bfloat16
uint16_to_bfloat16_scalbn
uint16_to_float16
uint16_to_float16_scalbn
uint16_to_float32
uint16_to_float32_scalbn
uint16_to_float64
uint16_to_float64_scalbn
uint32_to_bfloat16
uint32_to_bfloat16_scalbn
uint32_to_float16
uint32_to_float16_scalbn
uint32_to_float32
uint32_to_float32_scalbn
uint32_to_float64
uint32_to_float64_scalbn
uint64_to_bfloat16
uint64_to_bfloat16_scalbn
uint64_to_float128
uint64_to_float16
uint64_to_float16_scalbn
uint64_to_float32
uint64_to_float32_scalbn
uint64_to_float64
uint64_to_float64_scalbn
uint8_to_bfloat16
uint8_to_bfloat16_scalbn
uint8_to_float16
and my single binary duplicate symbols list drastically reduced:
-ld: 1759 duplicate symbols
+ld: 1427 duplicate symbols
Thank you a lot for this huge help! :)
FWIW:
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-20 8:48 ` [PATCH 00/10] fpu: Remove remaining target ifdefs and build " Philippe Mathieu-Daudé
@ 2025-02-20 9:00 ` Philippe Mathieu-Daudé
2025-02-21 10:48 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-20 9:00 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier, Thomas Huth
On 20/2/25 09:48, Philippe Mathieu-Daudé wrote:
> On 17/2/25 13:50, Peter Maydell wrote:
>> The work I needed to do to make various softfloat emulation behaviours
>> runtime-selectable for Arm FEAT_AFP has left the fpu code with very
>> few remaning target ifdefs. So this series turns the last remaning
>> ones into runtime behaviour choices and switches the fpu code into
>> "build once" rather than "build per target". The main driver of this
>> is that we're going to want to do this for the "multiple targets in
>> one binary" work.
> and my single binary duplicate symbols list drastically reduced:
>
> -ld: 1759 duplicate symbols
> +ld: 1427 duplicate symbols
(being so far for a microblaze+xtensa config:)
CpuModelCompareResult_lookup
CpuModelExpansionType_lookup
QAPIEvent_lookup
accel_cpu_common_realize
accel_cpu_common_unrealize
accel_cpu_instance_init
accel_find
accel_init_interfaces
accel_supported_gdbstub_sstep_flags
address_space_access_valid
address_space_cache_destroy
address_space_cache_init
address_space_cache_invalidate
address_space_destroy
address_space_dispatch_compact
address_space_dispatch_free
address_space_dispatch_new
address_space_get_flatview
address_space_get_iotlb_entry
address_space_init
address_space_io
address_space_ldl
address_space_ldl_be
address_space_ldl_be_cached_slow
address_space_ldl_cached_slow
address_space_ldl_le
address_space_ldl_le_cached_slow
address_space_ldq
address_space_ldq_be
address_space_ldq_be_cached_slow
address_space_ldq_cached_slow
address_space_ldq_le
address_space_ldq_le_cached_slow
address_space_ldub
address_space_ldub_cached_slow
address_space_lduw
address_space_lduw_be
address_space_lduw_be_cached_slow
address_space_lduw_cached_slow
address_space_lduw_le
address_space_lduw_le_cached_slow
address_space_map
address_space_memory
address_space_read_cached_slow
address_space_read_full
address_space_register_map_client
address_space_remove_listeners
address_space_rw
address_space_set
address_space_stb
address_space_stb_cached_slow
address_space_stl
address_space_stl_be
address_space_stl_be_cached_slow
address_space_stl_cached_slow
address_space_stl_le
address_space_stl_le_cached_slow
address_space_stl_notdirty
address_space_stl_notdirty_cached_slow
address_space_stq
address_space_stq_be
address_space_stq_be_cached_slow
address_space_stq_cached_slow
address_space_stq_le
address_space_stq_le_cached_slow
address_space_stw
address_space_stw_be
address_space_stw_be_cached_slow
address_space_stw_cached_slow
address_space_stw_le
address_space_stw_le_cached_slow
address_space_translate_for_iotlb
address_space_unmap
address_space_unregister_map_client
address_space_write
address_space_write_cached_slow
address_space_write_rom
arch_type
colo_flush_ram_cache
colo_incoming_start_dirty_log
colo_init_ram_cache
colo_record_bitmap
colo_release_ram_cache
cpu_abort
cpu_address_space_destroy
cpu_address_space_init
cpu_atomic_add_fetchb_mmu
cpu_atomic_add_fetchl_be_mmu
cpu_atomic_add_fetchl_le_mmu
cpu_atomic_add_fetchq_be_mmu
cpu_atomic_add_fetchq_le_mmu
cpu_atomic_add_fetchw_be_mmu
cpu_atomic_add_fetchw_le_mmu
cpu_atomic_and_fetchb_mmu
cpu_atomic_and_fetchl_be_mmu
cpu_atomic_and_fetchl_le_mmu
cpu_atomic_and_fetchq_be_mmu
cpu_atomic_and_fetchq_le_mmu
cpu_atomic_and_fetchw_be_mmu
cpu_atomic_and_fetchw_le_mmu
cpu_atomic_cmpxchgb_mmu
cpu_atomic_cmpxchgl_be_mmu
cpu_atomic_cmpxchgl_le_mmu
cpu_atomic_cmpxchgo_be_mmu
cpu_atomic_cmpxchgo_le_mmu
cpu_atomic_cmpxchgq_be_mmu
cpu_atomic_cmpxchgq_le_mmu
cpu_atomic_cmpxchgw_be_mmu
cpu_atomic_cmpxchgw_le_mmu
cpu_atomic_fetch_addb_mmu
cpu_atomic_fetch_addl_be_mmu
cpu_atomic_fetch_addl_le_mmu
cpu_atomic_fetch_addq_be_mmu
cpu_atomic_fetch_addq_le_mmu
cpu_atomic_fetch_addw_be_mmu
cpu_atomic_fetch_addw_le_mmu
cpu_atomic_fetch_andb_mmu
cpu_atomic_fetch_andl_be_mmu
cpu_atomic_fetch_andl_le_mmu
cpu_atomic_fetch_andq_be_mmu
cpu_atomic_fetch_andq_le_mmu
cpu_atomic_fetch_andw_be_mmu
cpu_atomic_fetch_andw_le_mmu
cpu_atomic_fetch_orb_mmu
cpu_atomic_fetch_orl_be_mmu
cpu_atomic_fetch_orl_le_mmu
cpu_atomic_fetch_orq_be_mmu
cpu_atomic_fetch_orq_le_mmu
cpu_atomic_fetch_orw_be_mmu
cpu_atomic_fetch_orw_le_mmu
cpu_atomic_fetch_smaxb_mmu
cpu_atomic_fetch_smaxl_be_mmu
cpu_atomic_fetch_smaxl_le_mmu
cpu_atomic_fetch_smaxq_be_mmu
cpu_atomic_fetch_smaxq_le_mmu
cpu_atomic_fetch_smaxw_be_mmu
cpu_atomic_fetch_smaxw_le_mmu
cpu_atomic_fetch_sminb_mmu
cpu_atomic_fetch_sminl_be_mmu
cpu_atomic_fetch_sminl_le_mmu
cpu_atomic_fetch_sminq_be_mmu
cpu_atomic_fetch_sminq_le_mmu
cpu_atomic_fetch_sminw_be_mmu
cpu_atomic_fetch_sminw_le_mmu
cpu_atomic_fetch_umaxb_mmu
cpu_atomic_fetch_umaxl_be_mmu
cpu_atomic_fetch_umaxl_le_mmu
cpu_atomic_fetch_umaxq_be_mmu
cpu_atomic_fetch_umaxq_le_mmu
cpu_atomic_fetch_umaxw_be_mmu
cpu_atomic_fetch_umaxw_le_mmu
cpu_atomic_fetch_uminb_mmu
cpu_atomic_fetch_uminl_be_mmu
cpu_atomic_fetch_uminl_le_mmu
cpu_atomic_fetch_uminq_be_mmu
cpu_atomic_fetch_uminq_le_mmu
cpu_atomic_fetch_uminw_be_mmu
cpu_atomic_fetch_uminw_le_mmu
cpu_atomic_fetch_xorb_mmu
cpu_atomic_fetch_xorl_be_mmu
cpu_atomic_fetch_xorl_le_mmu
cpu_atomic_fetch_xorq_be_mmu
cpu_atomic_fetch_xorq_le_mmu
cpu_atomic_fetch_xorw_be_mmu
cpu_atomic_fetch_xorw_le_mmu
cpu_atomic_or_fetchb_mmu
cpu_atomic_or_fetchl_be_mmu
cpu_atomic_or_fetchl_le_mmu
cpu_atomic_or_fetchq_be_mmu
cpu_atomic_or_fetchq_le_mmu
cpu_atomic_or_fetchw_be_mmu
cpu_atomic_or_fetchw_le_mmu
cpu_atomic_smax_fetchb_mmu
cpu_atomic_smax_fetchl_be_mmu
cpu_atomic_smax_fetchl_le_mmu
cpu_atomic_smax_fetchq_be_mmu
cpu_atomic_smax_fetchq_le_mmu
cpu_atomic_smax_fetchw_be_mmu
cpu_atomic_smax_fetchw_le_mmu
cpu_atomic_smin_fetchb_mmu
cpu_atomic_smin_fetchl_be_mmu
cpu_atomic_smin_fetchl_le_mmu
cpu_atomic_smin_fetchq_be_mmu
cpu_atomic_smin_fetchq_le_mmu
cpu_atomic_smin_fetchw_be_mmu
cpu_atomic_smin_fetchw_le_mmu
cpu_atomic_umax_fetchb_mmu
cpu_atomic_umax_fetchl_be_mmu
cpu_atomic_umax_fetchl_le_mmu
cpu_atomic_umax_fetchq_be_mmu
cpu_atomic_umax_fetchq_le_mmu
cpu_atomic_umax_fetchw_be_mmu
cpu_atomic_umax_fetchw_le_mmu
cpu_atomic_umin_fetchb_mmu
cpu_atomic_umin_fetchl_be_mmu
cpu_atomic_umin_fetchl_le_mmu
cpu_atomic_umin_fetchq_be_mmu
cpu_atomic_umin_fetchq_le_mmu
cpu_atomic_umin_fetchw_be_mmu
cpu_atomic_umin_fetchw_le_mmu
cpu_atomic_xchgb_mmu
cpu_atomic_xchgl_be_mmu
cpu_atomic_xchgl_le_mmu
cpu_atomic_xchgq_be_mmu
cpu_atomic_xchgq_le_mmu
cpu_atomic_xchgw_be_mmu
cpu_atomic_xchgw_le_mmu
cpu_atomic_xor_fetchb_mmu
cpu_atomic_xor_fetchl_be_mmu
cpu_atomic_xor_fetchl_le_mmu
cpu_atomic_xor_fetchq_be_mmu
cpu_atomic_xor_fetchq_le_mmu
cpu_atomic_xor_fetchw_be_mmu
cpu_atomic_xor_fetchw_le_mmu
cpu_check_watchpoint
cpu_class_init_props
cpu_exec
cpu_exec_init_all
cpu_exec_initfn
cpu_exec_realizefn
cpu_exec_step_atomic
cpu_exec_unrealizefn
cpu_flush_icache_range
cpu_get_address_space
cpu_inb
cpu_inl
cpu_inw
cpu_io_recompile
cpu_ld16_mmu
cpu_ldb_code_mmu
cpu_ldb_mmu
cpu_ldl_be_data
cpu_ldl_be_data_ra
cpu_ldl_be_mmuidx_ra
cpu_ldl_code
cpu_ldl_code_mmu
cpu_ldl_le_data
cpu_ldl_le_data_ra
cpu_ldl_le_mmuidx_ra
cpu_ldl_mmu
cpu_ldq_be_data
cpu_ldq_be_data_ra
cpu_ldq_be_mmuidx_ra
cpu_ldq_code
cpu_ldq_code_mmu
cpu_ldq_le_data
cpu_ldq_le_data_ra
cpu_ldq_le_mmuidx_ra
cpu_ldq_mmu
cpu_ldsb_data
cpu_ldsb_data_ra
cpu_ldsb_mmuidx_ra
cpu_ldsw_be_data
cpu_ldsw_be_data_ra
cpu_ldsw_be_mmuidx_ra
cpu_ldsw_le_data
cpu_ldsw_le_data_ra
cpu_ldsw_le_mmuidx_ra
cpu_ldub_code
cpu_ldub_data
cpu_ldub_data_ra
cpu_ldub_mmuidx_ra
cpu_lduw_be_data
cpu_lduw_be_data_ra
cpu_lduw_be_mmuidx_ra
cpu_lduw_code
cpu_lduw_le_data
cpu_lduw_le_data_ra
cpu_lduw_le_mmuidx_ra
cpu_ldw_code_mmu
cpu_ldw_mmu
cpu_memory_rw_debug
cpu_model_from_type
cpu_outb
cpu_outl
cpu_outw
cpu_physical_memory_is_io
cpu_physical_memory_map
cpu_physical_memory_rw
cpu_physical_memory_snapshot_and_clear_dirty
cpu_physical_memory_snapshot_get_dirty
cpu_physical_memory_test_and_clear_dirty
cpu_physical_memory_unmap
cpu_restore_state
cpu_restore_state_from_tb
cpu_single_step
cpu_st16_mmu
cpu_stb_data
cpu_stb_data_ra
cpu_stb_mmu
cpu_stb_mmuidx_ra
cpu_stl_be_data
cpu_stl_be_data_ra
cpu_stl_be_mmuidx_ra
cpu_stl_le_data
cpu_stl_le_data_ra
cpu_stl_le_mmuidx_ra
cpu_stl_mmu
cpu_stq_be_data
cpu_stq_be_data_ra
cpu_stq_be_mmuidx_ra
cpu_stq_le_data
cpu_stq_le_data_ra
cpu_stq_le_mmuidx_ra
cpu_stq_mmu
cpu_stw_be_data
cpu_stw_be_data_ra
cpu_stw_be_mmuidx_ra
cpu_stw_le_data
cpu_stw_le_data_ra
cpu_stw_le_mmuidx_ra
cpu_stw_mmu
cpu_unwind_state_data
cpu_watchpoint_address_matches
cpu_watchpoint_insert
cpu_watchpoint_remove
cpu_watchpoint_remove_all
cpu_watchpoint_remove_by_ref
create_win_dump
curr_cflags
current_accel_name
finalize_target_page_bits
flatview_add_to_dispatch
flatview_for_each_range
flatview_read_continue
flatview_translate
flatview_unref
foreach_not_ignored_block
gdb_static_features
get_monitor_def
get_page_addr_code_hostp
get_system_io
get_system_memory
global_dirty_tracking
gpa2hva
graphic_depth
graphic_height
graphic_width
helper_atomic_add_fetchb
helper_atomic_add_fetchl_be
helper_atomic_add_fetchl_le
helper_atomic_add_fetchq_be
helper_atomic_add_fetchq_le
helper_atomic_add_fetchw_be
helper_atomic_add_fetchw_le
helper_atomic_and_fetchb
helper_atomic_and_fetchl_be
helper_atomic_and_fetchl_le
helper_atomic_and_fetchq_be
helper_atomic_and_fetchq_le
helper_atomic_and_fetchw_be
helper_atomic_and_fetchw_le
helper_atomic_cmpxchgb
helper_atomic_cmpxchgl_be
helper_atomic_cmpxchgl_le
helper_atomic_cmpxchgo_be
helper_atomic_cmpxchgo_le
helper_atomic_cmpxchgq_be
helper_atomic_cmpxchgq_le
helper_atomic_cmpxchgw_be
helper_atomic_cmpxchgw_le
helper_atomic_fetch_addb
helper_atomic_fetch_addl_be
helper_atomic_fetch_addl_le
helper_atomic_fetch_addq_be
helper_atomic_fetch_addq_le
helper_atomic_fetch_addw_be
helper_atomic_fetch_addw_le
helper_atomic_fetch_andb
helper_atomic_fetch_andl_be
helper_atomic_fetch_andl_le
helper_atomic_fetch_andq_be
helper_atomic_fetch_andq_le
helper_atomic_fetch_andw_be
helper_atomic_fetch_andw_le
helper_atomic_fetch_orb
helper_atomic_fetch_orl_be
helper_atomic_fetch_orl_le
helper_atomic_fetch_orq_be
helper_atomic_fetch_orq_le
helper_atomic_fetch_orw_be
helper_atomic_fetch_orw_le
helper_atomic_fetch_smaxb
helper_atomic_fetch_smaxl_be
helper_atomic_fetch_smaxl_le
helper_atomic_fetch_smaxq_be
helper_atomic_fetch_smaxq_le
helper_atomic_fetch_smaxw_be
helper_atomic_fetch_smaxw_le
helper_atomic_fetch_sminb
helper_atomic_fetch_sminl_be
helper_atomic_fetch_sminl_le
helper_atomic_fetch_sminq_be
helper_atomic_fetch_sminq_le
helper_atomic_fetch_sminw_be
helper_atomic_fetch_sminw_le
helper_atomic_fetch_umaxb
helper_atomic_fetch_umaxl_be
helper_atomic_fetch_umaxl_le
helper_atomic_fetch_umaxq_be
helper_atomic_fetch_umaxq_le
helper_atomic_fetch_umaxw_be
helper_atomic_fetch_umaxw_le
helper_atomic_fetch_uminb
helper_atomic_fetch_uminl_be
helper_atomic_fetch_uminl_le
helper_atomic_fetch_uminq_be
helper_atomic_fetch_uminq_le
helper_atomic_fetch_uminw_be
helper_atomic_fetch_uminw_le
helper_atomic_fetch_xorb
helper_atomic_fetch_xorl_be
helper_atomic_fetch_xorl_le
helper_atomic_fetch_xorq_be
helper_atomic_fetch_xorq_le
helper_atomic_fetch_xorw_be
helper_atomic_fetch_xorw_le
helper_atomic_or_fetchb
helper_atomic_or_fetchl_be
helper_atomic_or_fetchl_le
helper_atomic_or_fetchq_be
helper_atomic_or_fetchq_le
helper_atomic_or_fetchw_be
helper_atomic_or_fetchw_le
helper_atomic_smax_fetchb
helper_atomic_smax_fetchl_be
helper_atomic_smax_fetchl_le
helper_atomic_smax_fetchq_be
helper_atomic_smax_fetchq_le
helper_atomic_smax_fetchw_be
helper_atomic_smax_fetchw_le
helper_atomic_smin_fetchb
helper_atomic_smin_fetchl_be
helper_atomic_smin_fetchl_le
helper_atomic_smin_fetchq_be
helper_atomic_smin_fetchq_le
helper_atomic_smin_fetchw_be
helper_atomic_smin_fetchw_le
helper_atomic_umax_fetchb
helper_atomic_umax_fetchl_be
helper_atomic_umax_fetchl_le
helper_atomic_umax_fetchq_be
helper_atomic_umax_fetchq_le
helper_atomic_umax_fetchw_be
helper_atomic_umax_fetchw_le
helper_atomic_umin_fetchb
helper_atomic_umin_fetchl_be
helper_atomic_umin_fetchl_le
helper_atomic_umin_fetchq_be
helper_atomic_umin_fetchq_le
helper_atomic_umin_fetchw_be
helper_atomic_umin_fetchw_le
helper_atomic_xchgb
helper_atomic_xchgl_be
helper_atomic_xchgl_le
helper_atomic_xchgq_be
helper_atomic_xchgq_le
helper_atomic_xchgw_be
helper_atomic_xchgw_le
helper_atomic_xor_fetchb
helper_atomic_xor_fetchl_be
helper_atomic_xor_fetchl_le
helper_atomic_xor_fetchq_be
helper_atomic_xor_fetchq_le
helper_atomic_xor_fetchw_be
helper_atomic_xor_fetchw_le
helper_clrsb_i32
helper_clrsb_i64
helper_clz_i32
helper_clz_i64
helper_ctpop_i32
helper_ctpop_i64
helper_ctz_i32
helper_ctz_i64
helper_div_i32
helper_div_i64
helper_divs
helper_divu
helper_divu_i32
helper_divu_i64
helper_exit_atomic
helper_fadd
helper_fcmp_eq
helper_fcmp_ge
helper_fcmp_gt
helper_fcmp_le
helper_fcmp_lt
helper_fcmp_ne
helper_fcmp_un
helper_fdiv
helper_fint
helper_flt
helper_fmul
helper_frsub
helper_fsqrt
helper_get
helper_gvec_abs16
helper_gvec_abs32
helper_gvec_abs64
helper_gvec_abs8
helper_gvec_add16
helper_gvec_add32
helper_gvec_add64
helper_gvec_add8
helper_gvec_adds16
helper_gvec_adds32
helper_gvec_adds64
helper_gvec_adds8
helper_gvec_and
helper_gvec_andc
helper_gvec_andcs
helper_gvec_ands
helper_gvec_bitsel
helper_gvec_dup16
helper_gvec_dup32
helper_gvec_dup64
helper_gvec_dup8
helper_gvec_eq16
helper_gvec_eq32
helper_gvec_eq64
helper_gvec_eq8
helper_gvec_eqs16
helper_gvec_eqs32
helper_gvec_eqs64
helper_gvec_eqs8
helper_gvec_eqv
helper_gvec_le16
helper_gvec_le32
helper_gvec_le64
helper_gvec_le8
helper_gvec_les16
helper_gvec_les32
helper_gvec_les64
helper_gvec_les8
helper_gvec_leu16
helper_gvec_leu32
helper_gvec_leu64
helper_gvec_leu8
helper_gvec_leus16
helper_gvec_leus32
helper_gvec_leus64
helper_gvec_leus8
helper_gvec_lt16
helper_gvec_lt32
helper_gvec_lt64
helper_gvec_lt8
helper_gvec_lts16
helper_gvec_lts32
helper_gvec_lts64
helper_gvec_lts8
helper_gvec_ltu16
helper_gvec_ltu32
helper_gvec_ltu64
helper_gvec_ltu8
helper_gvec_ltus16
helper_gvec_ltus32
helper_gvec_ltus64
helper_gvec_ltus8
helper_gvec_mov
helper_gvec_mul16
helper_gvec_mul32
helper_gvec_mul64
helper_gvec_mul8
helper_gvec_muls16
helper_gvec_muls32
helper_gvec_muls64
helper_gvec_muls8
helper_gvec_nand
helper_gvec_ne16
helper_gvec_ne32
helper_gvec_ne64
helper_gvec_ne8
helper_gvec_neg16
helper_gvec_neg32
helper_gvec_neg64
helper_gvec_neg8
helper_gvec_nor
helper_gvec_not
helper_gvec_or
helper_gvec_orc
helper_gvec_ors
helper_gvec_rotl16i
helper_gvec_rotl16v
helper_gvec_rotl32i
helper_gvec_rotl32v
helper_gvec_rotl64i
helper_gvec_rotl64v
helper_gvec_rotl8i
helper_gvec_rotl8v
helper_gvec_rotr16v
helper_gvec_rotr32v
helper_gvec_rotr64v
helper_gvec_rotr8v
helper_gvec_sar16i
helper_gvec_sar16v
helper_gvec_sar32i
helper_gvec_sar32v
helper_gvec_sar64i
helper_gvec_sar64v
helper_gvec_sar8i
helper_gvec_sar8v
helper_gvec_shl16i
helper_gvec_shl16v
helper_gvec_shl32i
helper_gvec_shl32v
helper_gvec_shl64i
helper_gvec_shl64v
helper_gvec_shl8i
helper_gvec_shl8v
helper_gvec_shr16i
helper_gvec_shr16v
helper_gvec_shr32i
helper_gvec_shr32v
helper_gvec_shr64i
helper_gvec_shr64v
helper_gvec_shr8i
helper_gvec_shr8v
helper_gvec_smax16
helper_gvec_smax32
helper_gvec_smax64
helper_gvec_smax8
helper_gvec_smin16
helper_gvec_smin32
helper_gvec_smin64
helper_gvec_smin8
helper_gvec_ssadd16
helper_gvec_ssadd32
helper_gvec_ssadd64
helper_gvec_ssadd8
helper_gvec_sssub16
helper_gvec_sssub32
helper_gvec_sssub64
helper_gvec_sssub8
helper_gvec_sub16
helper_gvec_sub32
helper_gvec_sub64
helper_gvec_sub8
helper_gvec_subs16
helper_gvec_subs32
helper_gvec_subs64
helper_gvec_subs8
helper_gvec_umax16
helper_gvec_umax32
helper_gvec_umax64
helper_gvec_umax8
helper_gvec_umin16
helper_gvec_umin32
helper_gvec_umin64
helper_gvec_umin8
helper_gvec_usadd16
helper_gvec_usadd32
helper_gvec_usadd64
helper_gvec_usadd8
helper_gvec_ussub16
helper_gvec_ussub32
helper_gvec_ussub64
helper_gvec_ussub8
helper_gvec_xor
helper_gvec_xors
helper_info_atomic_add_fetchb
helper_info_atomic_add_fetchl_be
helper_info_atomic_add_fetchl_le
helper_info_atomic_add_fetchq_be
helper_info_atomic_add_fetchq_le
helper_info_atomic_add_fetchw_be
helper_info_atomic_add_fetchw_le
helper_info_atomic_and_fetchb
helper_info_atomic_and_fetchl_be
helper_info_atomic_and_fetchl_le
helper_info_atomic_and_fetchq_be
helper_info_atomic_and_fetchq_le
helper_info_atomic_and_fetchw_be
helper_info_atomic_and_fetchw_le
helper_info_atomic_cmpxchgb
helper_info_atomic_cmpxchgl_be
helper_info_atomic_cmpxchgl_le
helper_info_atomic_cmpxchgo_be
helper_info_atomic_cmpxchgo_le
helper_info_atomic_cmpxchgq_be
helper_info_atomic_cmpxchgq_le
helper_info_atomic_cmpxchgw_be
helper_info_atomic_cmpxchgw_le
helper_info_atomic_fetch_addb
helper_info_atomic_fetch_addl_be
helper_info_atomic_fetch_addl_le
helper_info_atomic_fetch_addq_be
helper_info_atomic_fetch_addq_le
helper_info_atomic_fetch_addw_be
helper_info_atomic_fetch_addw_le
helper_info_atomic_fetch_andb
helper_info_atomic_fetch_andl_be
helper_info_atomic_fetch_andl_le
helper_info_atomic_fetch_andq_be
helper_info_atomic_fetch_andq_le
helper_info_atomic_fetch_andw_be
helper_info_atomic_fetch_andw_le
helper_info_atomic_fetch_orb
helper_info_atomic_fetch_orl_be
helper_info_atomic_fetch_orl_le
helper_info_atomic_fetch_orq_be
helper_info_atomic_fetch_orq_le
helper_info_atomic_fetch_orw_be
helper_info_atomic_fetch_orw_le
helper_info_atomic_fetch_smaxb
helper_info_atomic_fetch_smaxl_be
helper_info_atomic_fetch_smaxl_le
helper_info_atomic_fetch_smaxq_be
helper_info_atomic_fetch_smaxq_le
helper_info_atomic_fetch_smaxw_be
helper_info_atomic_fetch_smaxw_le
helper_info_atomic_fetch_sminb
helper_info_atomic_fetch_sminl_be
helper_info_atomic_fetch_sminl_le
helper_info_atomic_fetch_sminq_be
helper_info_atomic_fetch_sminq_le
helper_info_atomic_fetch_sminw_be
helper_info_atomic_fetch_sminw_le
helper_info_atomic_fetch_umaxb
helper_info_atomic_fetch_umaxl_be
helper_info_atomic_fetch_umaxl_le
helper_info_atomic_fetch_umaxq_be
helper_info_atomic_fetch_umaxq_le
helper_info_atomic_fetch_umaxw_be
helper_info_atomic_fetch_umaxw_le
helper_info_atomic_fetch_uminb
helper_info_atomic_fetch_uminl_be
helper_info_atomic_fetch_uminl_le
helper_info_atomic_fetch_uminq_be
helper_info_atomic_fetch_uminq_le
helper_info_atomic_fetch_uminw_be
helper_info_atomic_fetch_uminw_le
helper_info_atomic_fetch_xorb
helper_info_atomic_fetch_xorl_be
helper_info_atomic_fetch_xorl_le
helper_info_atomic_fetch_xorq_be
helper_info_atomic_fetch_xorq_le
helper_info_atomic_fetch_xorw_be
helper_info_atomic_fetch_xorw_le
helper_info_atomic_or_fetchb
helper_info_atomic_or_fetchl_be
helper_info_atomic_or_fetchl_le
helper_info_atomic_or_fetchq_be
helper_info_atomic_or_fetchq_le
helper_info_atomic_or_fetchw_be
helper_info_atomic_or_fetchw_le
helper_info_atomic_smax_fetchb
helper_info_atomic_smax_fetchl_be
helper_info_atomic_smax_fetchl_le
helper_info_atomic_smax_fetchq_be
helper_info_atomic_smax_fetchq_le
helper_info_atomic_smax_fetchw_be
helper_info_atomic_smax_fetchw_le
helper_info_atomic_smin_fetchb
helper_info_atomic_smin_fetchl_be
helper_info_atomic_smin_fetchl_le
helper_info_atomic_smin_fetchq_be
helper_info_atomic_smin_fetchq_le
helper_info_atomic_smin_fetchw_be
helper_info_atomic_smin_fetchw_le
helper_info_atomic_umax_fetchb
helper_info_atomic_umax_fetchl_be
helper_info_atomic_umax_fetchl_le
helper_info_atomic_umax_fetchq_be
helper_info_atomic_umax_fetchq_le
helper_info_atomic_umax_fetchw_be
helper_info_atomic_umax_fetchw_le
helper_info_atomic_umin_fetchb
helper_info_atomic_umin_fetchl_be
helper_info_atomic_umin_fetchl_le
helper_info_atomic_umin_fetchq_be
helper_info_atomic_umin_fetchq_le
helper_info_atomic_umin_fetchw_be
helper_info_atomic_umin_fetchw_le
helper_info_atomic_xchgb
helper_info_atomic_xchgl_be
helper_info_atomic_xchgl_le
helper_info_atomic_xchgq_be
helper_info_atomic_xchgq_le
helper_info_atomic_xchgw_be
helper_info_atomic_xchgw_le
helper_info_atomic_xor_fetchb
helper_info_atomic_xor_fetchl_be
helper_info_atomic_xor_fetchl_le
helper_info_atomic_xor_fetchq_be
helper_info_atomic_xor_fetchq_le
helper_info_atomic_xor_fetchw_be
helper_info_atomic_xor_fetchw_le
helper_info_clrsb_i32
helper_info_clrsb_i64
helper_info_clz_i32
helper_info_clz_i64
helper_info_ctpop_i32
helper_info_ctpop_i64
helper_info_ctz_i32
helper_info_ctz_i64
helper_info_div_i32
helper_info_div_i64
helper_info_divs
helper_info_divu
helper_info_divu_i32
helper_info_divu_i64
helper_info_exit_atomic
helper_info_fadd
helper_info_fcmp_eq
helper_info_fcmp_ge
helper_info_fcmp_gt
helper_info_fcmp_le
helper_info_fcmp_lt
helper_info_fcmp_ne
helper_info_fcmp_un
helper_info_fdiv
helper_info_fint
helper_info_flt
helper_info_fmul
helper_info_frsub
helper_info_fsqrt
helper_info_get
helper_info_gvec_abs16
helper_info_gvec_abs32
helper_info_gvec_abs64
helper_info_gvec_abs8
helper_info_gvec_add16
helper_info_gvec_add32
helper_info_gvec_add64
helper_info_gvec_add8
helper_info_gvec_adds16
helper_info_gvec_adds32
helper_info_gvec_adds64
helper_info_gvec_adds8
helper_info_gvec_and
helper_info_gvec_andc
helper_info_gvec_andcs
helper_info_gvec_ands
helper_info_gvec_bitsel
helper_info_gvec_dup16
helper_info_gvec_dup32
helper_info_gvec_dup64
helper_info_gvec_dup8
helper_info_gvec_eq16
helper_info_gvec_eq32
helper_info_gvec_eq64
helper_info_gvec_eq8
helper_info_gvec_eqs16
helper_info_gvec_eqs32
helper_info_gvec_eqs64
helper_info_gvec_eqs8
helper_info_gvec_eqv
helper_info_gvec_le16
helper_info_gvec_le32
helper_info_gvec_le64
helper_info_gvec_le8
helper_info_gvec_les16
helper_info_gvec_les32
helper_info_gvec_les64
helper_info_gvec_les8
helper_info_gvec_leu16
helper_info_gvec_leu32
helper_info_gvec_leu64
helper_info_gvec_leu8
helper_info_gvec_leus16
helper_info_gvec_leus32
helper_info_gvec_leus64
helper_info_gvec_leus8
helper_info_gvec_lt16
helper_info_gvec_lt32
helper_info_gvec_lt64
helper_info_gvec_lt8
helper_info_gvec_lts16
helper_info_gvec_lts32
helper_info_gvec_lts64
helper_info_gvec_lts8
helper_info_gvec_ltu16
helper_info_gvec_ltu32
helper_info_gvec_ltu64
helper_info_gvec_ltu8
helper_info_gvec_ltus16
helper_info_gvec_ltus32
helper_info_gvec_ltus64
helper_info_gvec_ltus8
helper_info_gvec_mov
helper_info_gvec_mul16
helper_info_gvec_mul32
helper_info_gvec_mul64
helper_info_gvec_mul8
helper_info_gvec_muls16
helper_info_gvec_muls32
helper_info_gvec_muls64
helper_info_gvec_muls8
helper_info_gvec_nand
helper_info_gvec_ne16
helper_info_gvec_ne32
helper_info_gvec_ne64
helper_info_gvec_ne8
helper_info_gvec_neg16
helper_info_gvec_neg32
helper_info_gvec_neg64
helper_info_gvec_neg8
helper_info_gvec_nor
helper_info_gvec_not
helper_info_gvec_or
helper_info_gvec_orc
helper_info_gvec_ors
helper_info_gvec_rotl16i
helper_info_gvec_rotl16v
helper_info_gvec_rotl32i
helper_info_gvec_rotl32v
helper_info_gvec_rotl64i
helper_info_gvec_rotl64v
helper_info_gvec_rotl8i
helper_info_gvec_rotl8v
helper_info_gvec_rotr16v
helper_info_gvec_rotr32v
helper_info_gvec_rotr64v
helper_info_gvec_rotr8v
helper_info_gvec_sar16i
helper_info_gvec_sar16v
helper_info_gvec_sar32i
helper_info_gvec_sar32v
helper_info_gvec_sar64i
helper_info_gvec_sar64v
helper_info_gvec_sar8i
helper_info_gvec_sar8v
helper_info_gvec_shl16i
helper_info_gvec_shl16v
helper_info_gvec_shl32i
helper_info_gvec_shl32v
helper_info_gvec_shl64i
helper_info_gvec_shl64v
helper_info_gvec_shl8i
helper_info_gvec_shl8v
helper_info_gvec_shr16i
helper_info_gvec_shr16v
helper_info_gvec_shr32i
helper_info_gvec_shr32v
helper_info_gvec_shr64i
helper_info_gvec_shr64v
helper_info_gvec_shr8i
helper_info_gvec_shr8v
helper_info_gvec_smax16
helper_info_gvec_smax32
helper_info_gvec_smax64
helper_info_gvec_smax8
helper_info_gvec_smin16
helper_info_gvec_smin32
helper_info_gvec_smin64
helper_info_gvec_smin8
helper_info_gvec_ssadd16
helper_info_gvec_ssadd32
helper_info_gvec_ssadd64
helper_info_gvec_ssadd8
helper_info_gvec_sssub16
helper_info_gvec_sssub32
helper_info_gvec_sssub64
helper_info_gvec_sssub8
helper_info_gvec_sub16
helper_info_gvec_sub32
helper_info_gvec_sub64
helper_info_gvec_sub8
helper_info_gvec_subs16
helper_info_gvec_subs32
helper_info_gvec_subs64
helper_info_gvec_subs8
helper_info_gvec_umax16
helper_info_gvec_umax32
helper_info_gvec_umax64
helper_info_gvec_umax8
helper_info_gvec_umin16
helper_info_gvec_umin32
helper_info_gvec_umin64
helper_info_gvec_umin8
helper_info_gvec_usadd16
helper_info_gvec_usadd32
helper_info_gvec_usadd64
helper_info_gvec_usadd8
helper_info_gvec_ussub16
helper_info_gvec_ussub32
helper_info_gvec_ussub64
helper_info_gvec_ussub8
helper_info_gvec_xor
helper_info_gvec_xors
helper_info_ld_i128
helper_info_lookup_tb_ptr
helper_info_memset
helper_info_mmu_read
helper_info_mmu_write
helper_info_mulsh_i64
helper_info_muluh_i64
helper_info_nonatomic_cmpxchgo
helper_info_pcmpbf
helper_info_put
helper_info_raise_exception
helper_info_rem_i32
helper_info_rem_i64
helper_info_remu_i32
helper_info_remu_i64
helper_info_sar_i64
helper_info_shl_i64
helper_info_shr_i64
helper_info_st_i128
helper_info_stackprot
helper_ld16_mmu
helper_ld_i128
helper_ldq_mmu
helper_ldsb_mmu
helper_ldsl_mmu
helper_ldsw_mmu
helper_ldub_mmu
helper_ldul_mmu
helper_lduw_mmu
helper_lookup_tb_ptr
helper_mmu_read
helper_mmu_write
helper_mulsh_i64
helper_muluh_i64
helper_nonatomic_cmpxchgo
helper_pcmpbf
helper_put
helper_raise_exception
helper_rem_i32
helper_rem_i64
helper_remu_i32
helper_remu_i64
helper_sar_i64
helper_shl_i64
helper_shr_i64
helper_st16_mmu
helper_st_i128
helper_stackprot
helper_stb_mmu
helper_stl_mmu
helper_stq_mmu
helper_stw_mmu
hmp_cmds
hmp_compare_cmd
hmp_gpa2hva
hmp_gva2gpa
hmp_info_registers
hmp_memory_dump
hmp_physical_memory_dump
icount_handle_deadline
icount_handle_interrupt
icount_percpu_budget
icount_prepare_for_run
icount_process_data
iotlb_to_section
kvm_allowed
kvm_arm_supports_user_irq
kvm_async_interrupts_allowed
kvm_cpu_synchronize_state
kvm_create_guest_memfd
kvm_dirty_ring_enabled
kvm_dirty_ring_size
kvm_flush_coalesced_mmio_buffer
kvm_get_free_memslots
kvm_get_max_memslots
kvm_gsi_direct_mapping
kvm_gsi_routing_allowed
kvm_has_sync_mmu
kvm_hwpoisoned_mem
kvm_init_cpu_signals
kvm_init_irq_routing
kvm_irqchip_add_change_notifier
kvm_irqchip_add_irqfd_notifier_gsi
kvm_irqchip_add_msi_route
kvm_irqchip_change_notify
kvm_irqchip_commit_routes
kvm_irqchip_release_virq
kvm_irqchip_remove_change_notifier
kvm_irqchip_remove_irqfd_notifier_gsi
kvm_irqchip_update_msi_route
kvm_kernel_irqchip
kvm_msi_use_devid
kvm_msi_via_irqfd_allowed
kvm_on_sigbus
kvm_on_sigbus_vcpu
kvm_readonly_mem_allowed
kvm_resamplefds_allowed
kvm_state
list_cpus
max_advance
max_delay
memory_access_size
memory_get_xlat_addr
memory_global_after_dirty_log_sync
memory_global_dirty_log_start
memory_global_dirty_log_stop
memory_global_dirty_log_sync
memory_listener_register
memory_listener_unregister
memory_region_access_valid
memory_region_add_coalescing
memory_region_add_eventfd
memory_region_add_subregion
memory_region_add_subregion_overlap
memory_region_clear_coalescing
memory_region_clear_dirty_bitmap
memory_region_clear_flush_coalesced
memory_region_del_eventfd
memory_region_del_subregion
memory_region_dispatch_read
memory_region_dispatch_write
memory_region_find
memory_region_flush_rom_device
memory_region_from_host
memory_region_get_alignment
memory_region_get_dirty_log_mask
memory_region_get_fd
memory_region_get_ram_addr
memory_region_get_ram_discard_manager
memory_region_get_ram_ptr
memory_region_has_guest_memfd
memory_region_init
memory_region_init_alias
memory_region_init_io
memory_region_init_iommu
memory_region_init_ram
memory_region_init_ram_device_ptr
memory_region_init_ram_flags_nomigrate
memory_region_init_ram_from_fd
memory_region_init_ram_from_file
memory_region_init_ram_guest_memfd
memory_region_init_ram_nomigrate
memory_region_init_ram_ptr
memory_region_init_resizeable_ram
memory_region_init_rom
memory_region_init_rom_device
memory_region_init_rom_device_nomigrate
memory_region_init_rom_nomigrate
memory_region_iommu_attrs_to_index
memory_region_iommu_get_attr
memory_region_iommu_get_min_page_size
memory_region_iommu_num_indexes
memory_region_iommu_replay
memory_region_is_logging
memory_region_is_mapped
memory_region_is_protected
memory_region_is_ram_device
memory_region_msync
memory_region_name
memory_region_notify_iommu
memory_region_notify_iommu_one
memory_region_owner
memory_region_present
memory_region_ram_resize
memory_region_ref
memory_region_register_iommu_notifier
memory_region_reset_dirty
memory_region_rom_device_set_romd
memory_region_section_free_copy
memory_region_section_get_iotlb
memory_region_section_new_copy
memory_region_set_address
memory_region_set_alias_offset
memory_region_set_coalescing
memory_region_set_dirty
memory_region_set_enabled
memory_region_set_flush_coalesced
memory_region_set_log
memory_region_set_nonvolatile
memory_region_set_ram_discard_manager
memory_region_set_readonly
memory_region_set_size
memory_region_set_unmergeable
memory_region_size
memory_region_snapshot_and_clear_dirty
memory_region_snapshot_get_dirty
memory_region_transaction_begin
memory_region_transaction_commit
memory_region_unmap_iommu_notifier_range
memory_region_unref
memory_region_unregister_iommu_notifier
memory_region_writeback
microblaze_load_kernel
mig_throttle_counter_reset
migrate_ram_is_ignored
migration_bitmap_sync_precopy
migration_populate_vfio_info
migration_reset_vfio_bytes_transferred
mmu_init
mmu_read
mmu_translate
mmu_write
mon_get_cpu
mon_get_cpu_env
monitor_get_cpu_index
monitor_register_hmp
monitor_register_hmp_info_hrt
monitor_set_cpu
mtree_info
mtree_print_dispatch
mttcg_enabled
mttcg_kick_vcpu_thread
mttcg_start_vcpu_thread
one_insn_per_tb
page_init
page_table_config_init
parse_cpu_option
portio_list_add
portio_list_del
portio_list_destroy
portio_list_init
portio_list_set_address
portio_list_set_enabled
portio_list_set_flush_coalesced
postcopy_preempt_shutdown_file
precopy_add_notifier
precopy_infrastructure_init
precopy_notify
precopy_remove_notifier
prepare_mmio_access
probe_access
probe_access_flags
probe_access_full
probe_access_full_mmu
qapi_dummy_qapi_commands_c
qapi_dummy_qapi_commands_machine_target_c
qapi_dummy_qapi_commands_misc_target_c
qapi_dummy_qapi_emit_events_c
qapi_dummy_qapi_events_c
qapi_dummy_qapi_events_machine_target_c
qapi_dummy_qapi_events_misc_target_c
qapi_dummy_qapi_init_commands_c
qapi_dummy_qapi_introspect_c
qapi_dummy_qapi_types_c
qapi_dummy_qapi_types_machine_target_c
qapi_dummy_qapi_types_misc_target_c
qapi_dummy_qapi_visit_c
qapi_dummy_qapi_visit_machine_target_c
qapi_dummy_qapi_visit_misc_target_c
qapi_free_CpuModelInfo
qapi_free_SGXEPCSection
qapi_free_SGXEPCSectionList
qemu_flush_coalesced_mmio_buffer
qemu_guest_free_page_hint
qemu_init_arch_modules
qemu_map_ram_ptr
qemu_maxrampagesize
qemu_minrampagesize
qemu_mutex_lock_ramlist
qemu_mutex_unlock_ramlist
qemu_ram_addr_from_host
qemu_ram_addr_from_host_nofail
qemu_ram_alloc
qemu_ram_alloc_from_fd
qemu_ram_alloc_from_file
qemu_ram_alloc_from_ptr
qemu_ram_alloc_resizeable
qemu_ram_block_by_name
qemu_ram_block_from_host
qemu_ram_block_host_offset
qemu_ram_foreach_block
qemu_ram_free
qemu_ram_get_fd
qemu_ram_get_host_addr
qemu_ram_get_idstr
qemu_ram_get_max_length
qemu_ram_get_offset
qemu_ram_get_used_length
qemu_ram_is_migratable
qemu_ram_is_named_file
qemu_ram_is_noreserve
qemu_ram_is_shared
qemu_ram_is_uf_zeroable
qemu_ram_msync
qemu_ram_pagesize
qemu_ram_pagesize_largest
qemu_ram_remap
qemu_ram_resize
qemu_ram_set_idstr
qemu_ram_set_migratable
qemu_ram_set_uf_zeroable
qemu_ram_unset_idstr
qemu_ram_unset_migratable
qemu_semihosting_guestfd_init
qemu_target_page_bits
qemu_target_page_bits_min
qemu_target_page_mask
qemu_target_page_size
qemu_target_pages_to_MiB
qmp_init_marshal
qmp_query_hv_balloon_status_report
qmp_schema_qlit
qmp_xen_set_global_dirty_log
ram_block_coordinated_discard_require
ram_block_discard_disable
ram_block_discard_guest_memfd_range
ram_block_discard_is_disabled
ram_block_discard_is_required
ram_block_discard_range
ram_block_discard_require
ram_block_format
ram_block_uncoordinated_discard_disable
ram_bytes_remaining
ram_bytes_total
ram_dirty_bitmap_reload
ram_discard_manager_get_min_granularity
ram_discard_manager_is_populated
ram_discard_manager_register_listener
ram_discard_manager_replay_discarded
ram_discard_manager_replay_populated
ram_discard_manager_unregister_listener
ram_discard_range
ram_get_total_transferred_pages
ram_handle_zero
ram_list
ram_load_postcopy
ram_mig_init
ram_pagesize_summary
ram_postcopy_incoming_init
ram_postcopy_migrated_memory_release
ram_postcopy_send_discard_bitmap
ram_release_page
ram_save_queue_pages
ram_transferred_add
ram_write_tracking_available
ram_write_tracking_compatible
ram_write_tracking_start
ram_write_tracking_stop
ramblock_is_pmem
ramblock_page_is_discarded
ramblock_recv_bitmap_send
ramblock_recv_bitmap_set
ramblock_recv_bitmap_set_offset
ramblock_recv_bitmap_set_range
ramblock_recv_bitmap_test
ramblock_recv_bitmap_test_byte_offset
ramblock_set_file_bmap_atomic
rr_kick_vcpu_thread
rr_start_vcpu_thread
set_preferred_target_page_bits
target_name
target_words_bigendian
tb_check_watchpoint
tb_ctx
tb_flush
tb_gen_code
tb_htable_init
tb_invalidate_phys_range
tb_invalidate_phys_range_fast
tb_link_page
tb_lock_page0
tb_lock_page1
tb_phys_invalidate
tb_reset_jump
tb_set_jmp_target
tb_unlock_page1
tb_unlock_pages
tcg_cflags_has
tcg_cflags_set
tcg_cpu_destroy
tcg_cpu_exec
tcg_cpu_init_cflags
tcg_exec_realizefn
tcg_exec_unrealizefn
tcg_flush_jmp_cache
tcg_handle_interrupt
tcg_iommu_free_notifier_list
tcg_iommu_init_notifier_list
tlb_destroy
tlb_flush
tlb_flush_all_cpus_synced
tlb_flush_by_mmuidx
tlb_flush_by_mmuidx_all_cpus_synced
tlb_flush_page
tlb_flush_page_all_cpus_synced
tlb_flush_page_bits_by_mmuidx
tlb_flush_page_bits_by_mmuidx_all_cpus_synced
tlb_flush_page_by_mmuidx
tlb_flush_page_by_mmuidx_all_cpus_synced
tlb_flush_range_by_mmuidx
tlb_flush_range_by_mmuidx_all_cpus_synced
tlb_init
tlb_protect_code
tlb_reset_dirty
tlb_reset_dirty_range_all
tlb_set_page
tlb_set_page_full
tlb_set_page_with_attrs
tlb_unprotect_code
tlb_vaddr_to_host
trace_event_set_state_dynamic
trace_event_set_state_dynamic_init
translator_fake_ld
translator_io_start
translator_is_same_page
translator_ldl
translator_ldq
translator_ldub
translator_lduw
translator_loop
translator_st
translator_st_len
translator_use_goto_tb
unassigned_io_ops
unassigned_mem_ops
visit_type_CpuModelCompareResult
visit_type_CpuModelExpansionType
visit_type_CpuModelInfo
visit_type_CpuModelInfo_members
visit_type_SGXEPCSection
visit_type_SGXEPCSectionList
visit_type_SGXEPCSection_members
vmstate_cpu_common
win_dump_available
xbzrle_cache_resize
xbzrle_counters
xen_allowed
xen_evtchn_deliver_pirq_msi
xen_evtchn_remove_pci_device
xen_evtchn_snoop_msi
xen_primary_console_create
xen_primary_console_set_be_port
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-20 8:48 ` [PATCH 00/10] fpu: Remove remaining target ifdefs and build " Philippe Mathieu-Daudé
2025-02-20 9:00 ` Philippe Mathieu-Daudé
@ 2025-02-21 10:48 ` Philippe Mathieu-Daudé
1 sibling, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 10:48 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier, Thomas Huth
On 20/2/25 09:48, Philippe Mathieu-Daudé wrote:
> On 17/2/25 13:50, Peter Maydell wrote:
>> The work I needed to do to make various softfloat emulation behaviours
>> runtime-selectable for Arm FEAT_AFP has left the fpu code with very
>> few remaning target ifdefs. So this series turns the last remaning
>> ones into runtime behaviour choices and switches the fpu code into
>> "build once" rather than "build per target". The main driver of this
>> is that we're going to want to do this for the "multiple targets in
>> one binary" work.
> FWIW:
> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Oops, that tag is only for patch 10 (meson buildsys change), not for
the whole series.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (10 preceding siblings ...)
2025-02-20 8:48 ` [PATCH 00/10] fpu: Remove remaining target ifdefs and build " Philippe Mathieu-Daudé
@ 2025-02-21 13:05 ` Philippe Mathieu-Daudé
2025-02-21 13:28 ` Peter Maydell
2025-02-21 14:41 ` Philippe Mathieu-Daudé
12 siblings, 1 reply; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 13:05 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
Hi Peter,
On 17/2/25 13:50, Peter Maydell wrote:
> (1) floatx80 behaviours
>
> Two QEMU targets implement floatx80: x86 and m68k. (PPC also has one
> use in the xsrqpxp round-to-80-bit-precision operation, and the
> Linux-user NWFPE emulation nominally supports it, but these are
> minor.) x86 and m68k disagree about some of the corner cases of
> floatx80 where the value has the explicit Integer bit wrongly set. At
> the moment the fpu code defaults to "floatx80 behaves like x86", with
> TARGET_M68K ifdefs to get the other option.
>
> The first six patches in this series remove those ifdefs, replacing
> them with a floatx80_behaviour field in float_status which can have
> various flags set to select the individual behaviours. The default is
> "like x86", which allows us to set these only for m68k and not worry
> about the minor "technically makes some use of floatx80" cases.
> Peter Maydell (10):
> fpu: Make targets specify floatx80 default Inf at runtime
> target/m68k: Avoid using floatx80_infinity global const
> target/i386: Avoid using floatx80_infinity global const
Could you add a preparatory patch passing float_status argument
here? This eases the following patch review.
-- >8 --
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index afae3906024..3c83d703baf 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -999 +999 @@ static inline floatx80 floatx80_chs(floatx80 a)
-static inline bool floatx80_is_infinity(floatx80 a)
+static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 741af09f908..3b79bc049d1 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1395,3 +1395,4 @@ void helper_fpatan(CPUX86State *env)
/* Pass this zero through. */
- } else if (((floatx80_is_infinity(ST0) &&
!floatx80_is_infinity(ST1)) ||
+ } else if (((floatx80_is_infinity(ST0, &env->fp_status) &&
+ !floatx80_is_infinity(ST1, &env->fp_status)) ||
arg0_exp - arg1_exp >= 80) &&
@@ -1444,4 +1445,4 @@ void helper_fpatan(CPUX86State *env)
rsig1 = pi_sig_low;
- } else if (floatx80_is_infinity(ST1)) {
- if (floatx80_is_infinity(ST0)) {
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
if (arg0_sign) {
@@ -1464,3 +1465,4 @@ void helper_fpatan(CPUX86State *env)
rsig1 = pi_2_sig_low;
- } else if (floatx80_is_infinity(ST0) || arg0_exp - arg1_exp >=
80) {
+ } else if (floatx80_is_infinity(ST0, &env->fp_status) ||
+ arg0_exp - arg1_exp >= 80) {
/* ST0 is negative. */
@@ -1831,3 +1833,3 @@ void helper_fxtract(CPUX86State *env)
ST0 = ST1;
- } else if (floatx80_is_infinity(ST0)) {
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
fpush(env);
@@ -2175,3 +2177,3 @@ void helper_fyl2x(CPUX86State *env)
ST1 = floatx80_default_nan(&env->fp_status);
- } else if (floatx80_is_infinity(ST1)) {
+ } else if (floatx80_is_infinity(ST1, &env->fp_status)) {
FloatRelation cmp = floatx80_compare(ST0, floatx80_one,
@@ -2190,3 +2192,3 @@ void helper_fyl2x(CPUX86State *env)
}
- } else if (floatx80_is_infinity(ST0)) {
+ } else if (floatx80_is_infinity(ST0, &env->fp_status)) {
if (floatx80_is_zero(ST1)) {
@@ -2343,3 +2345,3 @@ void helper_fscale(CPUX86State *env)
}
- } else if (floatx80_is_infinity(ST1) &&
+ } else if (floatx80_is_infinity(ST1, &env->fp_status) &&
!floatx80_invalid_encoding(ST0) &&
@@ -2347,3 +2349,3 @@ void helper_fscale(CPUX86State *env)
if (floatx80_is_neg(ST1)) {
- if (floatx80_is_infinity(ST0)) {
+ if (floatx80_is_infinity(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 339b73ad7dc..eb1cb8c6872 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -458 +458 @@ void HELPER(ftst)(CPUM68KState *env, FPReg *val)
- } else if (floatx80_is_infinity(val->d)) {
+ } else if (floatx80_is_infinity(val->d, &env->fp_status)) {
---
> fpu: Make targets specify whether floatx80 Inf can have Int bit clear
Ditto here:
-- >8 --
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 07259c59303..1c8f3cbb78d 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -1084 +1084 @@ static inline bool floatx80_unordered_quiet(floatx80
a, floatx80 b,
-static inline bool floatx80_invalid_encoding(floatx80 a)
+static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b12ad2b42a9..2a20ae871eb 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1813 +1813 @@ static bool floatx80_unpack_canonical(FloatParts128
*p, floatx80 f,
- if (unlikely(floatx80_invalid_encoding(f))) {
+ if (unlikely(floatx80_invalid_encoding(f, s))) {
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 3b79bc049d1..4858ae9a5fb 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1143,3 +1143,3 @@ void helper_f2xm1(CPUX86State *env)
- if (floatx80_invalid_encoding(ST0)) {
+ if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
@@ -1385,4 +1385,4 @@ void helper_fpatan(CPUX86State *env)
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
- } else if (floatx80_invalid_encoding(ST0) ||
- floatx80_invalid_encoding(ST1)) {
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
@@ -1821,3 +1821,3 @@ void helper_fxtract(CPUX86State *env)
ST0 = temp.d;
- } else if (floatx80_invalid_encoding(ST0)) {
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
@@ -1872,3 +1872,4 @@ static void helper_fprem_common(CPUX86State *env,
bool mod)
exp0 == 0x7fff || exp1 == 0x7fff ||
- floatx80_invalid_encoding(ST0) || floatx80_invalid_encoding(ST1)) {
+ floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
ST0 = floatx80_modrem(ST0, ST1, mod, "ient, &env->fp_status);
@@ -2068,4 +2069,4 @@ void helper_fyl2xp1(CPUX86State *env)
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
- } else if (floatx80_invalid_encoding(ST0) ||
- floatx80_invalid_encoding(ST1)) {
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
@@ -2166,4 +2167,4 @@ void helper_fyl2x(CPUX86State *env)
ST1 = floatx80_silence_nan(ST1, &env->fp_status);
- } else if (floatx80_invalid_encoding(ST0) ||
- floatx80_invalid_encoding(ST1)) {
+ } else if (floatx80_invalid_encoding(ST0, &env->fp_status) ||
+ floatx80_invalid_encoding(ST1, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
@@ -2333,3 +2334,4 @@ void helper_fscale(CPUX86State *env)
uint8_t old_flags = save_exception_flags(env);
- if (floatx80_invalid_encoding(ST1) || floatx80_invalid_encoding(ST0)) {
+ if (floatx80_invalid_encoding(ST1, &env->fp_status) ||
+ floatx80_invalid_encoding(ST0, &env->fp_status)) {
float_raise(float_flag_invalid, &env->fp_status);
@@ -2346,3 +2348,3 @@ void helper_fscale(CPUX86State *env)
} else if (floatx80_is_infinity(ST1, &env->fp_status) &&
- !floatx80_invalid_encoding(ST0) &&
+ !floatx80_invalid_encoding(ST0, &env->fp_status) &&
!floatx80_is_any_nan(ST0)) {
---
> fpu: Make floatx80 invalid encoding settable at runtime
> fpu: Move m68k_denormal fmt flag into floatx80_behaviour
> fpu: Always decide no_signaling_nans() at runtime
> fpu: Always decide snan_bit_is_one() at runtime
> fpu: Don't compile-time disable hardfloat for PPC targets
> fpu: Build only once
Thanks,
Phil.
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-21 13:05 ` Philippe Mathieu-Daudé
@ 2025-02-21 13:28 ` Peter Maydell
2025-02-21 13:48 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2025-02-21 13:28 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On Fri, 21 Feb 2025 at 13:05, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> Hi Peter,
>
> On 17/2/25 13:50, Peter Maydell wrote:
>
> > (1) floatx80 behaviours
> >
> > Two QEMU targets implement floatx80: x86 and m68k. (PPC also has one
> > use in the xsrqpxp round-to-80-bit-precision operation, and the
> > Linux-user NWFPE emulation nominally supports it, but these are
> > minor.) x86 and m68k disagree about some of the corner cases of
> > floatx80 where the value has the explicit Integer bit wrongly set. At
> > the moment the fpu code defaults to "floatx80 behaves like x86", with
> > TARGET_M68K ifdefs to get the other option.
> >
> > The first six patches in this series remove those ifdefs, replacing
> > them with a floatx80_behaviour field in float_status which can have
> > various flags set to select the individual behaviours. The default is
> > "like x86", which allows us to set these only for m68k and not worry
> > about the minor "technically makes some use of floatx80" cases.
>
>
> > Peter Maydell (10):
> > fpu: Make targets specify floatx80 default Inf at runtime
> > target/m68k: Avoid using floatx80_infinity global const
> > target/i386: Avoid using floatx80_infinity global const
>
> Could you add a preparatory patch passing float_status argument
> here? This eases the following patch review.
I could, and in retrospect I agree it would have been a better
division of patches, but both you and RTH have already reviewed
patches 4 and 5 in their current form, so is it worth doing now ?
thanks
-- PMM
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-21 13:28 ` Peter Maydell
@ 2025-02-21 13:48 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 13:48 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 21/2/25 14:28, Peter Maydell wrote:
> On Fri, 21 Feb 2025 at 13:05, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>>
>> Hi Peter,
>>
>> On 17/2/25 13:50, Peter Maydell wrote:
>>
>>> (1) floatx80 behaviours
>>>
>>> Two QEMU targets implement floatx80: x86 and m68k. (PPC also has one
>>> use in the xsrqpxp round-to-80-bit-precision operation, and the
>>> Linux-user NWFPE emulation nominally supports it, but these are
>>> minor.) x86 and m68k disagree about some of the corner cases of
>>> floatx80 where the value has the explicit Integer bit wrongly set. At
>>> the moment the fpu code defaults to "floatx80 behaves like x86", with
>>> TARGET_M68K ifdefs to get the other option.
>>>
>>> The first six patches in this series remove those ifdefs, replacing
>>> them with a floatx80_behaviour field in float_status which can have
>>> various flags set to select the individual behaviours. The default is
>>> "like x86", which allows us to set these only for m68k and not worry
>>> about the minor "technically makes some use of floatx80" cases.
>>
>>
>>> Peter Maydell (10):
>>> fpu: Make targets specify floatx80 default Inf at runtime
>>> target/m68k: Avoid using floatx80_infinity global const
>>> target/i386: Avoid using floatx80_infinity global const
>>
>> Could you add a preparatory patch passing float_status argument
>> here? This eases the following patch review.
>
> I could, and in retrospect I agree it would have been a better
> division of patches, but both you and RTH have already reviewed
> patches 4 and 5 in their current form, so is it worth doing now ?
If it isn't too much a burden, I'd prefer to have the extra patches
included. Not for today's review, but for our future readers learning
from the git history (as I'm custom to).
I understand you are waiting RTH's ack on patch #6 to update it and
don't plan to respin. If you agree to split, I suppose it isn't in
your principles to merge a series without posting the final result
on the list. I have the patches locally split so can post as v2 base
if that helps. Otherwise I won't insist, up to your workflow :)
Regards,
Phil.
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-17 12:50 [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once Peter Maydell
` (11 preceding siblings ...)
2025-02-21 13:05 ` Philippe Mathieu-Daudé
@ 2025-02-21 14:41 ` Philippe Mathieu-Daudé
2025-02-21 15:19 ` Peter Maydell
12 siblings, 1 reply; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 14:41 UTC (permalink / raw)
To: Peter Maydell, qemu-devel
Cc: Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 17/2/25 13:50, Peter Maydell wrote:
> (1) floatx80 behaviours
>
> Two QEMU targets implement floatx80: x86 and m68k. (PPC also has one
> use in the xsrqpxp round-to-80-bit-precision operation, and the
> Linux-user NWFPE emulation nominally supports it, but these are
> minor.) x86 and m68k disagree about some of the corner cases of
> floatx80 where the value has the explicit Integer bit wrongly set. At
> the moment the fpu code defaults to "floatx80 behaves like x86", with
> TARGET_M68K ifdefs to get the other option.
>
> The first six patches in this series remove those ifdefs, replacing
> them with a floatx80_behaviour field in float_status which can have
> various flags set to select the individual behaviours. The default is
> "like x86", which allows us to set these only for m68k and not worry
> about the minor "technically makes some use of floatx80" cases.
> Peter Maydell (10):
> fpu: Make targets specify floatx80 default Inf at runtime
> target/m68k: Avoid using floatx80_infinity global const
> target/i386: Avoid using floatx80_infinity global const
Bothering again, we can add the floatx80_default_inf() refactor as the
first patch:
-- >8 --
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 09a40b43106..afae3906024 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -963,0 +964 @@ extern const floatx80 floatx80_infinity;
+floatx80 floatx80_default_inf(bool zSign, float_status *status);
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index f4fed9bfda9..f56ae886c53 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5147,3 +5147 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec
roundingPrecision, bool zSign,
- return packFloatx80(zSign,
- floatx80_infinity_high,
- floatx80_infinity_low);
+ return floatx80_default_inf(zSign, status);
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index f112c6c6737..741af09f908 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1835 +1835 @@ void helper_fxtract(CPUX86State *env)
- ST1 = floatx80_infinity;
+ ST1 = floatx80_default_inf(0, &env->fp_status);
@@ -2361,3 +2361,2 @@ void helper_fscale(CPUX86State *env)
- ST0 = (floatx80_is_neg(ST0) ?
- floatx80_chs(floatx80_infinity) :
- floatx80_infinity);
+ ST0 = floatx80_default_inf(floatx80_is_neg(ST0),
+ &env->fp_status);
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 02dcc03d15d..d1f150e641f 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -145,2 +145 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b,
float_status *status)
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
@@ -248 +247 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -258,2 +257 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
@@ -445,2 +443 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -455,2 +452 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
- return packFloatx80(1, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(1, status);
@@ -613,2 +609 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -620,2 +615 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
- return packFloatx80(1, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(1, status);
@@ -671,2 +665 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -679,2 +672 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
- return packFloatx80(1, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(1, status);
@@ -743,2 +735 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -927,2 +918 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -1078,2 +1068 @@ floatx80 floatx80_tentox(floatx80 a, float_status
*status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -2263,2 +2252 @@ floatx80 floatx80_atanh(floatx80 a, float_status
*status)
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
@@ -2323,2 +2311 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status
*status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
@@ -2690,2 +2677 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
- return packFloatx80(aSign, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(aSign, status);
@@ -2777,2 +2763 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
- return packFloatx80(0, floatx80_infinity.high,
- floatx80_infinity.low);
+ return floatx80_default_inf(0, status);
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index cbbbab52ba3..403f7a9d69d 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -239,0 +240,5 @@ const floatx80 floatx80_infinity
+floatx80 floatx80_default_inf(bool zSign, float_status *status)
+{
+ return packFloatx80(zSign, floatx80_infinity_high,
floatx80_infinity_low);
+}
+
---
The single non-obvious thing to mention is the x86 floatx80_chs()
removal.
This effectively absorb patch #3 (x86).
Then patch #2 (m68k) becomes:
-- >8 --
diff --git a/include/fpu/softfloat-helpers.h
b/include/fpu/softfloat-helpers.h
index 8983c2748ec..90862f5cd22 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -77,0 +78,6 @@ static inline void
set_floatx80_rounding_precision(FloatX80RoundPrec val,
+static inline void set_floatx80_behaviour(FloatX80Behaviour b,
+ float_status *status)
+{
+ status->floatx80_behaviour = b;
+}
+
@@ -153,0 +160,6 @@ get_floatx80_rounding_precision(const float_status
*status)
+static inline FloatX80Behaviour
+get_floatx80_behaviour(const float_status *status)
+{
+ return status->floatx80_behaviour;
+}
+
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index 53d5eb85210..dd22ecdbe60 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -322,0 +323,12 @@ typedef enum __attribute__((__packed__)) {
+/*
+ * floatx80 is primarily used by x86 and m68k, and there are
+ * differences in the handling, largely related to the explicit
+ * Integer bit which floatx80 has and the other float formats do not.
+ * These flag values allow specification of the target's requirements
+ * and can be ORed together to set floatx80_behaviour.
+ */
+typedef enum __attribute__((__packed__)) {
+ /* In the default Infinity value, is the Integer bit 0 ? */
+ floatx80_default_inf_int_bit_is_zero = 1,
+} FloatX80Behaviour;
+
@@ -333,0 +346 @@ typedef struct float_status {
+ FloatX80Behaviour floatx80_behaviour;
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index f56ae886c53..b12ad2b42a9 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1863 +1863,2 @@ static floatx80
floatx80_round_pack_canonical(FloatParts128 *p,
- frac = floatx80_infinity_low;
+ frac = s->floatx80_behaviour &
floatx80_default_inf_int_bit_is_zero ?
+ 0 : (1ULL << 63);
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 41dfdf58045..df66e8ba22a 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -109,0 +110,6 @@ static void m68k_cpu_reset_hold(Object *obj,
ResetType type)
+ /*
+ * m68k-specific floatx80 behaviour:
+ * * default Infinity values have a zero Integer bit
+ */
+ set_floatx80_behaviour(floatx80_default_inf_int_bit_is_zero,
+ &env->fp_status);
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 403f7a9d69d..77a43f46597 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -242 +242,6 @@ floatx80 floatx80_default_inf(bool zSign, float_status
*status)
- return packFloatx80(zSign, floatx80_infinity_high,
floatx80_infinity_low);
+ /*
+ * Whether the Integer bit is set in the default Infinity is
+ * target dependent.
+ */
+ bool z = status->floatx80_behaviour &
floatx80_default_inf_int_bit_is_zero;
+ return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
---
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-21 14:41 ` Philippe Mathieu-Daudé
@ 2025-02-21 15:19 ` Peter Maydell
2025-02-21 16:21 ` Philippe Mathieu-Daudé
0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2025-02-21 15:19 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On Fri, 21 Feb 2025 at 14:41, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> On 17/2/25 13:50, Peter Maydell wrote:
>
> > (1) floatx80 behaviours
> >
> > Two QEMU targets implement floatx80: x86 and m68k. (PPC also has one
> > use in the xsrqpxp round-to-80-bit-precision operation, and the
> > Linux-user NWFPE emulation nominally supports it, but these are
> > minor.) x86 and m68k disagree about some of the corner cases of
> > floatx80 where the value has the explicit Integer bit wrongly set. At
> > the moment the fpu code defaults to "floatx80 behaves like x86", with
> > TARGET_M68K ifdefs to get the other option.
> >
> > The first six patches in this series remove those ifdefs, replacing
> > them with a floatx80_behaviour field in float_status which can have
> > various flags set to select the individual behaviours. The default is
> > "like x86", which allows us to set these only for m68k and not worry
> > about the minor "technically makes some use of floatx80" cases.
>
>
> > Peter Maydell (10):
> > fpu: Make targets specify floatx80 default Inf at runtime
> > target/m68k: Avoid using floatx80_infinity global const
> > target/i386: Avoid using floatx80_infinity global const
>
> Bothering again, we can add the floatx80_default_inf() refactor as the
> first patch:
I really think at this point this is just doing extra
work shuffling code changes between patches for no real benefit.
The patches aren't super huge and they've already been
reviewed. I'm OK with splitting out the "add the status
argument" part as you suggested previously, as that
makes the patches more reasonably split between "just
mechanical" and "interesting change" which is not a big
split to do and could be helpful for potential bisection
later, but churning the patchset beyond that doesn't
seem worthwhile to me.
-- PMM
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 00/10] fpu: Remove remaining target ifdefs and build only once
2025-02-21 15:19 ` Peter Maydell
@ 2025-02-21 16:21 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 43+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-02-21 16:21 UTC (permalink / raw)
To: Peter Maydell
Cc: qemu-devel, Alex Bennée, Richard Henderson, Paolo Bonzini,
Eduardo Habkost, Laurent Vivier
On 21/2/25 16:19, Peter Maydell wrote:
> On Fri, 21 Feb 2025 at 14:41, Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>>
>> On 17/2/25 13:50, Peter Maydell wrote:
>>
>>> (1) floatx80 behaviours
>>>
>>> Two QEMU targets implement floatx80: x86 and m68k. (PPC also has one
>>> use in the xsrqpxp round-to-80-bit-precision operation, and the
>>> Linux-user NWFPE emulation nominally supports it, but these are
>>> minor.) x86 and m68k disagree about some of the corner cases of
>>> floatx80 where the value has the explicit Integer bit wrongly set. At
>>> the moment the fpu code defaults to "floatx80 behaves like x86", with
>>> TARGET_M68K ifdefs to get the other option.
>>>
>>> The first six patches in this series remove those ifdefs, replacing
>>> them with a floatx80_behaviour field in float_status which can have
>>> various flags set to select the individual behaviours. The default is
>>> "like x86", which allows us to set these only for m68k and not worry
>>> about the minor "technically makes some use of floatx80" cases.
>>
>>
>>> Peter Maydell (10):
>>> fpu: Make targets specify floatx80 default Inf at runtime
>>> target/m68k: Avoid using floatx80_infinity global const
>>> target/i386: Avoid using floatx80_infinity global const
>>
>> Bothering again, we can add the floatx80_default_inf() refactor as the
>> first patch:
>
> I really think at this point this is just doing extra
> work shuffling code changes between patches for no real benefit.
> The patches aren't super huge and they've already been
> reviewed. I'm OK with splitting out the "add the status
> argument" part as you suggested previously, as that
> makes the patches more reasonably split between "just
> mechanical" and "interesting change" which is not a big
> split to do and could be helpful for potential bisection
> later, but churning the patchset beyond that doesn't
> seem worthwhile to me.
OK, fine then, series fully reviewed!
^ permalink raw reply [flat|nested] 43+ messages in thread