* [PULL 00/30] fpu patch queue
@ 2026-05-22 18:26 Richard Henderson
2026-05-22 18:26 ` [PULL 01/30] fpu: Return struct from parts{64,128}_scalbn Richard Henderson
` (30 more replies)
0 siblings, 31 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel
The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544:
Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400)
are available in the Git repository at:
https://gitlab.com/rth7680/qemu.git tags/pull-fpu-20260522
for you to fetch changes up to 512f5147c8722c2caf730d1b5a09dbf36b03da57:
fpu: Export floatN_minmax (2026-05-22 11:21:37 -0700)
----------------------------------------------------------------
fpu: Export partsN_{scalbn,muladd}
fpu: Export floatN_minmax
fpu: Simplifications to muladd, addsub
fpu: Introduce exp_scalbn
fpu: Introduce FloatExceptionFlags
fpu: Use float_status accessors everywhere
fpu: Compress float_status with bitfields
fpu: Fixes for E4M3 vs NaNs
target/alpha: Remove CONFIG_SOFTFLOAT_INLINE
target/alpha: Use FloatExceptionFlags
target/s390x: Move float{32,64}_s390_divide_to_integer
----------------------------------------------------------------
Richard Henderson (30):
fpu: Return struct from parts{64,128}_scalbn
fpu: Reorganize partsN(muladd)
fpu: Return struct from parts{64,128}_muladd
fpu: Hoist nan check in partsN_addsub
fpu: Simplify 0 +/- N case in parts_addsub
fpu: Use parts64_round_to_int in parts_s390_divide_to_integer
target/s390x: Move float{32,64}_s390_divide_to_integer
fpu: Introduce exp_scalbn
target/alpha: Remove CONFIG_SOFTFLOAT_INLINE
fpu: Introduce FloatExceptionFlags
target/alpha: Use FloatExceptionFlags
fpu: Introduce frac_msb_is_snan
fpu: Introduce FloatSNaNRule
fpu: Use {get,set}_float_rounding_mode everywhere
fpu: Use of {get,set}_floatx80_rounding_precision everywhere
fpu: Use get_floatx80_behaviour everywhere
fpu: Use get_float_2nan_prop_rule in partsN_pick_nan
fpu: Use get_float_3nan_prop_rule in partsN_pick_nan_muladd
fpu: Use get_float_infzeronan_rule in partsN_pick_nan_muladd
fpu: Use accessors for tininess_before_rounding
fpu: Use {get,set}_flush_to_zero everywhere
fpu: Use accessors for ftz_before_rounding
fpu: Use {get,set}_flush_inputs_to_zero everywhere
fpu: Use get_default_nan_mode everywhere
fpu: Use get_float_default_nan_pattern in partsN_default_nan
fpu: Add accessors for rebias_{underflow,overflow}
fpu: Reorg float_status
fpu: Introduce float_status.e4m3_nan_is_snan
fpu: Fix NaN encoding for E4M3 in parts64_uncanon
fpu: Export floatN_minmax
include/fpu/softfloat-helpers.h | 37 ++--
include/fpu/softfloat-parts.h | 12 ++
include/fpu/softfloat-types.h | 89 ++++++---
include/fpu/softfloat.h | 112 ++++++-----
target/i386/ops_sse.h | 24 +--
target/mips/fpu_helper.h | 3 +-
fpu/softfloat.c | 422 +++++++++++++---------------------------
target/alpha/fpu_helper.c | 8 +-
target/alpha/helper.c | 3 +-
target/alpha/translate.c | 18 +-
target/arm/tcg/helper-a64.c | 12 +-
target/arm/tcg/vfp_helper.c | 38 ++--
target/hexagon/fma_emu.c | 6 +-
target/hppa/fpu_helper.c | 2 +-
target/i386/tcg/fpu_helper.c | 65 ++++---
target/m68k/softfloat.c | 380 ++++++++++++++++++------------------
target/mips/msa.c | 4 +-
target/ppc/cpu.c | 4 +-
target/ppc/fpu_helper.c | 14 +-
target/riscv/vector_helper.c | 6 +-
target/s390x/tcg/fpu_helper.c | 139 ++++++++++++-
target/sh4/cpu.c | 2 +-
target/xtensa/cpu.c | 3 +-
tests/fp/fp-bench.c | 6 +-
tests/fp/fp-test.c | 6 +-
fpu/softfloat-parts.c.inc | 312 +++++++++++++++--------------
fpu/softfloat-specialize.c.inc | 117 ++++++-----
tests/fp/wrap.c.inc | 12 +-
28 files changed, 936 insertions(+), 920 deletions(-)
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PULL 01/30] fpu: Return struct from parts{64,128}_scalbn
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 02/30] fpu: Reorganize partsN(muladd) Richard Henderson
` (29 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
At the same time, export.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-parts.h | 3 +++
fpu/softfloat.c | 18 +++++++++---------
fpu/softfloat-parts.c.inc | 14 ++++++++------
3 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/include/fpu/softfloat-parts.h b/include/fpu/softfloat-parts.h
index 9504d0daa0..46618d217e 100644
--- a/include/fpu/softfloat-parts.h
+++ b/include/fpu/softfloat-parts.h
@@ -214,4 +214,7 @@ FloatParts128 parts128_round_to_int(const FloatParts128 *a,
FloatParts64 parts64_round_to_fmt(const FloatParts64 *p, float_status *s,
const FloatFmt *fmt);
+FloatParts64 parts64_scalbn(const FloatParts64 *a, int n, float_status *s);
+FloatParts128 parts128_scalbn(const FloatParts128 *a, int n, float_status *s);
+
#endif
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 90ebd83f69..7fc6df461e 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1910,7 +1910,7 @@ float16 float16_muladd_scalbn(float16 a, float16 b, float16 c,
/* Before rounding, scale. */
if (scale) {
- parts64_scalbn(pr, scale, status);
+ *pr = parts64_scalbn(pr, scale, status);
}
parts64_uncanon(pr, status, &float16_params, false);
/* After rounding, apply negate result, especially for -0.0. */
@@ -1937,7 +1937,7 @@ float32_muladd_scalbn(float32 a, float32 b, float32 c,
/* Before rounding, scale. */
if (scale) {
- parts64_scalbn(pr, scale, status);
+ *pr = parts64_scalbn(pr, scale, status);
}
parts64_uncanon(pr, status, &float32_params, false);
/* After rounding, apply negate result, especially for -0.0. */
@@ -1958,7 +1958,7 @@ float64_muladd_scalbn(float64 a, float64 b, float64 c,
/* Before rounding, scale. */
if (scale) {
- parts64_scalbn(pr, scale, status);
+ *pr = parts64_scalbn(pr, scale, status);
}
parts64_uncanon(pr, status, &float64_params, false);
/* After rounding, apply negate result, especially for -0.0. */
@@ -4312,7 +4312,7 @@ float16 float16_scalbn(float16 a, int n, float_status *status)
{
FloatParts64 p = float16_unpack_canonical(a, status);
- parts64_scalbn(&p, n, status);
+ p = parts64_scalbn(&p, n, status);
return float16_round_pack_canonical(&p, status);
}
@@ -4320,7 +4320,7 @@ float32 float32_scalbn(float32 a, int n, float_status *status)
{
FloatParts64 p = float32_unpack_canonical(a, status);
- parts64_scalbn(&p, n, status);
+ p = parts64_scalbn(&p, n, status);
return float32_round_pack_canonical(&p, status);
}
@@ -4328,7 +4328,7 @@ float64 float64_scalbn(float64 a, int n, float_status *status)
{
FloatParts64 p = float64_unpack_canonical(a, status);
- parts64_scalbn(&p, n, status);
+ p = parts64_scalbn(&p, n, status);
return float64_round_pack_canonical(&p, status);
}
@@ -4336,7 +4336,7 @@ bfloat16 bfloat16_scalbn(bfloat16 a, int n, float_status *status)
{
FloatParts64 p = bfloat16_unpack_canonical(a, status);
- parts64_scalbn(&p, n, status);
+ p = parts64_scalbn(&p, n, status);
return bfloat16_round_pack_canonical(&p, status);
}
@@ -4344,7 +4344,7 @@ float128 float128_scalbn(float128 a, int n, float_status *status)
{
FloatParts128 p = float128_unpack_canonical(a, status);
- parts128_scalbn(&p, n, status);
+ p = parts128_scalbn(&p, n, status);
return float128_round_pack_canonical(&p, status);
}
@@ -4355,7 +4355,7 @@ floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status)
if (!floatx80_unpack_canonical(&p, a, status)) {
return floatx80_default_nan(status);
}
- parts128_scalbn(&p, n, status);
+ p = parts128_scalbn(&p, n, status);
return floatx80_round_pack_canonical(&p, status);
}
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 2114797aca..3a9c2748cd 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -1633,22 +1633,24 @@ FloatRelation partsN(compare)(const FloatPartsN *a, const FloatPartsN *b,
/*
* Multiply A by 2 raised to the power N.
*/
-static void partsN(scalbn)(FloatPartsN *a, int n, float_status *s)
+FloatPartsN partsN(scalbn)(const FloatPartsN *a, int n, float_status *s)
{
switch (a->cls) {
case float_class_snan:
case float_class_qnan:
- *a = partsN(return_nan)(a, s);
- break;
+ return partsN(return_nan)(a, s);
case float_class_zero:
case float_class_inf:
- break;
+ return *a;
case float_class_denormal:
float_raise(float_flag_input_denormal_used, s);
/* fall through */
case float_class_normal:
- a->exp += MIN(MAX(n, -0x10000), 0x10000);
- break;
+ {
+ FloatPartsN r = *a;
+ r.exp += MIN(MAX(n, -0x10000), 0x10000);
+ return r;
+ }
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 02/30] fpu: Reorganize partsN(muladd)
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
2026-05-22 18:26 ` [PULL 01/30] fpu: Return struct from parts{64,128}_scalbn Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 03/30] fpu: Return struct from parts{64,128}_muladd Richard Henderson
` (28 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
Check the likely case of normal product and normal or
zero addend first; shift NaN and infinity detection down;
end with zero product + addend.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 156 +++++++++++++++++---------------------
1 file changed, 71 insertions(+), 85 deletions(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 3a9c2748cd..ca2d7a15c9 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -681,11 +681,47 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
FloatPartsN *c,
int flags, float_status *s)
{
- int ab_mask, abc_mask;
- FloatPartsW p_widen, c_widen;
+ int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
+ int c_mask = float_cmask(c->cls);
+ int abc_mask = ab_mask | c_mask;
+ bool c_sign = c->sign ^ !!(flags & float_muladd_negate_c);
+ bool p_sign = a->sign ^ b->sign ^ !!(flags & float_muladd_negate_product);
- ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
- abc_mask = float_cmask(c->cls) | ab_mask;
+ /*
+ * The "likely" case is A and B normal, so that the product is normal,
+ * and C normal or zero so that the result is normal.
+ */
+ int likely_mask = ab_mask | (c_mask & ~float_cmask_zero);
+ if (likely(cmask_is_only_normals(likely_mask))) {
+ record_denormals_used(abc_mask, s);
+
+ /* Perform the multiplication step. */
+ FloatPartsW p_widen = { .sign = p_sign, .exp = a->exp + b->exp + 1 };
+ fracN(mulw)(&p_widen, a, b);
+ if (!(p_widen.frac_hi & DECOMPOSED_IMPLICIT_BIT)) {
+ fracW(add)(&p_widen, &p_widen, &p_widen);
+ p_widen.exp -= 1;
+ }
+
+ /* Perform the addition step. */
+ if (!(c_mask & float_cmask_zero)) {
+ /* Zero-extend C to less significant bits. */
+ FloatPartsW c_widen = { .sign = c_sign, .exp = c->exp };
+ fracN(widen)(&c_widen, c);
+
+ if (p_sign == c_sign) {
+ partsW(add_normal)(&p_widen, &c_widen);
+ } else if (!partsW(sub_normal)(&p_widen, &c_widen)) {
+ goto return_sub_zero;
+ }
+ }
+
+ /* Narrow with sticky bit, for proper rounding later. */
+ fracN(truncjam)(a, &p_widen);
+ a->sign = p_widen.sign;
+ a->exp = p_widen.exp;
+ return a;
+ }
/*
* It is implementation-defined whether the cases of (0,inf,qnan)
@@ -698,97 +734,47 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
return a;
}
- if (flags & float_muladd_negate_c) {
- c->sign ^= 1;
+ if (unlikely(ab_mask == float_cmask_infzero)) {
+ /* Inf * Zero == NaN */
+ float_raise(float_flag_invalid | float_flag_invalid_imz, s);
+ goto d_nan;
}
- /* Compute the sign of the product into A. */
- a->sign ^= b->sign;
- if (flags & float_muladd_negate_product) {
- a->sign ^= 1;
- }
-
- if (unlikely(!cmask_is_only_normals(ab_mask))) {
- if (unlikely(ab_mask == float_cmask_infzero)) {
- float_raise(float_flag_invalid | float_flag_invalid_imz, s);
+ if (unlikely(ab_mask & float_cmask_inf)) {
+ if ((c_mask & float_cmask_inf) && p_sign != c_sign) {
+ /* Inf - Inf == NaN */
+ float_raise(float_flag_invalid | float_flag_invalid_isi, s);
goto d_nan;
}
-
- if (ab_mask & float_cmask_inf) {
- if (c->cls == float_class_inf && a->sign != c->sign) {
- float_raise(float_flag_invalid | float_flag_invalid_isi, s);
- goto d_nan;
- }
- goto return_inf;
- }
-
- g_assert(ab_mask & float_cmask_zero);
- if (is_anynorm(c->cls)) {
- *a = *c;
- goto finish_sign;
- }
- if (c->cls == float_class_zero) {
- if (flags & float_muladd_suppress_add_product_zero) {
- a->sign = c->sign;
- } else if (a->sign != c->sign) {
- goto return_sub_zero;
- }
- goto return_zero;
- }
- g_assert(c->cls == float_class_inf);
+ /* Inf + C == Inf */
+ record_denormals_used(abc_mask, s);
+ a->sign = p_sign;
+ a->cls = float_class_inf;
+ return a;
}
-
- if (unlikely(c->cls == float_class_inf)) {
- a->sign = c->sign;
- goto return_inf;
- }
-
- /* Perform the multiplication step. */
- p_widen.sign = a->sign;
- p_widen.exp = a->exp + b->exp + 1;
- fracN(mulw)(&p_widen, a, b);
- if (!(p_widen.frac_hi & DECOMPOSED_IMPLICIT_BIT)) {
- fracW(add)(&p_widen, &p_widen, &p_widen);
- p_widen.exp -= 1;
- }
-
- /* Perform the addition step. */
- if (c->cls != float_class_zero) {
- /* Zero-extend C to less significant bits. */
- fracN(widen)(&c_widen, c);
- c_widen.exp = c->exp;
-
- if (a->sign == c->sign) {
- partsW(add_normal)(&p_widen, &c_widen);
- } else if (!partsW(sub_normal)(&p_widen, &c_widen)) {
- goto return_sub_zero;
- }
- }
-
- /* Narrow with sticky bit, for proper rounding later. */
- fracN(truncjam)(a, &p_widen);
- a->sign = p_widen.sign;
- a->exp = p_widen.exp;
-
- finish_sign:
- /*
- * All result types except for "return the default NaN
- * because this is an Invalid Operation" go through here;
- * this matches the set of cases where we consumed a
- * denormal input.
- */
record_denormals_used(abc_mask, s);
- return a;
+
+ /* Only remaining cases are zero product or inf addend. */
+ assert((ab_mask & float_cmask_zero) | (c_mask & float_cmask_inf));
+
+ /*
+ * P + Inf == Inf, or
+ * 0 + C == C,
+ * except for 0 - 0, which needs special rounding,
+ * except for when we want to suppress this addition step.
+ */
+ if (!(c_mask & float_cmask_zero)
+ || p_sign == c_sign
+ || (flags & float_muladd_suppress_add_product_zero)) {
+ c->sign = c_sign;
+ return c;
+ }
return_sub_zero:
+ /* 0 - 0 == -0 for round_down, +0 otherwise. */
a->sign = s->float_rounding_mode == float_round_down;
- return_zero:
a->cls = float_class_zero;
- goto finish_sign;
-
- return_inf:
- a->cls = float_class_inf;
- goto finish_sign;
+ return a;
d_nan:
*a = partsN(default_nan)(s);
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 03/30] fpu: Return struct from parts{64,128}_muladd
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
2026-05-22 18:26 ` [PULL 01/30] fpu: Return struct from parts{64,128}_scalbn Richard Henderson
2026-05-22 18:26 ` [PULL 02/30] fpu: Reorganize partsN(muladd) Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 04/30] fpu: Hoist nan check in partsN_addsub Richard Henderson
` (27 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
At the same time, export.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-parts.h | 9 ++++
fpu/softfloat.c | 83 +++++++++++++++++------------------
fpu/softfloat-parts.c.inc | 38 ++++++++--------
3 files changed, 69 insertions(+), 61 deletions(-)
diff --git a/include/fpu/softfloat-parts.h b/include/fpu/softfloat-parts.h
index 46618d217e..7170cc7b6a 100644
--- a/include/fpu/softfloat-parts.h
+++ b/include/fpu/softfloat-parts.h
@@ -202,6 +202,15 @@ FloatParts64 parts64_mul(const FloatParts64 *a, const FloatParts64 *b,
FloatParts128 parts128_mul(const FloatParts128 *a, const FloatParts128 *b,
float_status *s);
+FloatParts64 parts64_muladd(const FloatParts64 *a,
+ const FloatParts64 *b,
+ const FloatParts64 *c,
+ int flags, float_status *s);
+FloatParts128 parts128_muladd(const FloatParts128 *a,
+ const FloatParts128 *b,
+ const FloatParts128 *c,
+ int flags, float_status *s);
+
FloatParts64 parts64_round_to_int(const FloatParts64 *a,
FloatRoundMode rmode,
int scale, float_status *s,
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 7fc6df461e..905ba6ecf8 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1906,18 +1906,18 @@ float16 float16_muladd_scalbn(float16 a, float16 b, float16 c,
FloatParts64 pa = float16_unpack_canonical(a, status);
FloatParts64 pb = float16_unpack_canonical(b, status);
FloatParts64 pc = float16_unpack_canonical(c, status);
- FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
+ FloatParts64 pr = parts64_muladd(&pa, &pb, &pc, flags, status);
/* Before rounding, scale. */
if (scale) {
- *pr = parts64_scalbn(pr, scale, status);
+ pr = parts64_scalbn(&pr, scale, status);
}
- parts64_uncanon(pr, status, &float16_params, false);
+ parts64_uncanon(&pr, status, &float16_params, false);
/* After rounding, apply negate result, especially for -0.0. */
- if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
- pr->sign ^= 1;
+ if ((flags & float_muladd_negate_result) && !is_nan(pr.cls)) {
+ pr.sign ^= 1;
}
- return pack_raw64(pr, &float16_params);
+ return pack_raw64(&pr, &float16_params);
}
float16 float16_muladd(float16 a, float16 b, float16 c,
@@ -1933,18 +1933,18 @@ float32_muladd_scalbn(float32 a, float32 b, float32 c,
FloatParts64 pa = float32_unpack_canonical(a, status);
FloatParts64 pb = float32_unpack_canonical(b, status);
FloatParts64 pc = float32_unpack_canonical(c, status);
- FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
+ FloatParts64 pr = parts64_muladd(&pa, &pb, &pc, flags, status);
/* Before rounding, scale. */
if (scale) {
- *pr = parts64_scalbn(pr, scale, status);
+ pr = parts64_scalbn(&pr, scale, status);
}
- parts64_uncanon(pr, status, &float32_params, false);
+ parts64_uncanon(&pr, status, &float32_params, false);
/* After rounding, apply negate result, especially for -0.0. */
- if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
- pr->sign ^= 1;
+ if ((flags & float_muladd_negate_result) && !is_nan(pr.cls)) {
+ pr.sign ^= 1;
}
- return pack_raw64(pr, &float32_params);
+ return pack_raw64(&pr, &float32_params);
}
float64 QEMU_SOFTFLOAT_ATTR
@@ -1954,18 +1954,18 @@ float64_muladd_scalbn(float64 a, float64 b, float64 c,
FloatParts64 pa = float64_unpack_canonical(a, status);
FloatParts64 pb = float64_unpack_canonical(b, status);
FloatParts64 pc = float64_unpack_canonical(c, status);
- FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
+ FloatParts64 pr = parts64_muladd(&pa, &pb, &pc, flags, status);
/* Before rounding, scale. */
if (scale) {
- *pr = parts64_scalbn(pr, scale, status);
+ pr = parts64_scalbn(&pr, scale, status);
}
- parts64_uncanon(pr, status, &float64_params, false);
+ parts64_uncanon(&pr, status, &float64_params, false);
/* After rounding, apply negate result, especially for -0.0. */
- if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
- pr->sign ^= 1;
+ if ((flags & float_muladd_negate_result) && !is_nan(pr.cls)) {
+ pr.sign ^= 1;
}
- return pack_raw64(pr, &float64_params);
+ return pack_raw64(&pr, &float64_params);
}
static bool force_soft_fma;
@@ -2115,14 +2115,14 @@ float64 float64r32_muladd(float64 a, float64 b, float64 c,
FloatParts64 pa = float64_unpack_canonical(a, status);
FloatParts64 pb = float64_unpack_canonical(b, status);
FloatParts64 pc = float64_unpack_canonical(c, status);
- FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
+ FloatParts64 pr = parts64_muladd(&pa, &pb, &pc, flags, status);
/* Round before applying negate result. */
- parts64_uncanon(pr, status, &float32_params, false);
- if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
- pr->sign ^= 1;
+ parts64_uncanon(&pr, status, &float32_params, false);
+ if ((flags & float_muladd_negate_result) && !is_nan(pr.cls)) {
+ pr.sign ^= 1;
}
- return float64r32_pack_raw(pr);
+ return float64r32_pack_raw(&pr);
}
bfloat16 bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c,
@@ -2131,14 +2131,14 @@ bfloat16 bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c,
FloatParts64 pa = bfloat16_unpack_canonical(a, status);
FloatParts64 pb = bfloat16_unpack_canonical(b, status);
FloatParts64 pc = bfloat16_unpack_canonical(c, status);
- FloatParts64 *pr = parts64_muladd(&pa, &pb, &pc, flags, status);
+ FloatParts64 pr = parts64_muladd(&pa, &pb, &pc, flags, status);
/* Round before applying negate result. */
- parts64_uncanon(pr, status, &bfloat16_params, false);
- if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
- pr->sign ^= 1;
+ parts64_uncanon(&pr, status, &bfloat16_params, false);
+ if ((flags & float_muladd_negate_result) && !is_nan(pr.cls)) {
+ pr.sign ^= 1;
}
- return pack_raw64(pr, &bfloat16_params);
+ return pack_raw64(&pr, &bfloat16_params);
}
float128 float128_muladd(float128 a, float128 b, float128 c,
@@ -2147,14 +2147,14 @@ float128 float128_muladd(float128 a, float128 b, float128 c,
FloatParts128 pa = float128_unpack_canonical(a, status);
FloatParts128 pb = float128_unpack_canonical(b, status);
FloatParts128 pc = float128_unpack_canonical(c, status);
- FloatParts128 *pr = parts128_muladd(&pa, &pb, &pc, flags, status);
+ FloatParts128 pr = parts128_muladd(&pa, &pb, &pc, flags, status);
/* Round before applying negate result. */
- parts128_uncanon(pr, status, &float128_params, false);
- if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) {
- pr->sign ^= 1;
+ parts128_uncanon(&pr, status, &float128_params, false);
+ if ((flags & float_muladd_negate_result) && !is_nan(pr.cls)) {
+ pr.sign ^= 1;
}
- return float128_pack_raw(pr);
+ return float128_pack_raw(&pr);
}
/*
@@ -5126,7 +5126,7 @@ float32 float32_exp2(float32 a, float_status *status)
rp = float64_unpack_canonical(float64_one, status);
for (int i = 0; i < 15; i++) {
tp = float64_unpack_canonical(float32_exp2_coefficients[i], status);
- rp = *parts64_muladd(&tp, &xnp, &rp, 0, status);
+ rp = parts64_muladd(&tp, &xnp, &rp, 0, status);
xnp = parts64_mul(&xnp, &xp, status);
}
@@ -5175,7 +5175,7 @@ static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
n->sign = a->sign ^ b->sign;
*cc = 0;
} else {
- FloatParts64 *q, q_buf, *r_precise, r_precise_buf;
+ FloatParts64 *q, q_buf, r_precise;
int float_exception_flags = 0;
bool is_q_smallish;
uint32_t r_flags;
@@ -5205,12 +5205,11 @@ static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
0, fmt->frac_size);
/* Compute precise remainder */
- r_precise_buf = *b;
- r_precise = parts64_muladd(&r_precise_buf, n, a,
+ r_precise = parts64_muladd(b, n, a,
float_muladd_negate_product, status);
/* Round remainder to the target format */
- *r = *r_precise;
+ *r = r_precise;
status->float_exception_flags = 0;
*r = parts64_round_to_fmt(r, status, fmt);
r_flags = status->float_exception_flags;
@@ -5234,17 +5233,17 @@ static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
* toward zero) or incremented.
*/
saved_r_sign = r->sign;
- saved_r_precise_sign = r_precise->sign;
+ saved_r_precise_sign = r_precise.sign;
r->sign = false;
- r_precise->sign = false;
- if (parts64_compare(r, r_precise, status, true) <
+ r_precise.sign = false;
+ if (parts64_compare(r, &r_precise, status, true) <
float_relation_equal) {
*dxc = 0x8;
} else {
*dxc = 0xc;
}
r->sign = saved_r_sign;
- r_precise->sign = saved_r_precise_sign;
+ r_precise.sign = saved_r_precise_sign;
}
}
}
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index ca2d7a15c9..437b333341 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -677,9 +677,8 @@ FloatPartsN partsN(mul)(const FloatPartsN *a, const FloatPartsN *b,
* Requires A and C extracted into a double-sized structure to provide the
* extra space for the widening multiply.
*/
-static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
- FloatPartsN *c,
- int flags, float_status *s)
+FloatPartsN partsN(muladd)(const FloatPartsN *a, const FloatPartsN *b,
+ const FloatPartsN *c, int flags, float_status *s)
{
int ab_mask = float_cmask(a->cls) | float_cmask(b->cls);
int c_mask = float_cmask(c->cls);
@@ -717,10 +716,13 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
}
/* Narrow with sticky bit, for proper rounding later. */
- fracN(truncjam)(a, &p_widen);
- a->sign = p_widen.sign;
- a->exp = p_widen.exp;
- return a;
+ FloatPartsN r = {
+ .sign = p_widen.sign,
+ .exp = p_widen.exp,
+ .cls = float_class_normal,
+ };
+ fracN(truncjam)(&r, &p_widen);
+ return r;
}
/*
@@ -730,8 +732,7 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
* off to the target-specific pick-a-NaN routine.
*/
if (unlikely(abc_mask & float_cmask_anynan)) {
- *a = partsN(pick_nan_muladd)(a, b, c, s, ab_mask, abc_mask);
- return a;
+ return partsN(pick_nan_muladd)(a, b, c, s, ab_mask, abc_mask);
}
if (unlikely(ab_mask == float_cmask_infzero)) {
@@ -748,9 +749,7 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
}
/* Inf + C == Inf */
record_denormals_used(abc_mask, s);
- a->sign = p_sign;
- a->cls = float_class_inf;
- return a;
+ return (FloatPartsN){ .sign = p_sign, .cls = float_class_inf };
}
record_denormals_used(abc_mask, s);
@@ -766,19 +765,20 @@ static FloatPartsN *partsN(muladd)(FloatPartsN *a, FloatPartsN *b,
if (!(c_mask & float_cmask_zero)
|| p_sign == c_sign
|| (flags & float_muladd_suppress_add_product_zero)) {
- c->sign = c_sign;
- return c;
+ FloatPartsN r = *c;
+ r.sign = c_sign;
+ return r;
}
return_sub_zero:
/* 0 - 0 == -0 for round_down, +0 otherwise. */
- a->sign = s->float_rounding_mode == float_round_down;
- a->cls = float_class_zero;
- return a;
+ return (FloatPartsN){
+ .sign = s->float_rounding_mode == float_round_down,
+ .cls = float_class_zero
+ };
d_nan:
- *a = partsN(default_nan)(s);
- return a;
+ return partsN(default_nan)(s);
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 04/30] fpu: Hoist nan check in partsN_addsub
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (2 preceding siblings ...)
2026-05-22 18:26 ` [PULL 03/30] fpu: Return struct from parts{64,128}_muladd Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 05/30] fpu: Simplify 0 +/- N case in parts_addsub Richard Henderson
` (26 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
The nan test had been down below because it was unlikely.
But if we have to have one anyway because of denormals,
we might as well take care of them right away.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 437b333341..3246702289 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -530,13 +530,15 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
{
int ab_mask = float_cmask(a_orig->cls) | float_cmask(b_orig->cls);
+ if (unlikely(ab_mask & float_cmask_anynan)) {
+ return partsN(pick_nan)(a_orig, b_orig, s);
+ }
+
/*
* For addition and subtraction, we will consume an
* input denormal unless the other input is a NaN.
*/
- if (!(ab_mask & float_cmask_anynan)) {
- record_denormals_used(ab_mask, s);
- }
+ record_denormals_used(ab_mask, s);
FloatPartsN a = *a_orig;
FloatPartsN b = *b_orig;
@@ -558,10 +560,6 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
return a;
}
- if (unlikely(ab_mask & float_cmask_anynan)) {
- goto p_nan;
- }
-
if (ab_mask & float_cmask_inf) {
if (a.cls != float_class_inf) {
/* N - Inf */
@@ -586,10 +584,6 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
return a;
}
- if (unlikely(ab_mask & float_cmask_anynan)) {
- goto p_nan;
- }
-
if (ab_mask & float_cmask_inf) {
a.cls = float_class_inf;
return a;
@@ -604,9 +598,6 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
g_assert(a.cls == float_class_zero);
g_assert(is_anynorm(b.cls));
return b;
-
- p_nan:
- return partsN(pick_nan)(a_orig, b_orig, s);
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 05/30] fpu: Simplify 0 +/- N case in parts_addsub
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (3 preceding siblings ...)
2026-05-22 18:26 ` [PULL 04/30] fpu: Hoist nan check in partsN_addsub Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 06/30] fpu: Use parts64_round_to_int in parts_s390_divide_to_integer Richard Henderson
` (25 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Consolidate the tests for zero and anynorm.
Add comments for a few cases.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 3246702289..45606f8402 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -556,6 +556,7 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
}
if (ab_mask == float_cmask_zero) {
+ /* 0 - 0 */
a.sign = s->float_rounding_mode == float_round_down;
return a;
}
@@ -581,23 +582,20 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
}
if (ab_mask == float_cmask_zero) {
+ /* 0 + 0 */
return a;
}
if (ab_mask & float_cmask_inf) {
+ /* N + Inf or Inf + N */
a.cls = float_class_inf;
return a;
}
}
- if (b.cls == float_class_zero) {
- g_assert(is_anynorm(a.cls));
- return a;
- }
-
- g_assert(a.cls == float_class_zero);
- g_assert(is_anynorm(b.cls));
- return b;
+ /* 0 +/- N or N +/- 0 */
+ assert((ab_mask & float_cmask_zero) && (ab_mask & float_cmask_anynorm));
+ return b.cls == float_class_zero ? a : b;
}
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 06/30] fpu: Use parts64_round_to_int in parts_s390_divide_to_integer
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (4 preceding siblings ...)
2026-05-22 18:26 ` [PULL 05/30] fpu: Simplify 0 +/- N case in parts_addsub Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 07/30] target/s390x: Move float{32,64}_s390_divide_to_integer Richard Henderson
` (24 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
We will not expose parts_round_to_int_normal.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 905ba6ecf8..08ea56a71d 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5197,12 +5197,11 @@ static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
* Rounding of partial quotient may be inexact. This is the whole point
* of distinguishing partial quotients, so ignore the exception.
*/
- *n = *q;
- parts64_round_to_int_normal(n,
- is_q_smallish
- ? final_quotient_rounding_mode
- : float_round_to_zero,
- 0, fmt->frac_size);
+ *n = parts64_round_to_int(q,
+ is_q_smallish
+ ? final_quotient_rounding_mode
+ : float_round_to_zero,
+ 0, status, fmt);
/* Compute precise remainder */
r_precise = parts64_muladd(b, n, a,
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 07/30] target/s390x: Move float{32,64}_s390_divide_to_integer
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (5 preceding siblings ...)
2026-05-22 18:26 ` [PULL 06/30] fpu: Use parts64_round_to_int in parts_s390_divide_to_integer Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 08/30] fpu: Introduce exp_scalbn Richard Henderson
` (23 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Ilya Leoshkevich
Now that we've exposed enough infrastructure, this can be
implemented in the backend that needs it.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat.h | 11 ---
fpu/softfloat.c | 137 ----------------------------------
target/s390x/tcg/fpu_helper.c | 135 +++++++++++++++++++++++++++++++++
3 files changed, 135 insertions(+), 148 deletions(-)
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 8389a07b04..1580d956d5 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -1386,15 +1386,4 @@ static inline bool float128_unordered_quiet(float128 a, float128 b,
*----------------------------------------------------------------------------*/
float128 float128_default_nan(float_status *status);
-#define DECLARE_S390_DIVIDE_TO_INTEGER(floatN) \
-void floatN ## _s390_divide_to_integer(floatN a, floatN b, \
- int final_quotient_rounding_mode, \
- bool mask_underflow, bool mask_inexact, \
- floatN *r, floatN *n, \
- uint32_t *cc, int *dxc, \
- float_status *status)
-DECLARE_S390_DIVIDE_TO_INTEGER(float32);
-DECLARE_S390_DIVIDE_TO_INTEGER(float64);
-
-
#endif /* SOFTFLOAT_H */
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 08ea56a71d..a762f4b43a 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5151,143 +5151,6 @@ floatx80 floatx80_round(floatx80 a, float_status *status)
return floatx80_round_pack_canonical(&p, status);
}
-static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
- int final_quotient_rounding_mode,
- bool mask_underflow, bool mask_inexact,
- const FloatFmt *fmt,
- FloatParts64 *r, FloatParts64 *n,
- uint32_t *cc, int *dxc,
- float_status *status)
-{
- /* POp table "Results: DIVIDE TO INTEGER (Part 1 of 2)" */
- if ((float_cmask(a->cls) | float_cmask(b->cls)) & float_cmask_anynan) {
- *r = parts64_pick_nan(a, b, status);
- *n = *r;
- *cc = 1;
- } else if (a->cls == float_class_inf || b->cls == float_class_zero) {
- *r = parts64_default_nan(status);
- *n = *r;
- *cc = 1;
- status->float_exception_flags |= float_flag_invalid;
- } else if (b->cls == float_class_inf) {
- *r = *a;
- n->cls = float_class_zero;
- n->sign = a->sign ^ b->sign;
- *cc = 0;
- } else {
- FloatParts64 *q, q_buf, r_precise;
- int float_exception_flags = 0;
- bool is_q_smallish;
- uint32_t r_flags;
-
- /* Compute precise quotient */
- q_buf = parts64_div(a, b, status);
- q = &q_buf;
-
- /*
- * Check whether two closest integers can be precisely represented,
- * i.e., all their bits fit into the fractional part.
- */
- is_q_smallish = q->exp < (fmt->frac_size + 1);
-
- /*
- * Final quotient is rounded using final-quotient-rounding method, and
- * partial quotient is rounded toward zero.
- *
- * Rounding of partial quotient may be inexact. This is the whole point
- * of distinguishing partial quotients, so ignore the exception.
- */
- *n = parts64_round_to_int(q,
- is_q_smallish
- ? final_quotient_rounding_mode
- : float_round_to_zero,
- 0, status, fmt);
-
- /* Compute precise remainder */
- r_precise = parts64_muladd(b, n, a,
- float_muladd_negate_product, status);
-
- /* Round remainder to the target format */
- *r = r_precise;
- status->float_exception_flags = 0;
- *r = parts64_round_to_fmt(r, status, fmt);
- r_flags = status->float_exception_flags;
-
- /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
- if (is_q_smallish) {
- if (r->cls != float_class_zero) {
- if (r->exp < 2 - (1 << (fmt->exp_size - 1))) {
- if (mask_underflow) {
- float_exception_flags |= float_flag_underflow;
- *dxc = 0x10;
- r->exp += fmt->exp_re_bias;
- }
- } else if (r_flags & float_flag_inexact) {
- float_exception_flags |= float_flag_inexact;
- if (mask_inexact) {
- bool saved_r_sign, saved_r_precise_sign;
-
- /*
- * Check whether remainder was truncated (rounded
- * toward zero) or incremented.
- */
- saved_r_sign = r->sign;
- saved_r_precise_sign = r_precise.sign;
- r->sign = false;
- r_precise.sign = false;
- if (parts64_compare(r, &r_precise, status, true) <
- float_relation_equal) {
- *dxc = 0x8;
- } else {
- *dxc = 0xc;
- }
- r->sign = saved_r_sign;
- r_precise.sign = saved_r_precise_sign;
- }
- }
- }
- *cc = 0;
- } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) {
- n->exp -= fmt->exp_re_bias;
- *cc = r->cls == float_class_zero ? 1 : 3;
- } else {
- *cc = r->cls == float_class_zero ? 0 : 2;
- }
-
- /* Adjust signs of zero results */
- if (r->cls == float_class_zero) {
- r->sign = a->sign;
- }
- if (n->cls == float_class_zero) {
- n->sign = a->sign ^ b->sign;
- }
-
- status->float_exception_flags = float_exception_flags;
- }
-}
-
-#define DEFINE_S390_DIVIDE_TO_INTEGER(floatN) \
-void floatN ## _s390_divide_to_integer(floatN a, floatN b, \
- int final_quotient_rounding_mode, \
- bool mask_underflow, bool mask_inexact, \
- floatN *r, floatN *n, \
- uint32_t *cc, int *dxc, \
- float_status *status) \
-{ \
- FloatParts64 pa = floatN ## _unpack_canonical(a, status); \
- FloatParts64 pb = floatN ## _unpack_canonical(b, status); \
- FloatParts64 pr, pn; \
- parts_s390_divide_to_integer(&pa, &pb, final_quotient_rounding_mode, \
- mask_underflow, mask_inexact, \
- &floatN ## _params, \
- &pr, &pn, cc, dxc, status); \
- *r = floatN ## _round_pack_canonical(&pr, status); \
- *n = floatN ## _round_pack_canonical(&pn, status); \
-}
-
-DEFINE_S390_DIVIDE_TO_INTEGER(float32)
-DEFINE_S390_DIVIDE_TO_INTEGER(float64)
-
static void __attribute__((constructor)) softfloat_init(void)
{
union_float64 ua, ub, uc, ur;
diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c
index 122994960a..33e0f6100d 100644
--- a/target/s390x/tcg/fpu_helper.c
+++ b/target/s390x/tcg/fpu_helper.c
@@ -24,6 +24,7 @@
#include "tcg_s390x.h"
#include "exec/helper-proto.h"
#include "fpu/softfloat.h"
+#include "fpu/softfloat-parts.h"
/* #define DEBUG_HELPER */
#ifdef DEBUG_HELPER
@@ -315,6 +316,140 @@ Int128 HELPER(dxb)(CPUS390XState *env, Int128 a, Int128 b)
return RET128(ret);
}
+static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
+ int final_quotient_rounding_mode,
+ bool mask_underflow, bool mask_inexact,
+ const FloatFmt *fmt,
+ FloatParts64 *r, FloatParts64 *n,
+ uint32_t *cc, int *dxc,
+ float_status *status)
+{
+ /* POp table "Results: DIVIDE TO INTEGER (Part 1 of 2)" */
+ if ((float_cmask(a->cls) | float_cmask(b->cls)) & float_cmask_anynan) {
+ *r = parts64_pick_nan(a, b, status);
+ *n = *r;
+ *cc = 1;
+ } else if (a->cls == float_class_inf || b->cls == float_class_zero) {
+ *r = parts64_default_nan(status);
+ *n = *r;
+ *cc = 1;
+ status->float_exception_flags |= float_flag_invalid;
+ } else if (b->cls == float_class_inf) {
+ *r = *a;
+ n->cls = float_class_zero;
+ n->sign = a->sign ^ b->sign;
+ *cc = 0;
+ } else {
+ FloatParts64 *q, q_buf, r_precise;
+ int float_exception_flags = 0;
+ bool is_q_smallish;
+ uint32_t r_flags;
+
+ /* Compute precise quotient */
+ q_buf = parts64_div(a, b, status);
+ q = &q_buf;
+
+ /*
+ * Check whether two closest integers can be precisely represented,
+ * i.e., all their bits fit into the fractional part.
+ */
+ is_q_smallish = q->exp < (fmt->frac_size + 1);
+
+ /*
+ * Final quotient is rounded using final-quotient-rounding method, and
+ * partial quotient is rounded toward zero.
+ *
+ * Rounding of partial quotient may be inexact. This is the whole point
+ * of distinguishing partial quotients, so ignore the exception.
+ */
+ *n = parts64_round_to_int(q,
+ is_q_smallish
+ ? final_quotient_rounding_mode
+ : float_round_to_zero,
+ 0, status, fmt);
+
+ /* Compute precise remainder */
+ r_precise = parts64_muladd(b, n, a,
+ float_muladd_negate_product, status);
+
+ /* Round remainder to the target format */
+ *r = r_precise;
+ status->float_exception_flags = 0;
+ *r = parts64_round_to_fmt(r, status, fmt);
+ r_flags = status->float_exception_flags;
+
+ /* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
+ if (is_q_smallish) {
+ if (r->cls != float_class_zero) {
+ if (r->exp < 2 - (1 << (fmt->exp_size - 1))) {
+ if (mask_underflow) {
+ float_exception_flags |= float_flag_underflow;
+ *dxc = 0x10;
+ r->exp += fmt->exp_re_bias;
+ }
+ } else if (r_flags & float_flag_inexact) {
+ float_exception_flags |= float_flag_inexact;
+ if (mask_inexact) {
+ bool saved_r_sign, saved_r_precise_sign;
+
+ /*
+ * Check whether remainder was truncated (rounded
+ * toward zero) or incremented.
+ */
+ saved_r_sign = r->sign;
+ saved_r_precise_sign = r_precise.sign;
+ r->sign = false;
+ r_precise.sign = false;
+ if (parts64_compare(r, &r_precise, status, true) <
+ float_relation_equal) {
+ *dxc = 0x8;
+ } else {
+ *dxc = 0xc;
+ }
+ r->sign = saved_r_sign;
+ r_precise.sign = saved_r_precise_sign;
+ }
+ }
+ }
+ *cc = 0;
+ } else if (n->exp > (1 << (fmt->exp_size - 1)) - 1) {
+ n->exp -= fmt->exp_re_bias;
+ *cc = r->cls == float_class_zero ? 1 : 3;
+ } else {
+ *cc = r->cls == float_class_zero ? 0 : 2;
+ }
+
+ /* Adjust signs of zero results */
+ if (r->cls == float_class_zero) {
+ r->sign = a->sign;
+ }
+ if (n->cls == float_class_zero) {
+ n->sign = a->sign ^ b->sign;
+ }
+
+ status->float_exception_flags = float_exception_flags;
+ }
+}
+
+#define DEFINE_S390_DIVIDE_TO_INTEGER(floatN) \
+static void floatN ## _s390_divide_to_integer(floatN a, floatN b, \
+ int final_quotient_rounding_mode, bool mask_underflow, bool mask_inexact, \
+ floatN *r, floatN *n, uint32_t *cc, int *dxc, float_status *status) \
+{ \
+ FloatParts64 pa = floatN ## _unpack_canonical(a, status); \
+ FloatParts64 pb = floatN ## _unpack_canonical(b, status); \
+ FloatParts64 pr, pn; \
+ parts_s390_divide_to_integer(&pa, &pb, final_quotient_rounding_mode, \
+ mask_underflow, mask_inexact, \
+ &floatN ## _params, \
+ &pr, &pn, cc, dxc, status); \
+ *r = floatN ## _round_pack_canonical(&pr, status); \
+ *n = floatN ## _round_pack_canonical(&pn, status); \
+}
+
+DEFINE_S390_DIVIDE_TO_INTEGER(float32)
+DEFINE_S390_DIVIDE_TO_INTEGER(float64)
+
void HELPER(dib)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,
uint32_t m4, uint32_t bits)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 08/30] fpu: Introduce exp_scalbn
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (6 preceding siblings ...)
2026-05-22 18:26 ` [PULL 07/30] target/s390x: Move float{32,64}_s390_divide_to_integer Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 09/30] target/alpha: Remove CONFIG_SOFTFLOAT_INLINE Richard Henderson
` (22 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Avoid exponent overflow as well as checking that we don't lose information with
opposing scaling. Use it in partsN(scalbn) and partsN(round_to_int_normal).
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat.c | 29 +++++++++++++++++++++++++++++
fpu/softfloat-parts.c.inc | 5 ++---
2 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index a762f4b43a..df94f299e1 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -461,6 +461,15 @@ typedef struct {
uint64_t frac_lo;
} FloatParts256;
+/*
+ * Minimum and maximum exponent for scalbn.
+ * These are chosen to be much larger than the true exponent for any input format,
+ * but also not at the bounds of INT32_{MIN,MAX} so that we can perform other
+ * arithmetic on the exponent without overflowing, particularly during uncanon.
+ */
+#define SCALBN_EXP_MAX 0x0fffffff
+#define SCALBN_EXP_MIN (-SCALBN_EXP_MAX)
+
/* These apply to the most significant word of each FloatPartsN. */
#define DECOMPOSED_BINARY_POINT 63
#define DECOMPOSED_IMPLICIT_BIT (1ull << DECOMPOSED_BINARY_POINT)
@@ -601,6 +610,26 @@ static float128 QEMU_FLATTEN float128_pack_raw(const FloatParts128 *p)
*----------------------------------------------------------------------------*/
#include "softfloat-specialize.c.inc"
+static int32_t exp_scalbn(int32_t exp, int32_t scale)
+{
+ /*
+ * Catch chains of scaling which lose information.
+ * In particular, if the exponent has been saturated,
+ * do not allow it to become unsaturated.
+ */
+ if (exp >= SCALBN_EXP_MAX) {
+ assert(scale >= 0);
+ } else if (exp <= SCALBN_EXP_MIN) {
+ assert(scale <= 0);
+ }
+ if (sadd32_overflow(exp, scale, &exp)) {
+ exp = scale < 0 ? SCALBN_EXP_MIN : SCALBN_EXP_MAX;
+ } else {
+ exp = MIN(MAX(exp, SCALBN_EXP_MIN), SCALBN_EXP_MAX);
+ }
+ return exp;
+}
+
/*
* Helper functions for softfloat-parts.c.inc, per-size operations.
*/
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 45606f8402..4715187017 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -1098,8 +1098,7 @@ static bool partsN(round_to_int_normal)(FloatPartsN *a, FloatRoundMode rmode,
uint64_t frac_lsb, frac_lsbm1, rnd_even_mask, rnd_mask, inc;
int shift_adj;
- scale = MIN(MAX(scale, -0x10000), 0x10000);
- a->exp += scale;
+ a->exp = exp_scalbn(a->exp, scale);
if (a->exp < 0) {
bool one;
@@ -1623,7 +1622,7 @@ FloatPartsN partsN(scalbn)(const FloatPartsN *a, int n, float_status *s)
case float_class_normal:
{
FloatPartsN r = *a;
- r.exp += MIN(MAX(n, -0x10000), 0x10000);
+ r.exp = exp_scalbn(r.exp, n);
return r;
}
default:
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 09/30] target/alpha: Remove CONFIG_SOFTFLOAT_INLINE
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (7 preceding siblings ...)
2026-05-22 18:26 ` [PULL 08/30] fpu: Introduce exp_scalbn Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 10/30] fpu: Introduce FloatExceptionFlags Richard Henderson
` (21 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Don't peek into float_status internals.
Fix the helper calls that were missing an argument.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/alpha/translate.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index d2d1467a81..c66e3f9c14 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -34,7 +34,6 @@
#undef HELPER_H
#undef ALPHA_DEBUG_DISAS
-#define CONFIG_SOFTFLOAT_INLINE
#ifdef ALPHA_DEBUG_DISAS
# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
@@ -578,15 +577,7 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11)
break;
}
-#if defined(CONFIG_SOFTFLOAT_INLINE)
- /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
- With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
- sets the one field. */
- tcg_gen_st8_i32(tmp, tcg_env,
- offsetof(CPUAlphaState, fp_status.float_rounding_mode));
-#else
- gen_helper_setroundmode(tmp);
-#endif
+ gen_helper_setroundmode(tcg_env, tmp);
}
static void gen_qual_flushzero(DisasContext *ctx, int fn11)
@@ -609,12 +600,7 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
tcg_gen_movi_i32(tmp, 1);
}
-#if defined(CONFIG_SOFTFLOAT_INLINE)
- tcg_gen_st8_i32(tmp, tcg_env,
- offsetof(CPUAlphaState, fp_status.flush_to_zero));
-#else
- gen_helper_setflushzero(tmp);
-#endif
+ gen_helper_setflushzero(tcg_env, tmp);
}
static TCGv_i64 gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 10/30] fpu: Introduce FloatExceptionFlags
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (8 preceding siblings ...)
2026-05-22 18:26 ` [PULL 09/30] target/alpha: Remove CONFIG_SOFTFLOAT_INLINE Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 11/30] target/alpha: Use FloatExceptionFlags Richard Henderson
` (20 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
We have, in the past, used any of uint8_t, uint16_t or int
to hold the set of exception flags. Use a typedef instead.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 6 ++++--
include/fpu/softfloat-types.h | 4 +++-
include/fpu/softfloat.h | 2 +-
fpu/softfloat.c | 2 +-
fpu/softfloat-parts.c.inc | 7 ++++---
5 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 90862f5cd2..745a49f07a 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -64,7 +64,8 @@ static inline void set_float_rounding_mode(FloatRoundMode val,
status->float_rounding_mode = val;
}
-static inline void set_float_exception_flags(int val, float_status *status)
+static inline void
+set_float_exception_flags(FloatExceptionFlags val, float_status *status)
{
status->float_exception_flags = val;
}
@@ -146,7 +147,8 @@ static inline FloatRoundMode get_float_rounding_mode(const float_status *status)
return status->float_rounding_mode;
}
-static inline int get_float_exception_flags(const float_status *status)
+static inline FloatExceptionFlags
+get_float_exception_flags(const float_status *status)
{
return status->float_exception_flags;
}
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index ead146c22d..5048faa76f 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -181,6 +181,8 @@ enum {
float_flag_input_denormal_used = 0x4000,
};
+typedef uint16_t FloatExceptionFlags;
+
/*
* Rounding precision for floatx80.
*/
@@ -385,7 +387,7 @@ typedef enum __attribute__((__packed__)) {
*/
typedef struct float_status {
- uint16_t float_exception_flags;
+ FloatExceptionFlags float_exception_flags;
FloatRoundMode float_rounding_mode;
FloatX80RoundPrec floatx80_rounding_precision;
FloatX80Behaviour floatx80_behaviour;
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 1580d956d5..4ae4ddc799 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -101,7 +101,7 @@ typedef enum {
| Routine to raise any or all of the software IEC/IEEE floating-point
| exception flags.
*----------------------------------------------------------------------------*/
-static inline void float_raise(uint16_t flags, float_status *status)
+static inline void float_raise(FloatExceptionFlags flags, float_status *status)
{
status->float_exception_flags |= flags;
}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index df94f299e1..391d8f3169 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2976,7 +2976,7 @@ static int64_t float128_to_int64_scalbn(float128 a, FloatRoundMode rmode,
static Int128 float128_to_int128_scalbn(float128 a, FloatRoundMode rmode,
int scale, float_status *s)
{
- int flags = 0;
+ FloatExceptionFlags flags = 0;
Int128 r;
FloatParts128 p = float128_unpack_canonical(a, s);
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 4715187017..bc348f75a3 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -297,7 +297,8 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
const uint64_t roundeven_mask = round_mask | frac_lsb;
uint64_t inc;
bool overflow_norm = saturate;
- int exp, flags = 0;
+ int exp;
+ FloatExceptionFlags flags = 0;
switch (s->float_rounding_mode) {
case float_round_nearest_even_max:
@@ -1256,7 +1257,7 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
int scale, int64_t min, int64_t max,
float_status *s)
{
- int flags = 0;
+ FloatExceptionFlags flags = 0;
uint64_t r;
switch (p->cls) {
@@ -1324,7 +1325,7 @@ static int64_t partsN(float_to_sint)(FloatPartsN *p, FloatRoundMode rmode,
static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
int scale, uint64_t max, float_status *s)
{
- int flags = 0;
+ FloatExceptionFlags flags = 0;
uint64_t r;
switch (p->cls) {
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 11/30] target/alpha: Use FloatExceptionFlags
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (9 preceding siblings ...)
2026-05-22 18:26 ` [PULL 10/30] fpu: Introduce FloatExceptionFlags Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 12/30] fpu: Introduce frac_msb_is_snan Richard Henderson
` (19 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Fixes a bug in which we were still using uint8_t.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/alpha/fpu_helper.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c
index 30f3c7fd18..9af77777da 100644
--- a/target/alpha/fpu_helper.c
+++ b/target/alpha/fpu_helper.c
@@ -40,7 +40,7 @@ void helper_setflushzero(CPUAlphaState *env, uint32_t val)
static uint32_t soft_to_fpcr_exc(CPUAlphaState *env)
{
- uint8_t exc = get_float_exception_flags(&FP_STATUS);
+ FloatExceptionFlags exc = get_float_exception_flags(&FP_STATUS);
uint32_t ret = 0;
if (unlikely(exc)) {
@@ -455,7 +455,7 @@ static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
float64 fa;
int64_t ret;
uint32_t exc = 0;
- int flags;
+ FloatExceptionFlags flags;
fa = t_to_float64(a);
ret = float64_to_int64_modulo(fa, roundmode, &FP_STATUS);
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 12/30] fpu: Introduce frac_msb_is_snan
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (10 preceding siblings ...)
2026-05-22 18:26 ` [PULL 11/30] target/alpha: Use FloatExceptionFlags Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 13/30] fpu: Introduce FloatSNaNRule Richard Henderson
` (18 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Unify handling of the two snan parameters, letting the
caller simply extract the msb.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-specialize.c.inc | 45 ++++++++++------------------------
1 file changed, 13 insertions(+), 32 deletions(-)
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 485f082cf8..e2e3ec0e81 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -104,16 +104,21 @@ static inline bool snan_bit_is_one(float_status *status)
| if the fraction represents a signalling NaN; otherwise false.
*----------------------------------------------------------------------------*/
-static bool parts_is_snan_frac(uint64_t frac, float_status *status)
+static bool frac_msb_is_snan(bool msb, float_status *status)
{
if (no_signaling_nans(status)) {
return false;
} else {
- bool msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
return msb == snan_bit_is_one(status);
}
}
+static bool parts_is_snan_frac(uint64_t frac, float_status *status)
+{
+ bool msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
+ return frac_msb_is_snan(msb, status);
+}
+
/*----------------------------------------------------------------------------
| The pattern for a default generated deconstructed floating-point NaN.
*----------------------------------------------------------------------------*/
@@ -238,11 +243,7 @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
static bool float16_nan_is_snan(float16 a, float_status *status)
{
- if (no_signaling_nans(status)) {
- return false;
- }
- bool frac_msb_is_one = (a >> 9) & 1;
- return frac_msb_is_one == snan_bit_is_one(status);
+ return frac_msb_is_snan((a >> 9) & 1, status);
}
/*----------------------------------------------------------------------------
@@ -271,11 +272,7 @@ bool float16_is_signaling_nan(float16 a_, float_status *status)
static bool bfloat16_nan_is_snan(bfloat16 a, float_status *status)
{
- if (no_signaling_nans(status)) {
- return false;
- }
- bool frac_msb_is_one = (a >> 6) & 1;
- return frac_msb_is_one == snan_bit_is_one(status);
+ return frac_msb_is_snan((a >> 6) & 1, status);
}
/*----------------------------------------------------------------------------
@@ -302,11 +299,7 @@ bool bfloat16_is_signaling_nan(bfloat16 a_, float_status *status)
static bool float32_nan_is_snan(float32 a, float_status *status)
{
- if (no_signaling_nans(status)) {
- return false;
- }
- bool frac_msb_is_one = (a >> 22) & 1;
- return frac_msb_is_one == snan_bit_is_one(status);
+ return frac_msb_is_snan((a >> 22) & 1, status);
}
/*----------------------------------------------------------------------------
@@ -335,11 +328,7 @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
static bool float64_nan_is_snan(float64 a, float_status *status)
{
- if (no_signaling_nans(status)) {
- return false;
- }
- bool frac_msb_is_one = (a >> 51) & 1;
- return frac_msb_is_one == snan_bit_is_one(status);
+ return frac_msb_is_snan((a >> 51) & 1, status);
}
/*----------------------------------------------------------------------------
@@ -370,11 +359,7 @@ bool float64_is_signaling_nan(float64 a_, float_status *status)
static bool floatx80_nan_is_snan(floatx80 a, float_status *status)
{
- if (no_signaling_nans(status)) {
- return false;
- }
- bool frac_msb_is_one = (a.low >> 62) & 1;
- return frac_msb_is_one == snan_bit_is_one(status);
+ return frac_msb_is_snan((a.low >> 62) & 1, status);
}
/*----------------------------------------------------------------------------
@@ -416,11 +401,7 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
static bool float128_nan_is_snan(float128 a, float_status *status)
{
- if (no_signaling_nans(status)) {
- return false;
- }
- bool frac_msb_is_one = (a.high >> 47) & 1;
- return frac_msb_is_one == snan_bit_is_one(status);
+ return frac_msb_is_snan((a.high >> 47) & 1, status);
}
/*----------------------------------------------------------------------------
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 13/30] fpu: Introduce FloatSNaNRule
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (11 preceding siblings ...)
2026-05-22 18:26 ` [PULL 12/30] fpu: Introduce frac_msb_is_snan Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 14/30] fpu: Use {get,set}_float_rounding_mode everywhere Richard Henderson
` (17 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Merge snan_bit_is_one and no_signaling_nans into one control.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 14 +++++-----
include/fpu/softfloat-types.h | 25 ++++++++++++-----
target/mips/fpu_helper.h | 3 ++-
target/hppa/fpu_helper.c | 2 +-
target/mips/msa.c | 4 +--
target/sh4/cpu.c | 2 +-
target/xtensa/cpu.c | 3 ++-
fpu/softfloat-specialize.c.inc | 48 +++++++++++++--------------------
8 files changed, 51 insertions(+), 50 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 745a49f07a..95edd22842 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -127,14 +127,9 @@ static inline void set_default_nan_mode(bool val, float_status *status)
status->default_nan_mode = val;
}
-static inline void set_snan_bit_is_one(bool val, float_status *status)
+static inline void set_snan_rule(FloatSNaNRule val, float_status *status)
{
- status->snan_bit_is_one = val;
-}
-
-static inline void set_no_signaling_nans(bool val, float_status *status)
-{
- status->no_signaling_nans = val;
+ status->float_snan_rule = val;
}
static inline bool get_float_detect_tininess(const float_status *status)
@@ -203,6 +198,11 @@ static inline bool get_default_nan_mode(const float_status *status)
return status->default_nan_mode;
}
+static inline FloatSNaNRule get_snan_rule(float_status *status)
+{
+ return status->float_snan_rule;
+}
+
static inline FloatFTZDetection get_float_ftz_detection(const float_status *status)
{
return status->ftz_detection;
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index 5048faa76f..cf7093fa86 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -192,6 +192,23 @@ typedef enum __attribute__((__packed__)) {
floatx80_precision_s,
} FloatX80RoundPrec;
+/*
+ * Define how the architecture discriminates signaling NaNs.
+ * This done with the most significant bit of the fraction.
+ *
+ * In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
+ * the msb must be 0. But setting the msb to 1 got baked into HPPA, SH4,
+ * and pre-2008 MIPS.
+ *
+ * Further, some architectures (or modes of architectures) do not detect
+ * signaling NaNs at all.
+ */
+typedef enum __attribute__((__packed__)) {
+ float_snan_bit_is_zero,
+ float_snan_bit_is_one,
+ float_snan_never,
+} FloatSNaNRule;
+
/*
* 2-input NaN propagation rule. Individual architectures have
* different rules for which input NaN is propagated to the output
@@ -394,6 +411,7 @@ typedef struct float_status {
Float2NaNPropRule float_2nan_prop_rule;
Float3NaNPropRule float_3nan_prop_rule;
FloatInfZeroNaNRule float_infzeronan_rule;
+ FloatSNaNRule float_snan_rule;
bool tininess_before_rounding;
/* should denormalised results go to zero and set output_denormal_flushed? */
bool flush_to_zero;
@@ -412,13 +430,6 @@ typedef struct float_status {
* create a default NaN.
*/
uint8_t default_nan_pattern;
- /*
- * The flags below are not used on all specializations and may
- * constant fold away (see snan_bit_is_one()/no_signalling_nans() in
- * softfloat-specialize.inc.c)
- */
- bool snan_bit_is_one;
- bool no_signaling_nans;
/* should overflowed results subtract re_bias to its exponent? */
bool rebias_overflow;
/* should underflowed results add re_bias to its exponent? */
diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h
index 08fb409390..cf667c6637 100644
--- a/target/mips/fpu_helper.h
+++ b/target/mips/fpu_helper.h
@@ -35,7 +35,8 @@ static inline void restore_snan_bit_mode(CPUMIPSState *env)
* With nan2008, SNaNs are silenced in the usual way.
* Before that, SNaNs are not silenced; default nans are produced.
*/
- set_snan_bit_is_one(!nan2008, &env->active_fpu.fp_status);
+ set_snan_rule(nan2008 ? float_snan_bit_is_zero : float_snan_bit_is_one,
+ &env->active_fpu.fp_status);
set_default_nan_mode(!nan2008, &env->active_fpu.fp_status);
/*
* For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
diff --git a/target/hppa/fpu_helper.c b/target/hppa/fpu_helper.c
index 2d272730f6..cdbebcfeb3 100644
--- a/target/hppa/fpu_helper.c
+++ b/target/hppa/fpu_helper.c
@@ -66,7 +66,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);
+ set_snan_rule(float_snan_bit_is_one, &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/mips/msa.c b/target/mips/msa.c
index 32c6acbcc5..53fbce10d3 100644
--- a/target/mips/msa.c
+++ b/target/mips/msa.c
@@ -84,8 +84,8 @@ void msa_reset(CPUMIPSState *env)
/* clear float_status nan mode */
set_default_nan_mode(0, &env->active_tc.msa_fp_status);
- /* set proper signanling bit meaning ("1" means "quiet") */
- set_snan_bit_is_one(0, &env->active_tc.msa_fp_status);
+ /* set proper signanling bit meaning */
+ set_snan_rule(float_snan_bit_is_zero, &env->active_tc.msa_fp_status);
/* Inf * 0 + NaN returns the input NaN */
set_float_infzeronan_rule(float_infzeronan_dnan_never,
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 40d5fde76d..763424695c 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -151,7 +151,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);
+ set_snan_rule(float_snan_bit_is_one, &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/target/xtensa/cpu.c b/target/xtensa/cpu.c
index d6d42319e5..2015a4e3d0 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -209,7 +209,8 @@ static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
#endif
/* For inf * 0 + NaN, return the input NaN */
set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
- set_no_signaling_nans(!dfpu, &env->fp_status);
+ set_snan_rule(dfpu ? float_snan_bit_is_zero : float_snan_never,
+ &env->fp_status);
/* Default NaN value: sign bit clear, set frac msb */
set_float_default_nan_pattern(0b01000000, &env->fp_status);
xtensa_use_first_nan(env, !dfpu);
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index e2e3ec0e81..0b527302a5 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -79,26 +79,6 @@ this code that are retained.
* version 2 or later. See the COPYING file in the top-level directory.
*/
-/*
- * Define whether architecture deviates from IEEE in not supporting
- * signaling NaNs (so all NaNs are treated as quiet).
- */
-static inline bool no_signaling_nans(float_status *status)
-{
- return status->no_signaling_nans;
-}
-
-/* Define how the architecture discriminates signaling NaNs.
- * This done with the most significant bit of the fraction.
- * 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.
- */
-static inline bool snan_bit_is_one(float_status *status)
-{
- return status->snan_bit_is_one;
-}
-
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
@@ -106,11 +86,15 @@ static inline bool snan_bit_is_one(float_status *status)
static bool frac_msb_is_snan(bool msb, float_status *status)
{
- if (no_signaling_nans(status)) {
+ switch (get_snan_rule(status)) {
+ case float_snan_never:
return false;
- } else {
- return msb == snan_bit_is_one(status);
+ case float_snan_bit_is_one:
+ return msb;
+ case float_snan_bit_is_zero:
+ return !msb;
}
+ g_assert_not_reached();
}
static bool parts_is_snan_frac(uint64_t frac, float_status *status)
@@ -172,14 +156,18 @@ FloatParts128 parts128_default_nan(float_status *status)
static uint64_t parts_silence_nan_frac(uint64_t frac, float_status *status)
{
- g_assert(!no_signaling_nans(status));
-
- /* The only snan_bit_is_one target without default_nan_mode is HPPA. */
- if (snan_bit_is_one(status)) {
+ switch (get_snan_rule(status)) {
+ case float_snan_bit_is_zero:
+ frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+ break;
+ case float_snan_bit_is_one:
+ /* The only snan_bit_is_one target without default_nan_mode is HPPA. */
frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1));
frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2);
- } else {
- frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+ break;
+ case float_snan_never:
+ default:
+ g_assert_not_reached();
}
return frac;
}
@@ -390,7 +378,7 @@ bool floatx80_is_signaling_nan(floatx80 a, float_status *status)
floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
{
/* None of the targets that have snan_bit_is_one use floatx80. */
- assert(!snan_bit_is_one(status));
+ assert(get_snan_rule(status) == float_snan_bit_is_zero);
a.low |= UINT64_C(0xC000000000000000);
return a;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 14/30] fpu: Use {get,set}_float_rounding_mode everywhere
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (12 preceding siblings ...)
2026-05-22 18:26 ` [PULL 13/30] fpu: Introduce FloatSNaNRule Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 15/30] fpu: Use of {get, set}_floatx80_rounding_precision everywhere Richard Henderson
` (16 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/i386/ops_sse.h | 24 ++---
fpu/softfloat.c | 88 +++++++++---------
target/alpha/fpu_helper.c | 2 +-
target/arm/tcg/vfp_helper.c | 8 +-
target/hexagon/fma_emu.c | 6 +-
target/i386/tcg/fpu_helper.c | 28 +++---
target/m68k/softfloat.c | 170 +++++++++++++++++-----------------
target/ppc/fpu_helper.c | 14 +--
target/riscv/vector_helper.c | 6 +-
target/s390x/tcg/fpu_helper.c | 4 +-
tests/fp/fp-bench.c | 2 +-
tests/fp/fp-test.c | 2 +-
fpu/softfloat-parts.c.inc | 8 +-
tests/fp/wrap.c.inc | 12 +--
14 files changed, 185 insertions(+), 189 deletions(-)
diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 99c4728ec8..5176a9f9e3 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -601,7 +601,7 @@ void glue(helper_cvtph2ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
void glue(helper_cvtps2ph, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, int mode)
{
int i;
- FloatRoundMode prev_rounding_mode = env->sse_status.float_rounding_mode;
+ FloatRoundMode prev_rounding_mode = get_float_rounding_mode(&env->sse_status);
if (!(mode & (1 << 2))) {
set_x86_rounding_mode(mode & 3, &env->sse_status);
}
@@ -613,7 +613,7 @@ void glue(helper_cvtps2ph, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, int mode)
d->Q(i) = 0;
}
- env->sse_status.float_rounding_mode = prev_rounding_mode;
+ set_float_rounding_mode(prev_rounding_mode, &env->sse_status);
}
#endif
@@ -1715,10 +1715,9 @@ void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
uint32_t mode)
{
int old_flags = get_float_exception_flags(&env->sse_status);
- signed char prev_rounding_mode;
+ FloatRoundMode prev_rounding_mode = get_float_rounding_mode(&env->sse_status);
int i;
- prev_rounding_mode = env->sse_status.float_rounding_mode;
if (!(mode & (1 << 2))) {
set_x86_rounding_mode(mode & 3, &env->sse_status);
}
@@ -1732,17 +1731,16 @@ void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
~float_flag_inexact,
&env->sse_status);
}
- env->sse_status.float_rounding_mode = prev_rounding_mode;
+ set_float_rounding_mode(prev_rounding_mode, &env->sse_status);
}
void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
uint32_t mode)
{
int old_flags = get_float_exception_flags(&env->sse_status);
- signed char prev_rounding_mode;
+ FloatRoundMode prev_rounding_mode = get_float_rounding_mode(&env->sse_status);
int i;
- prev_rounding_mode = env->sse_status.float_rounding_mode;
if (!(mode & (1 << 2))) {
set_x86_rounding_mode(mode & 3, &env->sse_status);
}
@@ -1756,7 +1754,7 @@ void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
~float_flag_inexact,
&env->sse_status);
}
- env->sse_status.float_rounding_mode = prev_rounding_mode;
+ set_float_rounding_mode(prev_rounding_mode, &env->sse_status);
}
#if SHIFT == 1
@@ -1764,10 +1762,9 @@ void glue(helper_roundss, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s,
uint32_t mode)
{
int old_flags = get_float_exception_flags(&env->sse_status);
- signed char prev_rounding_mode;
+ FloatRoundMode prev_rounding_mode = get_float_rounding_mode(&env->sse_status);
int i;
- prev_rounding_mode = env->sse_status.float_rounding_mode;
if (!(mode & (1 << 2))) {
set_x86_rounding_mode(mode & 3, &env->sse_status);
}
@@ -1782,17 +1779,16 @@ void glue(helper_roundss, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s,
~float_flag_inexact,
&env->sse_status);
}
- env->sse_status.float_rounding_mode = prev_rounding_mode;
+ set_float_rounding_mode(prev_rounding_mode, &env->sse_status);
}
void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s,
uint32_t mode)
{
int old_flags = get_float_exception_flags(&env->sse_status);
- signed char prev_rounding_mode;
+ FloatRoundMode prev_rounding_mode = get_float_rounding_mode(&env->sse_status);
int i;
- prev_rounding_mode = env->sse_status.float_rounding_mode;
if (!(mode & (1 << 2))) {
set_x86_rounding_mode(mode & 3, &env->sse_status);
}
@@ -1807,7 +1803,7 @@ void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s,
~float_flag_inexact,
&env->sse_status);
}
- env->sse_status.float_rounding_mode = prev_rounding_mode;
+ set_float_rounding_mode(prev_rounding_mode, &env->sse_status);
}
#endif
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 391d8f3169..d99543cc60 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -234,7 +234,7 @@ static inline bool can_use_fpu(const float_status *s)
return false;
}
return likely(s->float_exception_flags & float_flag_inexact &&
- s->float_rounding_mode == float_round_nearest_even);
+ get_float_rounding_mode(s) == float_round_nearest_even);
}
/*
@@ -2803,7 +2803,7 @@ float16 float16_round_to_int(float16 a, float_status *s)
{
FloatParts64 p = float16_unpack_canonical(a, s);
- p = parts64_round_to_int(&p, s->float_rounding_mode, 0, s,
+ p = parts64_round_to_int(&p, get_float_rounding_mode(s), 0, s,
&float16_params);
return float16_round_pack_canonical(&p, s);
}
@@ -2812,7 +2812,7 @@ float32 float32_round_to_int(float32 a, float_status *s)
{
FloatParts64 p = float32_unpack_canonical(a, s);
- p = parts64_round_to_int(&p, s->float_rounding_mode, 0, s,
+ p = parts64_round_to_int(&p, get_float_rounding_mode(s), 0, s,
&float32_params);
return float32_round_pack_canonical(&p, s);
}
@@ -2821,7 +2821,7 @@ float64 float64_round_to_int(float64 a, float_status *s)
{
FloatParts64 p = float64_unpack_canonical(a, s);
- p = parts64_round_to_int(&p, s->float_rounding_mode, 0, s,
+ p = parts64_round_to_int(&p, get_float_rounding_mode(s), 0, s,
&float64_params);
return float64_round_pack_canonical(&p, s);
}
@@ -2830,7 +2830,7 @@ bfloat16 bfloat16_round_to_int(bfloat16 a, float_status *s)
{
FloatParts64 p = bfloat16_unpack_canonical(a, s);
- p = parts64_round_to_int(&p, s->float_rounding_mode, 0, s,
+ p = parts64_round_to_int(&p, get_float_rounding_mode(s), 0, s,
&bfloat16_params);
return bfloat16_round_pack_canonical(&p, s);
}
@@ -2839,7 +2839,7 @@ float128 float128_round_to_int(float128 a, float_status *s)
{
FloatParts128 p = float128_unpack_canonical(a, s);
- p = parts128_round_to_int(&p, s->float_rounding_mode, 0, s,
+ p = parts128_round_to_int(&p, get_float_rounding_mode(s), 0, s,
&float128_params);
return float128_round_pack_canonical(&p, s);
}
@@ -2852,7 +2852,7 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status)
return floatx80_default_nan(status);
}
- p = parts128_round_to_int(&p, status->float_rounding_mode, 0, status,
+ p = parts128_round_to_int(&p, get_float_rounding_mode(status), 0, status,
&floatx80_params[status->floatx80_rounding_precision]);
return floatx80_round_pack_canonical(&p, status);
}
@@ -3050,77 +3050,77 @@ static int64_t floatx80_to_int64_scalbn(floatx80 a, FloatRoundMode rmode,
int8_t float16_to_int8(float16 a, float_status *s)
{
- return float16_to_int8_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_int8_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int16_t float16_to_int16(float16 a, float_status *s)
{
- return float16_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_int16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int32_t float16_to_int32(float16 a, float_status *s)
{
- return float16_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_int32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int64_t float16_to_int64(float16 a, float_status *s)
{
- return float16_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_int64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int16_t float32_to_int16(float32 a, float_status *s)
{
- return float32_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
+ return float32_to_int16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int32_t float32_to_int32(float32 a, float_status *s)
{
- return float32_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float32_to_int32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int64_t float32_to_int64(float32 a, float_status *s)
{
- return float32_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float32_to_int64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int16_t float64_to_int16(float64 a, float_status *s)
{
- return float64_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
+ return float64_to_int16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int32_t float64_to_int32(float64 a, float_status *s)
{
- return float64_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float64_to_int32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int64_t float64_to_int64(float64 a, float_status *s)
{
- return float64_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float64_to_int64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int32_t float128_to_int32(float128 a, float_status *s)
{
- return float128_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float128_to_int32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int64_t float128_to_int64(float128 a, float_status *s)
{
- return float128_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float128_to_int64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
Int128 float128_to_int128(float128 a, float_status *s)
{
- return float128_to_int128_scalbn(a, s->float_rounding_mode, 0, s);
+ return float128_to_int128_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int32_t floatx80_to_int32(floatx80 a, float_status *s)
{
- return floatx80_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
+ return floatx80_to_int32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int64_t floatx80_to_int64(floatx80 a, float_status *s)
{
- return floatx80_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
+ return floatx80_to_int64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int16_t float16_to_int16_round_to_zero(float16 a, float_status *s)
@@ -3195,22 +3195,22 @@ int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *s)
int8_t bfloat16_to_int8(bfloat16 a, float_status *s)
{
- return bfloat16_to_int8_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_int8_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int16_t bfloat16_to_int16(bfloat16 a, float_status *s)
{
- return bfloat16_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_int16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int32_t bfloat16_to_int32(bfloat16 a, float_status *s)
{
- return bfloat16_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_int32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int64_t bfloat16_to_int64(bfloat16 a, float_status *s)
{
- return bfloat16_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_int64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
int8_t bfloat16_to_int8_round_to_zero(bfloat16 a, float_status *s)
@@ -3489,67 +3489,67 @@ static Int128 float128_to_uint128_scalbn(float128 a, FloatRoundMode rmode,
uint8_t float16_to_uint8(float16 a, float_status *s)
{
- return float16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_uint8_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint16_t float16_to_uint16(float16 a, float_status *s)
{
- return float16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_uint16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint32_t float16_to_uint32(float16 a, float_status *s)
{
- return float16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_uint32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint64_t float16_to_uint64(float16 a, float_status *s)
{
- return float16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float16_to_uint64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint16_t float32_to_uint16(float32 a, float_status *s)
{
- return float32_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
+ return float32_to_uint16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint32_t float32_to_uint32(float32 a, float_status *s)
{
- return float32_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float32_to_uint32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint64_t float32_to_uint64(float32 a, float_status *s)
{
- return float32_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float32_to_uint64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint16_t float64_to_uint16(float64 a, float_status *s)
{
- return float64_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
+ return float64_to_uint16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint32_t float64_to_uint32(float64 a, float_status *s)
{
- return float64_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float64_to_uint32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint64_t float64_to_uint64(float64 a, float_status *s)
{
- return float64_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float64_to_uint64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint32_t float128_to_uint32(float128 a, float_status *s)
{
- return float128_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
+ return float128_to_uint32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint64_t float128_to_uint64(float128 a, float_status *s)
{
- return float128_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
+ return float128_to_uint64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
Int128 float128_to_uint128(float128 a, float_status *s)
{
- return float128_to_uint128_scalbn(a, s->float_rounding_mode, 0, s);
+ return float128_to_uint128_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *s)
@@ -3614,22 +3614,22 @@ Int128 float128_to_uint128_round_to_zero(float128 a, float_status *s)
uint8_t bfloat16_to_uint8(bfloat16 a, float_status *s)
{
- return bfloat16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_uint8_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s)
{
- return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_uint16_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint32_t bfloat16_to_uint32(bfloat16 a, float_status *s)
{
- return bfloat16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_uint32_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint64_t bfloat16_to_uint64(bfloat16 a, float_status *s)
{
- return bfloat16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
+ return bfloat16_to_uint64_scalbn(a, get_float_rounding_mode(s), 0, s);
}
uint8_t bfloat16_to_uint8_round_to_zero(bfloat16 a, float_status *s)
@@ -4878,7 +4878,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
bool roundNearestEven, increment, isTiny;
int64_t roundIncrement, roundMask, roundBits;
- roundingMode = status->float_rounding_mode;
+ roundingMode = get_float_rounding_mode(status);
roundNearestEven = ( roundingMode == float_round_nearest_even );
switch (roundingPrecision) {
case floatx80_precision_x:
diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c
index 9af77777da..0ced53c54e 100644
--- a/target/alpha/fpu_helper.c
+++ b/target/alpha/fpu_helper.c
@@ -485,7 +485,7 @@ static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
{
- return do_cvttq(env, a, FP_STATUS.float_rounding_mode);
+ return do_cvttq(env, a, get_float_rounding_mode(&FP_STATUS));
}
uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
index e692bc568b..5839e82449 100644
--- a/target/arm/tcg/vfp_helper.c
+++ b/target/arm/tcg/vfp_helper.c
@@ -423,10 +423,10 @@ ftype HELPER(vfp_##name##to##p)(uint##isz##_t x, uint32_t shift, \
float_status *fpst) \
{ \
ftype ret; \
- FloatRoundMode oldmode = fpst->float_rounding_mode; \
- fpst->float_rounding_mode = float_round_nearest_even; \
+ FloatRoundMode oldmode = get_float_rounding_mode(fpst); \
+ set_float_rounding_mode(float_round_nearest_even, fpst); \
ret = itype##_to_##float##fsz##_scalbn(x, -shift, fpst); \
- fpst->float_rounding_mode = oldmode; \
+ set_float_rounding_mode(oldmode, fpst); \
return ret; \
}
@@ -663,7 +663,7 @@ static uint64_t call_recip_estimate(int *exp, int exp_off, uint64_t frac,
static bool round_to_inf(float_status *fpst, bool sign_bit)
{
- switch (fpst->float_rounding_mode) {
+ switch (get_float_rounding_mode(fpst)) {
case float_round_nearest_even: /* Round to Nearest */
return true;
case float_round_up: /* Round to +Inf */
diff --git a/target/hexagon/fma_emu.c b/target/hexagon/fma_emu.c
index c557141f11..a90f5c87b6 100644
--- a/target/hexagon/fma_emu.c
+++ b/target/hexagon/fma_emu.c
@@ -315,7 +315,7 @@ static float64 accum_round_float64(Accum a, float_status *fp_status)
if ((int128_gethi(a.mant) == 0) && (int128_getlo(a.mant) == 0)
&& ((a.guard | a.round | a.sticky) == 0)) {
/* result zero */
- switch (fp_status->float_rounding_mode) {
+ switch (get_float_rounding_mode(fp_status)) {
case float_round_down:
return zero_float64(1);
default:
@@ -362,7 +362,7 @@ static float64 accum_round_float64(Accum a, float_status *fp_status)
/* OK, we're relatively canonical... now we need to round */
if (a.guard || a.round || a.sticky) {
float_raise(float_flag_inexact, fp_status);
- switch (fp_status->float_rounding_mode) {
+ switch (get_float_rounding_mode(fp_status)) {
case float_round_to_zero:
/* Chop and we're done */
break;
@@ -401,7 +401,7 @@ static float64 accum_round_float64(Accum a, float_status *fp_status)
/* Yep, inf result */
float_raise(float_flag_overflow, fp_status);
float_raise(float_flag_inexact, fp_status);
- switch (fp_status->float_rounding_mode) {
+ switch (get_float_rounding_mode(fp_status)) {
case float_round_to_zero:
return maxfinite_float64(a.sign);
case float_round_up:
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 37c83ded38..7b0b0dd520 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1183,10 +1183,10 @@ void helper_f2xm1(CPUX86State *env)
bool asign, bsign;
int32_t n, aexp, bexp;
uint64_t asig0, asig1, asig2, bsig0, bsig1;
- FloatRoundMode save_mode = env->fp_status.float_rounding_mode;
+ FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
env->fp_status.floatx80_rounding_precision;
- env->fp_status.float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
/* Find the nearest multiple of 1/32 to the argument. */
@@ -1202,7 +1202,7 @@ void helper_f2xm1(CPUX86State *env)
*/
ST0 = f2xm1_table[n].t;
set_float_exception_flags(float_flag_inexact, &env->fp_status);
- env->fp_status.float_rounding_mode = save_mode;
+ set_float_rounding_mode(save_mode, &env->fp_status);
} else {
/*
* Compute the lower parts of a polynomial expansion for
@@ -1282,7 +1282,7 @@ void helper_f2xm1(CPUX86State *env)
asign = bsign;
}
}
- env->fp_status.float_rounding_mode = save_mode;
+ set_float_rounding_mode(save_mode, &env->fp_status);
/* This result is inexact. */
asig1 |= 1;
ST0 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
@@ -1483,10 +1483,10 @@ void helper_fpatan(CPUX86State *env)
uint64_t azsig0, azsig1;
uint64_t azsig2, azsig3, axsig0, axsig1;
floatx80 x8;
- FloatRoundMode save_mode = env->fp_status.float_rounding_mode;
+ FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
env->fp_status.floatx80_rounding_precision;
- env->fp_status.float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
if (arg0_exp == 0) {
@@ -1793,7 +1793,7 @@ void helper_fpatan(CPUX86State *env)
}
}
- env->fp_status.float_rounding_mode = save_mode;
+ set_float_rounding_mode(save_mode, &env->fp_status);
env->fp_status.floatx80_rounding_precision = save_prec;
}
/* This result is inexact. */
@@ -2121,10 +2121,10 @@ void helper_fyl2xp1(CPUX86State *env)
} else {
int32_t aexp;
uint64_t asig0, asig1, asig2;
- FloatRoundMode save_mode = env->fp_status.float_rounding_mode;
+ FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
env->fp_status.floatx80_rounding_precision;
- env->fp_status.float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
helper_fyl2x_common(env, ST0, &aexp, &asig0, &asig1);
@@ -2139,7 +2139,7 @@ void helper_fyl2xp1(CPUX86State *env)
aexp += arg1_exp - 0x3ffe;
/* This result is inexact. */
asig1 |= 1;
- env->fp_status.float_rounding_mode = save_mode;
+ set_float_rounding_mode(save_mode, &env->fp_status);
ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
arg0_sign ^ arg1_sign, aexp,
asig0, asig1, &env->fp_status);
@@ -2224,10 +2224,10 @@ void helper_fyl2x(CPUX86State *env)
} else {
int32_t int_exp;
floatx80 arg0_m1;
- FloatRoundMode save_mode = env->fp_status.float_rounding_mode;
+ FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
env->fp_status.floatx80_rounding_precision;
- env->fp_status.float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
if (arg0_exp == 0) {
@@ -2245,7 +2245,7 @@ void helper_fyl2x(CPUX86State *env)
floatx80_one, &env->fp_status);
if (floatx80_is_zero(arg0_m1)) {
/* Exact power of 2; multiply by ST1. */
- env->fp_status.float_rounding_mode = save_mode;
+ set_float_rounding_mode(save_mode, &env->fp_status);
ST1 = floatx80_mul(int32_to_floatx80(int_exp, &env->fp_status),
ST1, &env->fp_status);
} else {
@@ -2284,7 +2284,7 @@ void helper_fyl2x(CPUX86State *env)
aexp += arg1_exp - 0x3ffe;
/* This result is inexact. */
asig1 |= 1;
- env->fp_status.float_rounding_mode = save_mode;
+ set_float_rounding_mode(save_mode, &env->fp_status);
ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
asign ^ arg1_sign, aexp,
asig0, asig1, &env->fp_status);
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index d1f150e641..51706f6db8 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -266,9 +266,9 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
return floatx80_move(a, status);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -336,7 +336,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
status); /* LOG(F)+U*V*(A2+V*(A4+V*A6)) */
fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS LOG(F) + LOG(1+U) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, klog2, status);
@@ -402,7 +402,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, fp1,
status); /* U*V*([B1+W*(B3+W*B5)] + [V*(B2+W*B4)]) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, saveu, status);
@@ -464,9 +464,9 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
return floatx80_default_nan(status);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -523,7 +523,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
status); /* LOG(F)+U*V*(A2+V*(A4+V*A6)) */
fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS LOG(F) + LOG(1+U) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, klog2, status);
@@ -569,7 +569,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, fp1,
status); /* U*V*([B1+W*(B3+W*B5)] + [V*(B2+W*B4)]) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, saveu, status);
@@ -620,15 +620,15 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
return floatx80_default_nan(status);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
fp0 = floatx80_logn(a, status);
fp1 = packFloatx80(0, 0x3FFD, UINT64_C(0xDE5BD8A937287195)); /* INV_L10 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, fp1, status); /* LOGN(X)*INV_L10 */
@@ -679,13 +679,13 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
return floatx80_default_nan(status);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
if (aSig == one_sig) { /* X is 2^k */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = int32_to_floatx80(aExp - 0x3FFF, status);
@@ -693,7 +693,7 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
fp0 = floatx80_logn(a, status);
fp1 = packFloatx80(0, 0x3FFF, UINT64_C(0xB8AA3B295C17F0BC)); /* INV_L2 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, fp1, status); /* LOGN(X)*INV_L2 */
@@ -739,9 +739,9 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
return packFloatx80(0, one_exp, one_sig);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
adjflag = 0;
@@ -817,7 +817,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, adjscale, status);
}
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, scale, status);
@@ -827,7 +827,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
return a;
} else { /* |X| >= 16380 log2 */
if (compact > 0x400CB27C) { /* |X| >= 16480 log2 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
if (aSign) {
a = roundAndPackFloatx80(
@@ -876,7 +876,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
}
}
} else { /* |X| < 2^(-65) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(a, float32_to_floatx80(make_float32(0x3F800000),
@@ -922,9 +922,9 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
return packFloatx80(0, one_exp, one_sig);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
fp0 = a;
@@ -934,7 +934,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
if (compact < 0x3FB98000 || compact > 0x400D80C0) {
/* |X| > 16480 or |X| < 2^(-70) */
if (compact > 0x3FFF8000) { /* |X| > 16480 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
if (aSign) {
@@ -945,7 +945,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
0, 0x8000, aSig, 0, status);
}
} else { /* |X| < 2^(-70) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, float32_to_floatx80(
@@ -1027,7 +1027,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fact2, status);
fp0 = floatx80_add(fp0, fact1, status);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, adjfact, status);
@@ -1072,9 +1072,9 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
return packFloatx80(0, one_exp, one_sig);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
fp0 = a;
@@ -1084,7 +1084,7 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
if (compact < 0x3FB98000 || compact > 0x400B9B07) {
/* |X| > 16480 LOG2/LOG10 or |X| < 2^(-70) */
if (compact > 0x3FFF8000) { /* |X| > 16480 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
if (aSign) {
@@ -1095,7 +1095,7 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
0, 0x8000, aSig, 0, status);
}
} else { /* |X| < 2^(-70) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, float32_to_floatx80(
@@ -1182,7 +1182,7 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fact2, status);
fp0 = floatx80_add(fp0, fact1, status);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, adjfact, status);
@@ -1227,9 +1227,9 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
return packFloatx80(aSign, 0, 0);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -1294,7 +1294,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
fp1 = floatx80_add(fp1, fp3, status); /* FP1 is r := (A-R)+a */
goto loop;
} else {
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_move(a, status);
@@ -1354,7 +1354,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
xSign ^= 1;
fp1 = packFloatx80(xSign, xExp, xSig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_div(fp0, fp1, status);
@@ -1392,7 +1392,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
make_float32(0x3F800000), status),
status); /* 1+S(Q1+S(Q2+S(Q3+SQ4))) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_div(fp0, fp1, status);
@@ -1438,9 +1438,9 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
return packFloatx80(aSign, 0, 0);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -1509,7 +1509,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
fp0 = float32_to_floatx80(make_float32(0x3F800000),
status); /* 1 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
/* SINTINY */
@@ -1582,7 +1582,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
x = packFloatx80(xSign, xExp, xSig);
fp0 = floatx80_mul(fp0, x, status);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
@@ -1632,7 +1632,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, x, status); /* R'*S */
fp0 = floatx80_mul(fp0, fp1, status); /* SIN(R')-R' */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, x, status);
@@ -1678,9 +1678,9 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
return packFloatx80(0, one_exp, one_sig);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -1748,7 +1748,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
/* SINSM */
fp0 = float32_to_floatx80(make_float32(0x3F800000), status); /* 1 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
/* COSTINY */
@@ -1822,7 +1822,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
x = packFloatx80(xSign, xExp, xSig);
fp0 = floatx80_mul(fp0, x, status);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
@@ -1870,7 +1870,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, x, status); /* R'*S */
fp0 = floatx80_mul(fp0, fp1, status); /* SIN(R')-R' */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, x, status);
@@ -1917,9 +1917,9 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
compact = floatx80_make_compact(aExp, aSig);
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
if (compact < 0x3FFB8000 || compact > 0x4002FFFF) {
@@ -1929,7 +1929,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp0 = packFloatx80(aSign, piby2_exp, pi_sig);
fp1 = packFloatx80(aSign, 0x0001, one_sig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_sub(fp0, fp1, status);
@@ -1969,7 +1969,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, xsave, status);
fp1 = packFloatx80(aSign, piby2_exp, pi_sig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, fp1, status);
@@ -1980,7 +1980,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
}
} else { /* |X| < 1/16 */
if (compact < 0x3FD78000) { /* |X| < 2^(-40) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_move(a, status);
@@ -2020,7 +2020,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
/* X*Y*([B1+Z*(B3+Z*B5)]+[Y*(B2+Z*(B4+Z*B6))]) */
fp0 = floatx80_mul(fp0, fp1, status);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, xsave, status);
@@ -2069,7 +2069,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp1 = floatx80_mul(fp1, fp2, status); /* A1*U*V*(A2+V*(A3+V)) */
fp0 = floatx80_add(fp0, fp1, status); /* ATAN(U) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, fp3, status); /* ATAN(X) */
@@ -2122,9 +2122,9 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
} /* |X| < 1 */
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
one = packFloatx80(0, one_exp, one_sig);
@@ -2136,7 +2136,7 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
fp1 = floatx80_sqrt(fp1, status); /* SQRT((1+X)*(1-X)) */
fp0 = floatx80_div(fp0, fp1, status); /* X/SQRT((1+X)*(1-X)) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_atan(fp0, status); /* ATAN(X/SQRT((1+X)*(1-X))) */
@@ -2192,9 +2192,9 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
}
} /* |X| < 1 */
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
one = packFloatx80(0, one_exp, one_sig);
@@ -2206,7 +2206,7 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
fp0 = floatx80_sqrt(fp0, status); /* SQRT((1-X)/(1+X)) */
fp0 = floatx80_atan(fp0, status); /* ATAN(SQRT((1-X)/(1+X))) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, fp0, status); /* 2 * ATAN(SQRT((1-X)/(1+X))) */
@@ -2256,9 +2256,9 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
}
} /* |X| < 1 */
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
one = packFloatx80(0, one_exp, one_sig);
@@ -2270,7 +2270,7 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
fp0 = floatx80_div(fp0, fp1, status); /* Z = 2Y/(1-Y) */
fp0 = floatx80_lognp1(fp0, status); /* LOG1P(Z) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, fp2,
@@ -2315,9 +2315,9 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
return packFloatx80(aSign, 0, 0);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
if (aExp >= 0x3FFD) { /* |X| >= 1/4 */
@@ -2410,7 +2410,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
sc = packFloatx80(0, m + 0x3FFF, one_sig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, sc, status);
@@ -2423,7 +2423,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
fp0 = float32_to_floatx80(make_float32(0xBF800000),
status); /* -1 */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, float32_to_floatx80(
@@ -2434,7 +2434,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
return a;
} else {
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
return floatx80_etox(a, status);
@@ -2495,7 +2495,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
fp1 = floatx80_add(fp1, fp2, status); /* Q */
fp0 = floatx80_add(fp0, fp1, status); /* S*B1+Q */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, a, status);
@@ -2513,14 +2513,14 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
status);
fp0 = floatx80_add(fp0, sc, status);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, float64_to_floatx80(
make_float64(0x3730000000000000), status),
status);
} else {
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, sc, status);
@@ -2565,9 +2565,9 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
return packFloatx80(aSign, 0, 0);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -2576,7 +2576,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
/* TANHBORS */
if (compact < 0x3FFF8000) {
/* TANHSM */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_move(a, status);
@@ -2593,7 +2593,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
sign &= 0x80000000;
sign ^= 0x80800000; /* -SIGN(X)*EPS */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, float32_to_floatx80(make_float32(sign),
@@ -2615,7 +2615,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
fp0 = float32_to_floatx80(make_float32(sign | 0x3F800000),
status); /* SIGN */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp1, fp0, status);
@@ -2638,7 +2638,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
fp1 = packFloatx80(vSign ^ aSign, vExp, vSig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_div(fp0, fp1, status);
@@ -2681,9 +2681,9 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
return packFloatx80(aSign, 0, 0);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
@@ -2691,7 +2691,7 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
if (compact > 0x400CB167) {
/* SINHBIG */
if (compact > 0x400CB2B3) {
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
return roundAndPackFloatx80(status->floatx80_rounding_precision,
@@ -2707,7 +2707,7 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
fp0 = floatx80_etox(fp0, status);
fp2 = packFloatx80(aSign, 0x7FFB, one_sig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, fp2, status);
@@ -2727,7 +2727,7 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
fact = packFloat32(aSign, 0x7E, 0);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, float32_to_floatx80(fact, status), status);
@@ -2767,16 +2767,16 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
return packFloatx80(0, one_exp, one_sig);
}
- user_rnd_mode = status->float_rounding_mode;
+ user_rnd_mode = get_float_rounding_mode(status);
user_rnd_prec = status->floatx80_rounding_precision;
- status->float_rounding_mode = float_round_nearest_even;
+ set_float_rounding_mode(float_round_nearest_even, status);
status->floatx80_rounding_precision = floatx80_precision_x;
compact = floatx80_make_compact(aExp, aSig);
if (compact > 0x400CB167) {
if (compact > 0x400CB2B3) {
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
0x8000, one_sig, 0, status);
@@ -2791,7 +2791,7 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
fp0 = floatx80_etox(fp0, status);
fp1 = packFloatx80(0, 0x7FFB, one_sig);
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_mul(fp0, fp1, status);
@@ -2809,7 +2809,7 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
fp1 = float32_to_floatx80(make_float32(0x3E800000), status); /* 1/4 */
fp1 = floatx80_div(fp1, fp0, status); /* 1/(2*EXP(|X|)) */
- status->float_rounding_mode = user_rnd_mode;
+ set_float_rounding_mode(user_rnd_mode, status);
status->floatx80_rounding_precision = user_rnd_prec;
a = floatx80_add(fp0, fp1, status);
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 850aca6ed1..c1bdde9e10 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -1616,7 +1616,7 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode,
tstat = env->fp_status;
if (unlikely(Rc(opcode) != 0)) {
- tstat.float_rounding_mode = float_round_to_odd;
+ set_float_rounding_mode(float_round_to_odd, &tstat);
}
set_float_exception_flags(0, &tstat);
@@ -1688,7 +1688,7 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode,
helper_reset_fpstatus(env);
tstat = env->fp_status;
if (unlikely(Rc(opcode) != 0)) {
- tstat.float_rounding_mode = float_round_to_odd;
+ set_float_rounding_mode(float_round_to_odd, &tstat);
}
set_float_exception_flags(0, &tstat);
@@ -1762,7 +1762,7 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode,
helper_reset_fpstatus(env);
tstat = env->fp_status;
if (unlikely(Rc(opcode) != 0)) {
- tstat.float_rounding_mode = float_round_to_odd;
+ set_float_rounding_mode(float_round_to_odd, &tstat);
}
set_float_exception_flags(0, &tstat);
@@ -2095,7 +2095,7 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *s1, ppc_vsr_t *s2,\
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
if (ro) { \
- tstat.float_rounding_mode = float_round_to_odd; \
+ set_float_rounding_mode(float_round_to_odd, &tstat); \
} \
t.f128 = float128_muladd(s1->f128, s3->f128, s2->f128, maddflgs, &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
@@ -2706,7 +2706,7 @@ void helper_XSCVQPDP(CPUPPCState *env, uint32_t ro, ppc_vsr_t *xt,
tstat = env->fp_status;
if (ro != 0) {
- tstat.float_rounding_mode = float_round_to_odd;
+ set_float_rounding_mode(float_round_to_odd, &tstat);
}
t.VsrD(0) = float128_to_float64(xb->f128, &tstat);
@@ -3306,7 +3306,7 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode,
tstat = env->fp_status;
if (unlikely(Rc(opcode) != 0)) {
- tstat.float_rounding_mode = float_round_to_odd;
+ set_float_rounding_mode(float_round_to_odd, &tstat);
}
set_float_exception_flags(0, &tstat);
@@ -3332,7 +3332,7 @@ void helper_xssubqp(CPUPPCState *env, uint32_t opcode,
tstat = env->fp_status;
if (unlikely(Rc(opcode) != 0)) {
- tstat.float_rounding_mode = float_round_to_odd;
+ set_float_rounding_mode(float_round_to_odd, &tstat);
}
set_float_exception_flags(0, &tstat);
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 5a3554dd71..c826702bf8 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -4270,9 +4270,9 @@ static uint64_t frec7(uint64_t f, int exp_size, int frac_size,
s->float_exception_flags |= (float_flag_inexact |
float_flag_overflow);
- if ((s->float_rounding_mode == float_round_to_zero) ||
- ((s->float_rounding_mode == float_round_down) && !sign) ||
- ((s->float_rounding_mode == float_round_up) && sign)) {
+ if ((get_float_rounding_mode(s) == float_round_to_zero) ||
+ ((get_float_rounding_mode(s) == float_round_down) && !sign) ||
+ ((get_float_rounding_mode(s) == float_round_up) && sign)) {
/* Return greatest/negative finite value. */
return (sign << (exp_size + frac_size)) |
(MAKE_64BIT_MASK(frac_size, exp_size) - 1);
diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c
index 33e0f6100d..6ca0b7162b 100644
--- a/target/s390x/tcg/fpu_helper.c
+++ b/target/s390x/tcg/fpu_helper.c
@@ -62,7 +62,7 @@ static int s390_get_bfp_rounding_mode(CPUS390XState *env, int m3)
switch (m3) {
case 0:
/* current mode */
- return env->fpu_status.float_rounding_mode;
+ return get_float_rounding_mode(&env->fpu_status);
case 1:
/* round to nearest with ties away from 0 */
return float_round_ties_away;
@@ -634,7 +634,7 @@ uint32_t HELPER(cxb)(CPUS390XState *env, Int128 a, Int128 b)
int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3)
{
- int ret = env->fpu_status.float_rounding_mode;
+ int ret = get_float_rounding_mode(&env->fpu_status);
set_float_rounding_mode(s390_get_bfp_rounding_mode(env, m3),
&env->fpu_status);
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
index d90f542ea2..2b6f66817e 100644
--- a/tests/fp/fp-bench.c
+++ b/tests/fp/fp-bench.c
@@ -615,7 +615,7 @@ static void set_soft_precision(enum rounding rounding)
default:
g_assert_not_reached();
}
- soft_status.float_rounding_mode = mode;
+ set_float_rounding_mode(mode, &soft_status);
}
static void parse_args(int argc, char *argv[])
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
index c619e5dbf7..fdb0cccf14 100644
--- a/tests/fp/fp-test.c
+++ b/tests/fp/fp-test.c
@@ -967,7 +967,7 @@ void run_test(void)
verCases_roundingCode = 0;
slowfloat_roundingMode = rmode;
- qsf.float_rounding_mode = sf_rounding_to_qemu(rmode);
+ set_float_rounding_mode(sf_rounding_to_qemu(rmode), &qsf);
if (attrs & (FUNC_ARG_ROUNDINGMODE | FUNC_EFF_ROUNDINGMODE)) {
/* print rounding mode if the op is affected by it */
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index bc348f75a3..7311c3696e 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -300,7 +300,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
int exp;
FloatExceptionFlags flags = 0;
- switch (s->float_rounding_mode) {
+ switch (get_float_rounding_mode(s)) {
case float_round_nearest_even_max:
overflow_norm = true;
/* fall through */
@@ -431,7 +431,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
if (p->frac_lo & round_mask) {
/* Need to recompute round-to-even/round-to-odd. */
- switch (s->float_rounding_mode) {
+ switch (get_float_rounding_mode(s)) {
case float_round_nearest_even:
if (N > 64 && frac_lsb == 0) {
inc = ((p->frac_hi & 1) ||
@@ -558,7 +558,7 @@ FloatPartsN partsN(addsub)(const FloatPartsN *a_orig,
if (ab_mask == float_cmask_zero) {
/* 0 - 0 */
- a.sign = s->float_rounding_mode == float_round_down;
+ a.sign = get_float_rounding_mode(s) == float_round_down;
return a;
}
@@ -763,7 +763,7 @@ FloatPartsN partsN(muladd)(const FloatPartsN *a, const FloatPartsN *b,
return_sub_zero:
/* 0 - 0 == -0 for round_down, +0 otherwise. */
return (FloatPartsN){
- .sign = s->float_rounding_mode == float_round_down,
+ .sign = get_float_rounding_mode(s) == float_round_down,
.cls = float_class_zero
};
diff --git a/tests/fp/wrap.c.inc b/tests/fp/wrap.c.inc
index 9ff884c140..a67b390e5a 100644
--- a/tests/fp/wrap.c.inc
+++ b/tests/fp/wrap.c.inc
@@ -168,7 +168,7 @@ WRAP_SF_TO_128(qemu_f64_to_f128M, float64_to_float128, float64)
{ \
type *ap = (type *)&a; \
\
- qsf.float_rounding_mode = sf_rounding_to_qemu(round); \
+ set_float_rounding_mode(sf_rounding_to_qemu(round), &qsf); \
return func(*ap, &qsf); \
}
@@ -328,7 +328,7 @@ WRAP_INT_TO_80(qemu_i64_to_extF80M, int64_to_floatx80, int64_t)
floatx80 a; \
\
a = soft_to_qemu80(*ap); \
- qsf.float_rounding_mode = sf_rounding_to_qemu(round); \
+ set_float_rounding_mode(sf_rounding_to_qemu(round), &qsf); \
return func(a, &qsf); \
}
@@ -360,7 +360,7 @@ WRAP_80_TO_INT_MINMAG(qemu_extF80M_to_i64_r_minMag,
float128 a; \
\
a = soft_to_qemu128(*ap); \
- qsf.float_rounding_mode = sf_rounding_to_qemu(round); \
+ set_float_rounding_mode(sf_rounding_to_qemu(round), &qsf); \
return func(a, &qsf); \
}
@@ -414,7 +414,7 @@ WRAP_INT_TO_128(qemu_i64_to_f128M, int64_to_float128, int64_t)
type *ap = (type *)&a; \
type ret; \
\
- qsf.float_rounding_mode = sf_rounding_to_qemu(round); \
+ set_float_rounding_mode(sf_rounding_to_qemu(round), &qsf); \
ret = func(*ap, &qsf); \
return *(type##_t *)&ret; \
}
@@ -431,7 +431,7 @@ static void qemu_extF80M_roundToInt(const extFloat80_t *ap, uint_fast8_t round,
floatx80 ret;
a = soft_to_qemu80(*ap);
- qsf.float_rounding_mode = sf_rounding_to_qemu(round);
+ set_float_rounding_mode(sf_rounding_to_qemu(round), &qsf);
ret = floatx80_round_to_int(a, &qsf);
*res = qemu_to_soft80(ret);
}
@@ -443,7 +443,7 @@ static void qemu_f128M_roundToInt(const float128_t *ap, uint_fast8_t round,
float128 ret;
a = soft_to_qemu128(*ap);
- qsf.float_rounding_mode = sf_rounding_to_qemu(round);
+ set_float_rounding_mode(sf_rounding_to_qemu(round), &qsf);
ret = float128_round_to_int(a, &qsf);
*res = qemu_to_soft128(ret);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 15/30] fpu: Use of {get, set}_floatx80_rounding_precision everywhere
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (13 preceding siblings ...)
2026-05-22 18:26 ` [PULL 14/30] fpu: Use {get,set}_float_rounding_mode everywhere Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 16/30] fpu: Use get_floatx80_behaviour everywhere Richard Henderson
` (15 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat.c | 10 +-
target/i386/tcg/fpu_helper.c | 37 ++++---
target/m68k/softfloat.c | 208 ++++++++++++++++++-----------------
tests/fp/fp-test.c | 2 +-
4 files changed, 130 insertions(+), 127 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index d99543cc60..d2a9f97089 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1515,7 +1515,7 @@ float128 float128_round_pack_canonical(FloatParts128 *p, float_status *s)
bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f, float_status *s)
{
/* Ensure rounding precision is set before beginning. */
- switch (s->floatx80_rounding_precision) {
+ switch (get_floatx80_rounding_precision(s)) {
case floatx80_precision_x:
case floatx80_precision_d:
case floatx80_precision_s:
@@ -1550,14 +1550,14 @@ bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f, float_status *s)
floatx80 floatx80_round_pack_canonical(FloatParts128 *p, float_status *s)
{
- const FloatFmt *fmt = &floatx80_params[s->floatx80_rounding_precision];
+ const FloatFmt *fmt = &floatx80_params[get_floatx80_rounding_precision(s)];
uint64_t frac;
int exp;
switch (p->cls) {
case float_class_normal:
case float_class_denormal:
- if (s->floatx80_rounding_precision == floatx80_precision_x) {
+ if (get_floatx80_rounding_precision(s) == floatx80_precision_x) {
parts128_uncanon_normal(p, s, fmt, false);
frac = p->frac_hi;
exp = p->exp;
@@ -2853,7 +2853,7 @@ floatx80 floatx80_round_to_int(floatx80 a, float_status *status)
}
p = parts128_round_to_int(&p, get_float_rounding_mode(status), 0, status,
- &floatx80_params[status->floatx80_rounding_precision]);
+ &floatx80_params[get_floatx80_rounding_precision(status)]);
return floatx80_round_pack_canonical(&p, status);
}
@@ -4503,7 +4503,7 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *s)
if (!floatx80_unpack_canonical(&p, a, s)) {
return floatx80_default_nan(s);
}
- parts128_sqrt(&p, s, &floatx80_params[s->floatx80_rounding_precision]);
+ parts128_sqrt(&p, s, &floatx80_params[get_floatx80_rounding_precision(s)]);
return floatx80_round_pack_canonical(&p, s);
}
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 7b0b0dd520..978eb1411b 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -1185,9 +1185,9 @@ void helper_f2xm1(CPUX86State *env)
uint64_t asig0, asig1, asig2, bsig0, bsig1;
FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
- env->fp_status.floatx80_rounding_precision;
+ get_floatx80_rounding_precision(&env->fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
/* Find the nearest multiple of 1/32 to the argument. */
tmp = floatx80_scalbn(ST0, 5, &env->fp_status);
@@ -1290,7 +1290,7 @@ void helper_f2xm1(CPUX86State *env)
&env->fp_status);
}
- env->fp_status.floatx80_rounding_precision = save_prec;
+ set_floatx80_rounding_precision(save_prec, &env->fp_status);
}
merge_exception_flags(env, old_flags);
}
@@ -1406,10 +1406,10 @@ void helper_fpatan(CPUX86State *env)
* (and underflowing where appropriate).
*/
FloatX80RoundPrec save_prec =
- env->fp_status.floatx80_rounding_precision;
- env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
+ get_floatx80_rounding_precision(&env->fp_status);
+ set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
ST1 = floatx80_div(ST1, ST0, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = save_prec;
+ set_floatx80_rounding_precision(save_prec, &env->fp_status);
if (!floatx80_is_zero(ST1) &&
!(get_float_exception_flags(&env->fp_status) &
float_flag_inexact)) {
@@ -1485,9 +1485,10 @@ void helper_fpatan(CPUX86State *env)
floatx80 x8;
FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
- env->fp_status.floatx80_rounding_precision;
+ get_floatx80_rounding_precision(&env->fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x,
+ &env->fp_status);
if (arg0_exp == 0) {
normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig);
@@ -1794,7 +1795,7 @@ void helper_fpatan(CPUX86State *env)
}
set_float_rounding_mode(save_mode, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = save_prec;
+ set_floatx80_rounding_precision(save_prec, &env->fp_status);
}
/* This result is inexact. */
rsig1 |= 1;
@@ -2123,9 +2124,9 @@ void helper_fyl2xp1(CPUX86State *env)
uint64_t asig0, asig1, asig2;
FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
- env->fp_status.floatx80_rounding_precision;
+ get_floatx80_rounding_precision(&env->fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
helper_fyl2x_common(env, ST0, &aexp, &asig0, &asig1);
/*
@@ -2143,7 +2144,7 @@ void helper_fyl2xp1(CPUX86State *env)
ST1 = normalizeRoundAndPackFloatx80(floatx80_precision_x,
arg0_sign ^ arg1_sign, aexp,
asig0, asig1, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = save_prec;
+ set_floatx80_rounding_precision(save_prec, &env->fp_status);
}
fpop(env);
merge_exception_flags(env, old_flags);
@@ -2226,9 +2227,9 @@ void helper_fyl2x(CPUX86State *env)
floatx80 arg0_m1;
FloatRoundMode save_mode = get_float_rounding_mode(&env->fp_status);
FloatX80RoundPrec save_prec =
- env->fp_status.floatx80_rounding_precision;
+ get_floatx80_rounding_precision(&env->fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
if (arg0_exp == 0) {
normalizeFloatx80Subnormal(arg0_sig, &arg0_exp, &arg0_sig);
@@ -2290,7 +2291,7 @@ void helper_fyl2x(CPUX86State *env)
asig0, asig1, &env->fp_status);
}
- env->fp_status.floatx80_rounding_precision = save_prec;
+ set_floatx80_rounding_precision(save_prec, &env->fp_status);
}
fpop(env);
merge_exception_flags(env, old_flags);
@@ -2368,14 +2369,14 @@ void helper_fscale(CPUX86State *env)
}
} else {
int n;
- FloatX80RoundPrec save = env->fp_status.floatx80_rounding_precision;
+ FloatX80RoundPrec save = get_floatx80_rounding_precision(&env->fp_status);
int save_flags = get_float_exception_flags(&env->fp_status);
set_float_exception_flags(0, &env->fp_status);
n = floatx80_to_int32_round_to_zero(ST1, &env->fp_status);
set_float_exception_flags(save_flags, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, &env->fp_status);
ST0 = floatx80_scalbn(ST0, n, &env->fp_status);
- env->fp_status.floatx80_rounding_precision = save;
+ set_floatx80_rounding_precision(save, &env->fp_status);
}
merge_exception_flags(env, old_flags);
}
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 51706f6db8..f5d683bcc5 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -72,7 +72,8 @@ floatx80 floatx80_getman(floatx80 a, float_status *status)
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
}
- return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
+ aSign,
0x3FFF, aSig, 0, status);
}
@@ -160,7 +161,7 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
if (0x400F < bExp) {
aExp = bSign ? -0x6001 : 0xE000;
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
aSign, aExp, aSig, 0, status);
}
@@ -168,7 +169,7 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
bSig >>= shiftCount;
aExp = bSign ? (aExp - bSig) : (aExp + bSig);
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
aSign, aExp, aSig, 0, status);
}
@@ -192,10 +193,11 @@ floatx80 floatx80_move(floatx80 a, float_status *status)
if (aSig == 0) {
return a;
}
- normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision,
+ normalizeRoundAndPackFloatx80(get_floatx80_rounding_precision(status),
aSign, aExp, aSig, 0, status);
}
- return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
+ aSign,
aExp, aSig, 0, status);
}
@@ -267,9 +269,9 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -337,7 +339,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS LOG(F) + LOG(1+U) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, klog2, status);
@@ -403,7 +405,7 @@ floatx80 floatx80_lognp1(floatx80 a, float_status *status)
status); /* U*V*([B1+W*(B3+W*B5)] + [V*(B2+W*B4)]) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, saveu, status);
@@ -465,9 +467,9 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -524,7 +526,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fp1, status); /* FP0 IS LOG(F) + LOG(1+U) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, klog2, status);
@@ -570,7 +572,7 @@ floatx80 floatx80_logn(floatx80 a, float_status *status)
status); /* U*V*([B1+W*(B3+W*B5)] + [V*(B2+W*B4)]) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, saveu, status);
@@ -621,15 +623,15 @@ floatx80 floatx80_log10(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
fp0 = floatx80_logn(a, status);
fp1 = packFloatx80(0, 0x3FFD, UINT64_C(0xDE5BD8A937287195)); /* INV_L10 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, fp1, status); /* LOGN(X)*INV_L10 */
@@ -680,13 +682,13 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
if (aSig == one_sig) { /* X is 2^k */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = int32_to_floatx80(aExp - 0x3FFF, status);
} else {
@@ -694,7 +696,7 @@ floatx80 floatx80_log2(floatx80 a, float_status *status)
fp1 = packFloatx80(0, 0x3FFF, UINT64_C(0xB8AA3B295C17F0BC)); /* INV_L2 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, fp1, status); /* LOGN(X)*INV_L2 */
}
@@ -740,9 +742,9 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
adjflag = 0;
@@ -818,7 +820,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
}
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, scale, status);
@@ -828,15 +830,13 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
} else { /* |X| >= 16380 log2 */
if (compact > 0x400CB27C) { /* |X| >= 16480 log2 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
if (aSign) {
- a = roundAndPackFloatx80(
- status->floatx80_rounding_precision,
- 0, -0x1000, aSig, 0, status);
+ a = roundAndPackFloatx80(get_floatx80_rounding_precision(status),
+ 0, -0x1000, aSig, 0, status);
} else {
- a = roundAndPackFloatx80(
- status->floatx80_rounding_precision,
- 0, 0x8000, aSig, 0, status);
+ a = roundAndPackFloatx80(get_floatx80_rounding_precision(status),
+ 0, 0x8000, aSig, 0, status);
}
float_raise(float_flag_inexact, status);
@@ -877,7 +877,7 @@ floatx80 floatx80_etox(floatx80 a, float_status *status)
}
} else { /* |X| < 2^(-65) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(a, float32_to_floatx80(make_float32(0x3F800000),
status), status); /* 1 + X */
@@ -923,9 +923,9 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
fp0 = a;
@@ -935,18 +935,18 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
/* |X| > 16480 or |X| < 2^(-70) */
if (compact > 0x3FFF8000) { /* |X| > 16480 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
if (aSign) {
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
0, -0x1000, aSig, 0, status);
} else {
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
0, 0x8000, aSig, 0, status);
}
} else { /* |X| < 2^(-70) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, float32_to_floatx80(
make_float32(0x3F800000), status),
@@ -1028,7 +1028,7 @@ floatx80 floatx80_twotox(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fact1, status);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, adjfact, status);
@@ -1073,9 +1073,9 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
fp0 = a;
@@ -1085,18 +1085,18 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
/* |X| > 16480 LOG2/LOG10 or |X| < 2^(-70) */
if (compact > 0x3FFF8000) { /* |X| > 16480 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
if (aSign) {
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
0, -0x1000, aSig, 0, status);
} else {
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
0, 0x8000, aSig, 0, status);
}
} else { /* |X| < 2^(-70) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, float32_to_floatx80(
make_float32(0x3F800000), status),
@@ -1183,7 +1183,7 @@ floatx80 floatx80_tentox(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fact1, status);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, adjfact, status);
@@ -1228,9 +1228,9 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -1295,7 +1295,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
goto loop;
} else {
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_move(a, status);
@@ -1355,7 +1355,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
fp1 = packFloatx80(xSign, xExp, xSig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_div(fp0, fp1, status);
@@ -1393,7 +1393,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status)
status); /* 1+S(Q1+S(Q2+S(Q3+SQ4))) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_div(fp0, fp1, status);
@@ -1439,9 +1439,9 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -1510,7 +1510,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
status); /* 1 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
/* SINTINY */
a = floatx80_move(a, status);
@@ -1583,7 +1583,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, x, status);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
@@ -1633,7 +1633,7 @@ floatx80 floatx80_sin(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, fp1, status); /* SIN(R')-R' */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, x, status);
@@ -1679,9 +1679,9 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -1749,7 +1749,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
fp0 = float32_to_floatx80(make_float32(0x3F800000), status); /* 1 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
/* COSTINY */
a = floatx80_sub(fp0, float32_to_floatx80(
@@ -1823,7 +1823,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, x, status);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, float32_to_floatx80(posneg1, status), status);
@@ -1871,7 +1871,7 @@ floatx80 floatx80_cos(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, fp1, status); /* SIN(R')-R' */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, x, status);
@@ -1918,9 +1918,9 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
compact = floatx80_make_compact(aExp, aSig);
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
if (compact < 0x3FFB8000 || compact > 0x4002FFFF) {
/* |X| >= 16 or |X| < 1/16 */
@@ -1930,7 +1930,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp1 = packFloatx80(aSign, 0x0001, one_sig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_sub(fp0, fp1, status);
@@ -1970,7 +1970,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp1 = packFloatx80(aSign, piby2_exp, pi_sig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, fp1, status);
@@ -1981,7 +1981,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
} else { /* |X| < 1/16 */
if (compact < 0x3FD78000) { /* |X| < 2^(-40) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_move(a, status);
@@ -2021,7 +2021,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp0 = floatx80_mul(fp0, fp1, status);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, xsave, status);
@@ -2070,7 +2070,7 @@ floatx80 floatx80_atan(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fp1, status); /* ATAN(U) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, fp3, status); /* ATAN(X) */
@@ -2123,9 +2123,9 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
} /* |X| < 1 */
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
one = packFloatx80(0, one_exp, one_sig);
fp0 = a;
@@ -2137,7 +2137,7 @@ floatx80 floatx80_asin(floatx80 a, float_status *status)
fp0 = floatx80_div(fp0, fp1, status); /* X/SQRT((1+X)*(1-X)) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_atan(fp0, status); /* ATAN(X/SQRT((1+X)*(1-X))) */
@@ -2171,7 +2171,8 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
}
if (aExp == 0 && aSig == 0) {
float_raise(float_flag_inexact, status);
- return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
+ 0,
piby2_exp, pi_sig, 0, status);
}
@@ -2193,9 +2194,9 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
} /* |X| < 1 */
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
one = packFloatx80(0, one_exp, one_sig);
fp0 = a;
@@ -2207,7 +2208,7 @@ floatx80 floatx80_acos(floatx80 a, float_status *status)
fp0 = floatx80_atan(fp0, status); /* ATAN(SQRT((1-X)/(1+X))) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, fp0, status); /* 2 * ATAN(SQRT((1-X)/(1+X))) */
@@ -2257,9 +2258,9 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
} /* |X| < 1 */
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
one = packFloatx80(0, one_exp, one_sig);
fp2 = packFloatx80(aSign, 0x3FFE, one_sig); /* SIGN(X) * (1/2) */
@@ -2271,7 +2272,7 @@ floatx80 floatx80_atanh(floatx80 a, float_status *status)
fp0 = floatx80_lognp1(fp0, status); /* LOG1P(Z) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, fp2,
status); /* ATANH(X) = SIGN(X) * (1/2) * LOG1P(Z) */
@@ -2316,9 +2317,9 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
if (aExp >= 0x3FFD) { /* |X| >= 1/4 */
compact = floatx80_make_compact(aExp, aSig);
@@ -2411,7 +2412,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
sc = packFloatx80(0, m + 0x3FFF, one_sig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, sc, status);
@@ -2424,7 +2425,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
status); /* -1 */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, float32_to_floatx80(
make_float32(0x00800000), status),
@@ -2435,7 +2436,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
return a;
} else {
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
return floatx80_etox(a, status);
}
@@ -2496,7 +2497,7 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, fp1, status); /* S*B1+Q */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, a, status);
@@ -2514,14 +2515,14 @@ floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
fp0 = floatx80_add(fp0, sc, status);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, float64_to_floatx80(
make_float64(0x3730000000000000), status),
status);
} else {
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, sc, status);
}
@@ -2566,9 +2567,9 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -2577,7 +2578,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
if (compact < 0x3FFF8000) {
/* TANHSM */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_move(a, status);
@@ -2594,7 +2595,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
sign ^= 0x80800000; /* -SIGN(X)*EPS */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, float32_to_floatx80(make_float32(sign),
status), status);
@@ -2616,7 +2617,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
status); /* SIGN */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp1, fp0, status);
@@ -2639,7 +2640,7 @@ floatx80 floatx80_tanh(floatx80 a, float_status *status)
fp1 = packFloatx80(vSign ^ aSign, vExp, vSig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_div(fp0, fp1, status);
@@ -2682,9 +2683,9 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
@@ -2692,9 +2693,9 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
/* SINHBIG */
if (compact > 0x400CB2B3) {
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
- return roundAndPackFloatx80(status->floatx80_rounding_precision,
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
aSign, 0x8000, aSig, 0, status);
} else {
fp0 = floatx80_abs(a); /* Y = |X| */
@@ -2708,7 +2709,7 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
fp2 = packFloatx80(aSign, 0x7FFB, one_sig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, fp2, status);
@@ -2728,7 +2729,7 @@ floatx80 floatx80_sinh(floatx80 a, float_status *status)
fact = packFloat32(aSign, 0x7E, 0);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, float32_to_floatx80(fact, status), status);
@@ -2768,17 +2769,18 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
}
user_rnd_mode = get_float_rounding_mode(status);
- user_rnd_prec = status->floatx80_rounding_precision;
+ user_rnd_prec = get_floatx80_rounding_precision(status);
set_float_rounding_mode(float_round_nearest_even, status);
- status->floatx80_rounding_precision = floatx80_precision_x;
+ set_floatx80_rounding_precision(floatx80_precision_x, status);
compact = floatx80_make_compact(aExp, aSig);
if (compact > 0x400CB167) {
if (compact > 0x400CB2B3) {
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
- return roundAndPackFloatx80(status->floatx80_rounding_precision, 0,
+ set_floatx80_rounding_precision(user_rnd_prec, status);
+ return roundAndPackFloatx80(get_floatx80_rounding_precision(status),
+ 0,
0x8000, one_sig, 0, status);
} else {
fp0 = packFloatx80(0, aExp, aSig);
@@ -2792,7 +2794,7 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
fp1 = packFloatx80(0, 0x7FFB, one_sig);
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_mul(fp0, fp1, status);
@@ -2810,7 +2812,7 @@ floatx80 floatx80_cosh(floatx80 a, float_status *status)
fp1 = floatx80_div(fp1, fp0, status); /* 1/(2*EXP(|X|)) */
set_float_rounding_mode(user_rnd_mode, status);
- status->floatx80_rounding_precision = user_rnd_prec;
+ set_floatx80_rounding_precision(user_rnd_prec, status);
a = floatx80_add(fp0, fp1, status);
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
index fdb0cccf14..326a1201f3 100644
--- a/tests/fp/fp-test.c
+++ b/tests/fp/fp-test.c
@@ -996,7 +996,7 @@ void run_test(void)
verCases_roundingPrecision = 0;
slow_extF80_roundingPrecision = prec80;
- qsf.floatx80_rounding_precision = qsf_prec80;
+ set_floatx80_rounding_precision(qsf_prec80, &qsf);
if (attrs & FUNC_EFF_ROUNDINGPRECISION) {
verCases_roundingPrecision = prec80;
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 16/30] fpu: Use get_floatx80_behaviour everywhere
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (14 preceding siblings ...)
2026-05-22 18:26 ` [PULL 15/30] fpu: Use of {get, set}_floatx80_rounding_precision everywhere Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 17/30] fpu: Use get_float_2nan_prop_rule in partsN_pick_nan Richard Henderson
` (14 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat.h | 10 ++++++----
fpu/softfloat.c | 2 +-
fpu/softfloat-parts.c.inc | 4 ++--
fpu/softfloat-specialize.c.inc | 2 +-
4 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 4ae4ddc799..e08d1c374d 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -1018,7 +1018,7 @@ static inline bool floatx80_is_infinity(floatx80 a, float_status *status)
bool intbit = a.low >> 63;
if (!intbit &&
- !(status->floatx80_behaviour & floatx80_pseudo_inf_valid)) {
+ !(get_floatx80_behaviour(status) & floatx80_pseudo_inf_valid)) {
return false;
}
return (a.high & 0x7fff) == 0x7fff && !(a.low << 1);
@@ -1112,6 +1112,8 @@ static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
*----------------------------------------------------------------------------*/
static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
{
+ FloatX80Behaviour rule = get_floatx80_behaviour(s);
+
if ((a.low >> 63) || (a.high & 0x7fff) == 0) {
/* Anything with the Integer bit set or the exponent 0 is valid */
return false;
@@ -1119,12 +1121,12 @@ static inline bool floatx80_invalid_encoding(floatx80 a, float_status *s)
if ((a.high & 0x7fff) == 0x7fff) {
if (a.low) {
- return !(s->floatx80_behaviour & floatx80_pseudo_nan_valid);
+ return !(rule & floatx80_pseudo_nan_valid);
} else {
- return !(s->floatx80_behaviour & floatx80_pseudo_inf_valid);
+ return !(rule & floatx80_pseudo_inf_valid);
}
} else {
- return !(s->floatx80_behaviour & floatx80_unnormal_valid);
+ return !(rule & floatx80_unnormal_valid);
}
}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index d2a9f97089..f774ff278c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1578,7 +1578,7 @@ floatx80 floatx80_round_pack_canonical(FloatParts128 *p, float_status *s)
case float_class_inf:
/* x86 and m68k differ in the setting of the integer bit. */
- frac = s->floatx80_behaviour & floatx80_default_inf_int_bit_is_zero ?
+ frac = get_floatx80_behaviour(s) & floatx80_default_inf_int_bit_is_zero ?
0 : (1ULL << 63);
exp = fmt->exp_max;
break;
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 7311c3696e..fd3e79fd3e 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -213,7 +213,7 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
* how we uncanonicalize results.
*/
bool has_pseudo_denormals = fmt->has_explicit_bit &&
- (status->floatx80_behaviour & floatx80_pseudo_denormal_valid);
+ (get_floatx80_behaviour(status) & floatx80_pseudo_denormal_valid);
if (unlikely(p->exp == 0)) {
if (likely(fracN(eqz)(p))) {
@@ -420,7 +420,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
} else {
bool is_tiny = s->tininess_before_rounding || exp < 0;
bool has_pseudo_denormals = fmt->has_explicit_bit &&
- (s->floatx80_behaviour & floatx80_pseudo_denormal_valid);
+ (get_floatx80_behaviour(s) & floatx80_pseudo_denormal_valid);
if (!is_tiny) {
FloatPartsN discard;
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 0b527302a5..4b6c17e433 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -221,7 +221,7 @@ 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;
+ bool z = get_floatx80_behaviour(status) & floatx80_default_inf_int_bit_is_zero;
return packFloatx80(zSign, 0x7fff, z ? 0 : (1ULL << 63));
}
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 17/30] fpu: Use get_float_2nan_prop_rule in partsN_pick_nan
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (15 preceding siblings ...)
2026-05-22 18:26 ` [PULL 16/30] fpu: Use get_floatx80_behaviour everywhere Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 18/30] fpu: Use get_float_3nan_prop_rule in partsN_pick_nan_muladd Richard Henderson
` (13 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index fd3e79fd3e..f40a950b41 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -53,7 +53,7 @@ FloatPartsN partsN(pick_nan)(const FloatPartsN *a, const FloatPartsN *b,
return partsN(default_nan)(s);
}
- switch (s->float_2nan_prop_rule) {
+ switch (get_float_2nan_prop_rule(s)) {
case float_2nan_prop_s_ab:
if (have_snan) {
ret = is_snan(a->cls) ? a : b;
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 18/30] fpu: Use get_float_3nan_prop_rule in partsN_pick_nan_muladd
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (16 preceding siblings ...)
2026-05-22 18:26 ` [PULL 17/30] fpu: Use get_float_2nan_prop_rule in partsN_pick_nan Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 19/30] fpu: Use get_float_infzeronan_rule " Richard Henderson
` (12 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index f40a950b41..7781e16122 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -163,7 +163,7 @@ static FloatPartsN partsN(pick_nan_muladd)(const FloatPartsN *a,
ret = c;
} else {
const FloatPartsN *val[R_3NAN_1ST_MASK + 1] = { a, b, c };
- Float3NaNPropRule rule = s->float_3nan_prop_rule;
+ Float3NaNPropRule rule = get_float_3nan_prop_rule(s);
assert(rule != float_3nan_prop_none);
if (have_snan && (rule & R_3NAN_SNAN_MASK)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 19/30] fpu: Use get_float_infzeronan_rule in partsN_pick_nan_muladd
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (17 preceding siblings ...)
2026-05-22 18:26 ` [PULL 18/30] fpu: Use get_float_3nan_prop_rule in partsN_pick_nan_muladd Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 20/30] fpu: Use accessors for tininess_before_rounding Richard Henderson
` (11 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Deduplicate the uses to a local variable.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 7781e16122..1e92251761 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -122,14 +122,14 @@ static FloatPartsN partsN(pick_nan_muladd)(const FloatPartsN *a,
{
bool infzero = (ab_mask == float_cmask_infzero);
bool have_snan = (abc_mask & float_cmask_snan);
+ FloatInfZeroNaNRule izn_rule = get_float_infzeronan_rule(s);
const FloatPartsN *ret;
if (unlikely(have_snan)) {
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
}
- if (infzero &&
- !(s->float_infzeronan_rule & float_infzeronan_suppress_invalid)) {
+ if (infzero && !(izn_rule & float_infzeronan_suppress_invalid)) {
/* This is (0 * inf) + NaN or (inf * 0) + NaN */
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
}
@@ -147,7 +147,7 @@ static FloatPartsN partsN(pick_nan_muladd)(const FloatPartsN *a,
* Inf * 0 + NaN -- some implementations return the
* default NaN here, and some return the input NaN.
*/
- switch (s->float_infzeronan_rule & ~float_infzeronan_suppress_invalid) {
+ switch (izn_rule & ~float_infzeronan_suppress_invalid) {
case float_infzeronan_dnan_never:
break;
case float_infzeronan_dnan_always:
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 20/30] fpu: Use accessors for tininess_before_rounding
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (18 preceding siblings ...)
2026-05-22 18:26 ` [PULL 19/30] fpu: Use get_float_infzeronan_rule " Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 21/30] fpu: Use {get,set}_flush_to_zero everywhere Richard Henderson
` (10 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Rename get_float_detect_tininess to get_tininess_before_rounding
and move to softfloat.c, as there are no external users.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 5 -----
fpu/softfloat.c | 4 ++--
tests/fp/fp-test.c | 2 +-
fpu/softfloat-parts.c.inc | 2 +-
fpu/softfloat-specialize.c.inc | 5 +++++
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 95edd22842..395ce67abf 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -132,11 +132,6 @@ static inline void set_snan_rule(FloatSNaNRule val, float_status *status)
status->float_snan_rule = val;
}
-static inline bool get_float_detect_tininess(const float_status *status)
-{
- return status->tininess_before_rounding;
-}
-
static inline FloatRoundMode get_float_rounding_mode(const float_status *status)
{
return status->float_rounding_mode;
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index f774ff278c..c7c750f284 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -4923,7 +4923,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
float_raise(float_flag_output_denormal_flushed, status);
return packFloatx80(zSign, 0, 0);
}
- isTiny = status->tininess_before_rounding
+ isTiny = get_tininess_before_rounding(status)
|| (zExp < 0 )
|| (zSig0 <= zSig0 + roundIncrement);
shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
@@ -4997,7 +4997,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
return floatx80_default_inf(zSign, status);
}
if ( zExp <= 0 ) {
- isTiny = status->tininess_before_rounding
+ isTiny = get_tininess_before_rounding(status)
|| (zExp < 0)
|| !increment
|| (zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF));
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
index 326a1201f3..16ffd36e6f 100644
--- a/tests/fp/fp-test.c
+++ b/tests/fp/fp-test.c
@@ -1011,7 +1011,7 @@ void run_test(void)
verCases_tininessCode = 0;
slowfloat_detectTininess = tmode;
- qsf.tininess_before_rounding = sf_tininess_to_qemu(tmode);
+ set_float_detect_tininess(sf_tininess_to_qemu(tmode), &qsf);
if (attrs & FUNC_EFF_TININESSMODE ||
((attrs & FUNC_EFF_TININESSMODE_REDUCEDPREC) &&
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 1e92251761..1c726cb86e 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -418,7 +418,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
exp = 0;
fracN(clear)(p);
} else {
- bool is_tiny = s->tininess_before_rounding || exp < 0;
+ bool is_tiny = get_tininess_before_rounding(s) || exp < 0;
bool has_pseudo_denormals = fmt->has_explicit_bit &&
(get_floatx80_behaviour(s) & floatx80_pseudo_denormal_valid);
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 4b6c17e433..0b62b0e907 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -79,6 +79,11 @@ this code that are retained.
* version 2 or later. See the COPYING file in the top-level directory.
*/
+static inline bool get_tininess_before_rounding(const float_status *status)
+{
+ return status->tininess_before_rounding;
+}
+
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 21/30] fpu: Use {get,set}_flush_to_zero everywhere
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (19 preceding siblings ...)
2026-05-22 18:26 ` [PULL 20/30] fpu: Use accessors for tininess_before_rounding Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 22/30] fpu: Use accessors for ftz_before_rounding Richard Henderson
` (9 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat.c | 2 +-
target/arm/tcg/vfp_helper.c | 6 +++---
tests/fp/fp-bench.c | 2 +-
fpu/softfloat-parts.c.inc | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c7c750f284..dcae5b3be2 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -4919,7 +4919,7 @@ floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
goto overflow;
}
if ( zExp <= 0 ) {
- if (status->flush_to_zero) {
+ if (get_flush_to_zero(status)) {
float_raise(float_flag_output_denormal_flushed, status);
return packFloatx80(zSign, 0, 0);
}
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
index 5839e82449..495ce8a329 100644
--- a/target/arm/tcg/vfp_helper.c
+++ b/target/arm/tcg/vfp_helper.c
@@ -711,7 +711,7 @@ uint32_t HELPER(recpe_f16)(uint32_t input, float_status *fpst)
} else {
return float16_set_sign(float16_maxnorm, f16_sign);
}
- } else if (f16_exp >= 29 && fpst->flush_to_zero) {
+ } else if (f16_exp >= 29 && get_flush_to_zero(fpst)) {
float_raise(float_flag_underflow, fpst);
return float16_set_sign(float16_zero, float16_is_neg(f16));
}
@@ -764,7 +764,7 @@ static float32 do_recpe_f32(float32 input, float_status *fpst, bool rpres)
} else {
return float32_set_sign(float32_maxnorm, f32_sign);
}
- } else if (f32_exp >= 253 && fpst->flush_to_zero) {
+ } else if (f32_exp >= 253 && get_flush_to_zero(fpst)) {
float_raise(float_flag_underflow, fpst);
return float32_set_sign(float32_zero, float32_is_neg(f32));
}
@@ -823,7 +823,7 @@ float64 HELPER(recpe_f64)(float64 input, float_status *fpst)
} else {
return float64_set_sign(float64_maxnorm, f64_sign);
}
- } else if (f64_exp >= 2045 && fpst->flush_to_zero) {
+ } else if (f64_exp >= 2045 && get_flush_to_zero(fpst)) {
float_raise(float_flag_underflow, fpst);
return float64_set_sign(float64_zero, float64_is_neg(f64));
}
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
index 2b6f66817e..ccc561b578 100644
--- a/tests/fp/fp-bench.c
+++ b/tests/fp/fp-bench.c
@@ -675,7 +675,7 @@ static void parse_args(int argc, char *argv[])
soft_status.flush_inputs_to_zero = 1;
break;
case 'Z':
- soft_status.flush_to_zero = 1;
+ set_flush_to_zero(true, &soft_status);
break;
}
}
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 1c726cb86e..9e823a3ee9 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -411,7 +411,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
p->frac_lo &= ~round_mask;
}
fracN(shr)(p, frac_shift);
- } else if (s->flush_to_zero &&
+ } else if (get_flush_to_zero(s) &&
s->ftz_detection == float_ftz_before_rounding) {
flags |= float_flag_output_denormal_flushed;
p->cls = float_class_zero;
@@ -462,7 +462,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
fracN(shr)(p, frac_shift);
if (is_tiny) {
- if (s->flush_to_zero) {
+ if (get_flush_to_zero(s)) {
assert(s->ftz_detection == float_ftz_after_rounding);
flags |= float_flag_output_denormal_flushed;
p->cls = float_class_zero;
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 22/30] fpu: Use accessors for ftz_before_rounding
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (20 preceding siblings ...)
2026-05-22 18:26 ` [PULL 21/30] fpu: Use {get,set}_flush_to_zero everywhere Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 23/30] fpu: Use {get,set}_flush_inputs_to_zero everywhere Richard Henderson
` (8 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Drop FloatFTZDetection and use #defines, like we do for
tininess_before_rounding. Rename get_float_ftz_detection
to get_ftz_before_rounding and move to softfloat.c, as
there are no external users.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 10 ++--------
include/fpu/softfloat-types.h | 8 +++-----
fpu/softfloat-parts.c.inc | 5 ++---
fpu/softfloat-specialize.c.inc | 5 +++++
4 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 395ce67abf..d36e3a24b1 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -116,10 +116,9 @@ static inline void set_flush_inputs_to_zero(bool val, float_status *status)
status->flush_inputs_to_zero = val;
}
-static inline void set_float_ftz_detection(FloatFTZDetection d,
- float_status *status)
+static inline void set_float_ftz_detection(bool val, float_status *status)
{
- status->ftz_detection = d;
+ status->ftz_before_rounding = val;
}
static inline void set_default_nan_mode(bool val, float_status *status)
@@ -198,9 +197,4 @@ static inline FloatSNaNRule get_snan_rule(float_status *status)
return status->float_snan_rule;
}
-static inline FloatFTZDetection get_float_ftz_detection(const float_status *status)
-{
- return status->ftz_detection;
-}
-
#endif /* SOFTFLOAT_HELPERS_H */
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index cf7093fa86..67b7f38aef 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -341,10 +341,8 @@ typedef enum __attribute__((__packed__)) {
* configure it matches the default for tininess_before_rounding
* (i.e. "after rounding").
*/
-typedef enum __attribute__((__packed__)) {
- float_ftz_after_rounding = 0,
- float_ftz_before_rounding = 1,
-} FloatFTZDetection;
+#define float_ftz_after_rounding false
+#define float_ftz_before_rounding true
/*
* floatx80 is primarily used by x86 and m68k, and there are
@@ -416,7 +414,7 @@ typedef struct float_status {
/* should denormalised results go to zero and set output_denormal_flushed? */
bool flush_to_zero;
/* do we detect and flush denormal results before or after rounding? */
- FloatFTZDetection ftz_detection;
+ bool ftz_before_rounding;
/* should denormalised inputs go to zero and set input_denormal_flushed? */
bool flush_inputs_to_zero;
bool default_nan_mode;
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 9e823a3ee9..0e5311b50f 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -411,8 +411,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
p->frac_lo &= ~round_mask;
}
fracN(shr)(p, frac_shift);
- } else if (get_flush_to_zero(s) &&
- s->ftz_detection == float_ftz_before_rounding) {
+ } else if (get_flush_to_zero(s) && get_ftz_before_rounding(s)) {
flags |= float_flag_output_denormal_flushed;
p->cls = float_class_zero;
exp = 0;
@@ -463,7 +462,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
if (is_tiny) {
if (get_flush_to_zero(s)) {
- assert(s->ftz_detection == float_ftz_after_rounding);
+ assert(!get_ftz_before_rounding(s));
flags |= float_flag_output_denormal_flushed;
p->cls = float_class_zero;
exp = 0;
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index 0b62b0e907..bd6984282f 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -84,6 +84,11 @@ static inline bool get_tininess_before_rounding(const float_status *status)
return status->tininess_before_rounding;
}
+static inline bool get_ftz_before_rounding(const float_status *status)
+{
+ return status->ftz_before_rounding;
+}
+
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 23/30] fpu: Use {get,set}_flush_inputs_to_zero everywhere
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (21 preceding siblings ...)
2026-05-22 18:26 ` [PULL 22/30] fpu: Use accessors for ftz_before_rounding Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 24/30] fpu: Use get_default_nan_mode everywhere Richard Henderson
` (7 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat.c | 14 +++++++-------
target/alpha/fpu_helper.c | 2 +-
target/alpha/helper.c | 3 ++-
tests/fp/fp-bench.c | 2 +-
fpu/softfloat-parts.c.inc | 2 +-
5 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index dcae5b3be2..be6b02d866 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -141,7 +141,7 @@ GEN_INPUT_FLUSH__NOCHECK(float64_input_flush__nocheck, float64)
#define GEN_INPUT_FLUSH1(name, soft_t) \
static inline void name(soft_t *a, float_status *s) \
{ \
- if (likely(!s->flush_inputs_to_zero)) { \
+ if (likely(!get_flush_inputs_to_zero(s))) { \
return; \
} \
soft_t ## _input_flush__nocheck(a, s); \
@@ -154,7 +154,7 @@ GEN_INPUT_FLUSH1(float64_input_flush1, float64)
#define GEN_INPUT_FLUSH2(name, soft_t) \
static inline void name(soft_t *a, soft_t *b, float_status *s) \
{ \
- if (likely(!s->flush_inputs_to_zero)) { \
+ if (likely(!get_flush_inputs_to_zero(s))) { \
return; \
} \
soft_t ## _input_flush__nocheck(a, s); \
@@ -168,7 +168,7 @@ GEN_INPUT_FLUSH2(float64_input_flush2, float64)
#define GEN_INPUT_FLUSH3(name, soft_t) \
static inline void name(soft_t *a, soft_t *b, soft_t *c, float_status *s) \
{ \
- if (likely(!s->flush_inputs_to_zero)) { \
+ if (likely(!get_flush_inputs_to_zero(s))) { \
return; \
} \
soft_t ## _input_flush__nocheck(a, s); \
@@ -4764,7 +4764,7 @@ static bool parts_squash_denormal(FloatParts64 p, float_status *status)
float16 float16_squash_input_denormal(float16 a, float_status *status)
{
- if (status->flush_inputs_to_zero) {
+ if (get_flush_inputs_to_zero(status)) {
FloatParts64 p = unpack_raw64(&float16_params, a);
if (parts_squash_denormal(p, status)) {
@@ -4776,7 +4776,7 @@ float16 float16_squash_input_denormal(float16 a, float_status *status)
float32 float32_squash_input_denormal(float32 a, float_status *status)
{
- if (status->flush_inputs_to_zero) {
+ if (get_flush_inputs_to_zero(status)) {
FloatParts64 p = unpack_raw64(&float32_params, a);
if (parts_squash_denormal(p, status)) {
@@ -4788,7 +4788,7 @@ float32 float32_squash_input_denormal(float32 a, float_status *status)
float64 float64_squash_input_denormal(float64 a, float_status *status)
{
- if (status->flush_inputs_to_zero) {
+ if (get_flush_inputs_to_zero(status)) {
FloatParts64 p = unpack_raw64(&float64_params, a);
if (parts_squash_denormal(p, status)) {
@@ -4800,7 +4800,7 @@ float64 float64_squash_input_denormal(float64 a, float_status *status)
bfloat16 bfloat16_squash_input_denormal(bfloat16 a, float_status *status)
{
- if (status->flush_inputs_to_zero) {
+ if (get_flush_inputs_to_zero(status)) {
FloatParts64 p = unpack_raw64(&bfloat16_params, a);
if (parts_squash_denormal(p, status)) {
diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c
index 0ced53c54e..5b7e4bd5eb 100644
--- a/target/alpha/fpu_helper.c
+++ b/target/alpha/fpu_helper.c
@@ -151,7 +151,7 @@ void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
void helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
{
if (unlikely(2 * val - 1 < 0x1fffffffffffffull)
- && !env->fp_status.flush_inputs_to_zero) {
+ && !get_flush_inputs_to_zero(&env->fp_status)) {
arith_excp(env, GETPC(), EXC_M_INV | EXC_M_SWC, 0);
}
}
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index 33fed0c746..2abf07c191 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -24,6 +24,7 @@
#include "exec/page-protection.h"
#include "exec/target_page.h"
#include "fpu/softfloat-types.h"
+#include "fpu/softfloat-helpers.h"
#include "exec/helper-proto.h"
#include "qemu/qemu-print.h"
#include "system/memory.h"
@@ -80,7 +81,7 @@ void cpu_alpha_store_fpcr(CPUAlphaState *env, uint64_t val)
env->fpcr_exc_enable = ~t & FPCR_STATUS_MASK;
env->fpcr_dyn_round = rm_map[(fpcr & FPCR_DYN_MASK) >> FPCR_DYN_SHIFT];
- env->fp_status.flush_inputs_to_zero = (fpcr & FPCR_DNZ) != 0;
+ set_flush_inputs_to_zero(fpcr & FPCR_DNZ, &env->fp_status);
t = (fpcr & FPCR_UNFD) && (fpcr & FPCR_UNDZ);
#ifdef CONFIG_USER_ONLY
diff --git a/tests/fp/fp-bench.c b/tests/fp/fp-bench.c
index ccc561b578..c53d6e4b34 100644
--- a/tests/fp/fp-bench.c
+++ b/tests/fp/fp-bench.c
@@ -672,7 +672,7 @@ static void parse_args(int argc, char *argv[])
tester = val;
break;
case 'z':
- soft_status.flush_inputs_to_zero = 1;
+ set_flush_inputs_to_zero(true, &soft_status);
break;
case 'Z':
set_flush_to_zero(true, &soft_status);
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 0e5311b50f..6a67e6af2c 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -218,7 +218,7 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
if (unlikely(p->exp == 0)) {
if (likely(fracN(eqz)(p))) {
p->cls = float_class_zero;
- } else if (status->flush_inputs_to_zero) {
+ } else if (get_flush_inputs_to_zero(status)) {
float_raise(float_flag_input_denormal_flushed, status);
p->cls = float_class_zero;
fracN(clear)(p);
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 24/30] fpu: Use get_default_nan_mode everywhere
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (22 preceding siblings ...)
2026-05-22 18:26 ` [PULL 23/30] fpu: Use {get,set}_flush_inputs_to_zero everywhere Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 25/30] fpu: Use get_float_default_nan_pattern in partsN_default_nan Richard Henderson
` (6 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/helper-a64.c | 12 ++++++------
target/arm/tcg/vfp_helper.c | 24 ++++++++++++------------
target/m68k/softfloat.c | 2 +-
fpu/softfloat-parts.c.inc | 8 ++++----
4 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index dd1f9c6dc6..6505ee3c94 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -273,11 +273,11 @@ uint32_t HELPER(frecpx_f16)(uint32_t a, float_status *fpst)
float16 nan = a;
if (float16_is_signaling_nan(a, fpst)) {
float_raise(float_flag_invalid, fpst);
- if (!fpst->default_nan_mode) {
+ if (!get_default_nan_mode(fpst)) {
nan = float16_silence_nan(a, fpst);
}
}
- if (fpst->default_nan_mode) {
+ if (get_default_nan_mode(fpst)) {
nan = float16_default_nan(fpst);
}
return nan;
@@ -305,11 +305,11 @@ float32 HELPER(frecpx_f32)(float32 a, float_status *fpst)
float32 nan = a;
if (float32_is_signaling_nan(a, fpst)) {
float_raise(float_flag_invalid, fpst);
- if (!fpst->default_nan_mode) {
+ if (!get_default_nan_mode(fpst)) {
nan = float32_silence_nan(a, fpst);
}
}
- if (fpst->default_nan_mode) {
+ if (get_default_nan_mode(fpst)) {
nan = float32_default_nan(fpst);
}
return nan;
@@ -337,11 +337,11 @@ float64 HELPER(frecpx_f64)(float64 a, float_status *fpst)
float64 nan = a;
if (float64_is_signaling_nan(a, fpst)) {
float_raise(float_flag_invalid, fpst);
- if (!fpst->default_nan_mode) {
+ if (!get_default_nan_mode(fpst)) {
nan = float64_silence_nan(a, fpst);
}
}
- if (fpst->default_nan_mode) {
+ if (get_default_nan_mode(fpst)) {
nan = float64_default_nan(fpst);
}
return nan;
diff --git a/target/arm/tcg/vfp_helper.c b/target/arm/tcg/vfp_helper.c
index 495ce8a329..8d3f6e3a2e 100644
--- a/target/arm/tcg/vfp_helper.c
+++ b/target/arm/tcg/vfp_helper.c
@@ -690,11 +690,11 @@ uint32_t HELPER(recpe_f16)(uint32_t input, float_status *fpst)
float16 nan = f16;
if (float16_is_signaling_nan(f16, fpst)) {
float_raise(float_flag_invalid, fpst);
- if (!fpst->default_nan_mode) {
+ if (!get_default_nan_mode(fpst)) {
nan = float16_silence_nan(f16, fpst);
}
}
- if (fpst->default_nan_mode) {
+ if (get_default_nan_mode(fpst)) {
nan = float16_default_nan(fpst);
}
return nan;
@@ -743,11 +743,11 @@ static float32 do_recpe_f32(float32 input, float_status *fpst, bool rpres)
float32 nan = f32;
if (float32_is_signaling_nan(f32, fpst)) {
float_raise(float_flag_invalid, fpst);
- if (!fpst->default_nan_mode) {
+ if (!get_default_nan_mode(fpst)) {
nan = float32_silence_nan(f32, fpst);
}
}
- if (fpst->default_nan_mode) {
+ if (get_default_nan_mode(fpst)) {
nan = float32_default_nan(fpst);
}
return nan;
@@ -802,11 +802,11 @@ float64 HELPER(recpe_f64)(float64 input, float_status *fpst)
float64 nan = f64;
if (float64_is_signaling_nan(f64, fpst)) {
float_raise(float_flag_invalid, fpst);
- if (!fpst->default_nan_mode) {
+ if (!get_default_nan_mode(fpst)) {
nan = float64_silence_nan(f64, fpst);
}
}
- if (fpst->default_nan_mode) {
+ if (get_default_nan_mode(fpst)) {
nan = float64_default_nan(fpst);
}
return nan;
@@ -945,11 +945,11 @@ uint32_t HELPER(rsqrte_f16)(uint32_t input, float_status *s)
float16 nan = f16;
if (float16_is_signaling_nan(f16, s)) {
float_raise(float_flag_invalid, s);
- if (!s->default_nan_mode) {
+ if (!get_default_nan_mode(s)) {
nan = float16_silence_nan(f16, s);
}
}
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
nan = float16_default_nan(s);
}
return nan;
@@ -994,11 +994,11 @@ static float32 do_rsqrte_f32(float32 input, float_status *s, bool rpres)
float32 nan = f32;
if (float32_is_signaling_nan(f32, s)) {
float_raise(float_flag_invalid, s);
- if (!s->default_nan_mode) {
+ if (!get_default_nan_mode(s)) {
nan = float32_silence_nan(f32, s);
}
}
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
nan = float32_default_nan(s);
}
return nan;
@@ -1056,11 +1056,11 @@ float64 HELPER(rsqrte_f64)(float64 input, float_status *s)
float64 nan = f64;
if (float64_is_signaling_nan(f64, s)) {
float_raise(float_flag_invalid, s);
- if (!s->default_nan_mode) {
+ if (!get_default_nan_mode(s)) {
nan = float64_silence_nan(f64, s);
}
}
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
nan = float64_default_nan(s);
}
return nan;
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index f5d683bcc5..99c2dcbe8c 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -35,7 +35,7 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status)
a = floatx80_silence_nan(a, status);
}
- if (status->default_nan_mode) {
+ if (get_default_nan_mode(status)) {
return floatx80_default_nan(status);
}
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 6a67e6af2c..bef47a932d 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -20,14 +20,14 @@ FloatPartsN partsN(return_nan)(const FloatPartsN *a, float_status *s)
switch (a->cls) {
case float_class_snan:
float_raise(float_flag_invalid | float_flag_invalid_snan, s);
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
return partsN(default_nan)(s);
} else {
return partsN(silence_nan)(a, s);
}
break;
case float_class_qnan:
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
return partsN(default_nan)(s);
}
break;
@@ -49,7 +49,7 @@ FloatPartsN partsN(pick_nan)(const FloatPartsN *a, const FloatPartsN *b,
have_snan = true;
}
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
return partsN(default_nan)(s);
}
@@ -134,7 +134,7 @@ static FloatPartsN partsN(pick_nan_muladd)(const FloatPartsN *a,
float_raise(float_flag_invalid | float_flag_invalid_imz, s);
}
- if (s->default_nan_mode) {
+ if (get_default_nan_mode(s)) {
/*
* We guarantee not to require the target to tell us how to
* pick a NaN if we're always returning the default NaN.
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 25/30] fpu: Use get_float_default_nan_pattern in partsN_default_nan
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (23 preceding siblings ...)
2026-05-22 18:26 ` [PULL 24/30] fpu: Use get_default_nan_mode everywhere Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 26/30] fpu: Add accessors for rebias_{underflow,overflow} Richard Henderson
` (5 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Move get_float_default_nan_pattern to softfloat-specialize.c.inc,
since there are no external users.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 5 -----
fpu/softfloat-specialize.c.inc | 7 ++++++-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index d36e3a24b1..49e04ffee9 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -172,11 +172,6 @@ get_float_infzeronan_rule(const float_status *status)
return status->float_infzeronan_rule;
}
-static inline uint8_t get_float_default_nan_pattern(const float_status *status)
-{
- return status->default_nan_pattern;
-}
-
static inline bool get_flush_to_zero(const float_status *status)
{
return status->flush_to_zero;
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index bd6984282f..c1ed661f5e 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -89,6 +89,11 @@ static inline bool get_ftz_before_rounding(const float_status *status)
return status->ftz_before_rounding;
}
+static inline uint8_t get_float_default_nan_pattern(const float_status *status)
+{
+ return status->default_nan_pattern;
+}
+
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
@@ -121,7 +126,7 @@ FloatParts64 parts64_default_nan(float_status *status)
{
bool sign = 0;
uint64_t frac;
- uint8_t dnan_pattern = status->default_nan_pattern;
+ uint8_t dnan_pattern = get_float_default_nan_pattern(status);
assert(dnan_pattern != 0);
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 26/30] fpu: Add accessors for rebias_{underflow,overflow}
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (24 preceding siblings ...)
2026-05-22 18:26 ` [PULL 25/30] fpu: Use get_float_default_nan_pattern in partsN_default_nan Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 27/30] fpu: Reorg float_status Richard Henderson
` (4 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 10 ++++++++++
target/ppc/cpu.c | 4 ++--
fpu/softfloat-parts.c.inc | 4 ++--
fpu/softfloat-specialize.c.inc | 10 ++++++++++
4 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 49e04ffee9..4791a7fc87 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -131,6 +131,16 @@ static inline void set_snan_rule(FloatSNaNRule val, float_status *status)
status->float_snan_rule = val;
}
+static inline void set_float_rebias_overflow(bool val, float_status *status)
+{
+ status->rebias_overflow = val;
+}
+
+static inline void set_float_rebias_underflow(bool val, float_status *status)
+{
+ status->rebias_underflow = val;
+}
+
static inline FloatRoundMode get_float_rounding_mode(const float_status *status)
{
return status->float_rounding_mode;
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index 4d8faaddee..41edb18643 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -248,8 +248,8 @@ void ppc_store_fpscr(CPUPPCState *env, target_ulong val)
val |= FP_FEX;
}
env->fpscr = val;
- env->fp_status.rebias_overflow = (FP_OE & env->fpscr) ? true : false;
- env->fp_status.rebias_underflow = (FP_UE & env->fpscr) ? true : false;
+ set_float_rebias_overflow(FP_OE & env->fpscr, &env->fp_status);
+ set_float_rebias_underflow(FP_UE & env->fpscr, &env->fp_status);
if (tcg_enabled()) {
fpscr_set_rounding_mode(env);
}
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index bef47a932d..184614ea47 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -358,7 +358,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
switch (fmt->exp_max_kind) {
case float_expmax_ieee:
flags |= float_flag_overflow;
- if (s->rebias_overflow) {
+ if (get_float_rebias_overflow(s)) {
exp -= fmt->exp_re_bias;
} else if (overflow_norm) {
flags |= float_flag_inexact;
@@ -398,7 +398,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
}
}
fracN(shr)(p, frac_shift);
- } else if (unlikely(s->rebias_underflow)) {
+ } else if (unlikely(get_float_rebias_underflow(s))) {
flags |= float_flag_underflow;
exp += fmt->exp_re_bias;
if (p->frac_lo & round_mask) {
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index c1ed661f5e..b97c971ae6 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -94,6 +94,16 @@ static inline uint8_t get_float_default_nan_pattern(const float_status *status)
return status->default_nan_pattern;
}
+static inline bool get_float_rebias_overflow(const float_status *status)
+{
+ return status->rebias_overflow;
+}
+
+static inline bool get_float_rebias_underflow(const float_status *status)
+{
+ return status->rebias_underflow;
+}
+
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 27/30] fpu: Reorg float_status
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (25 preceding siblings ...)
2026-05-22 18:26 ` [PULL 26/30] fpu: Add accessors for rebias_{underflow,overflow} Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 28/30] fpu: Introduce float_status.e4m3_nan_is_snan Richard Henderson
` (3 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Use bitfields to compress float_status from 18 bytes down to 8 bytes.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-types.h | 53 ++++++++++++++++++++++-------------
1 file changed, 33 insertions(+), 20 deletions(-)
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index 67b7f38aef..c5a6684763 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -327,7 +327,7 @@ typedef enum __attribute__((__packed__)) {
* This is a flag which can be ORed in with any of the above
* DNaN behaviour options.
*/
- float_infzeronan_suppress_invalid = (1 << 7),
+ float_infzeronan_suppress_invalid = (1 << 2),
} FloatInfZeroNaNRule;
/*
@@ -402,22 +402,39 @@ typedef enum __attribute__((__packed__)) {
*/
typedef struct float_status {
- FloatExceptionFlags 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;
- FloatSNaNRule float_snan_rule;
- bool tininess_before_rounding;
+ FloatExceptionFlags float_exception_flags : 16;
+
+ /*
+ * Floating point status controls.
+ * Items that, in general, may be updated by writes to an architectural
+ * floating point control register.
+ */
+ FloatRoundMode float_rounding_mode : 3;
+ FloatX80RoundPrec floatx80_rounding_precision : 2;
/* should denormalised results go to zero and set output_denormal_flushed? */
- bool flush_to_zero;
- /* do we detect and flush denormal results before or after rounding? */
- bool ftz_before_rounding;
+ bool flush_to_zero : 1;
/* should denormalised inputs go to zero and set input_denormal_flushed? */
- bool flush_inputs_to_zero;
- bool default_nan_mode;
+ bool flush_inputs_to_zero : 1;
+ /* should default nans be produced instead of propagating an input nan? */
+ bool default_nan_mode : 1;
+ /* should overflowed results subtract re_bias to its exponent? */
+ bool rebias_overflow : 1;
+ /* should underflowed results add re_bias to its exponent? */
+ bool rebias_underflow : 1;
+
+ /*
+ * Floating point behaviour controls.
+ * Items that, in general, will be set at cpu realization because
+ * the behaviour is baked into the specific hardware implementation.
+ */
+ bool tininess_before_rounding : 1;
+ /* do we detect and flush denormal results before or after rounding? */
+ bool ftz_before_rounding : 1;
+ FloatSNaNRule float_snan_rule : 2;
+ Float2NaNPropRule float_2nan_prop_rule : 3;
+ Float3NaNPropRule float_3nan_prop_rule : 7;
+ FloatInfZeroNaNRule float_infzeronan_rule: 3;
+ FloatX80Behaviour floatx80_behaviour : 5;
/*
* The pattern to use for the default NaN. Here the high bit specifies
* the default NaN's sign bit, and bits 6..0 specify the high bits of the
@@ -427,11 +444,7 @@ typedef struct float_status {
* this to the correct non-zero value, or we will assert when trying to
* create a default NaN.
*/
- uint8_t default_nan_pattern;
- /* should overflowed results subtract re_bias to its exponent? */
- bool rebias_overflow;
- /* should underflowed results add re_bias to its exponent? */
- bool rebias_underflow;
+ unsigned default_nan_pattern : 8;
} float_status;
#endif /* SOFTFLOAT_TYPES_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 28/30] fpu: Introduce float_status.e4m3_nan_is_snan
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (26 preceding siblings ...)
2026-05-22 18:26 ` [PULL 27/30] fpu: Reorg float_status Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 29/30] fpu: Fix NaN encoding for E4M3 in parts64_uncanon Richard Henderson
` (2 subsequent siblings)
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
Introduce a separate control from float_snan_rule
that applies only to the OCP E4M3 format.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-helpers.h | 5 +++++
include/fpu/softfloat-types.h | 5 +++++
fpu/softfloat-parts.c.inc | 2 +-
fpu/softfloat-specialize.c.inc | 5 +++++
4 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index 4791a7fc87..8df0273132 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -131,6 +131,11 @@ static inline void set_snan_rule(FloatSNaNRule val, float_status *status)
status->float_snan_rule = val;
}
+static inline void set_float_e4m3_nan_is_snan(bool val, float_status *status)
+{
+ status->e4m3_nan_is_snan = val;
+}
+
static inline void set_float_rebias_overflow(bool val, float_status *status)
{
status->rebias_overflow = val;
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index c5a6684763..d7f5303a6b 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -431,6 +431,11 @@ typedef struct float_status {
/* do we detect and flush denormal results before or after rounding? */
bool ftz_before_rounding : 1;
FloatSNaNRule float_snan_rule : 2;
+ /*
+ * Overriding float_snan_rule, is the single NaN representation for
+ * the OCP E4M3 format an SNaN or QNaN?
+ */
+ bool e4m3_nan_is_snan : 1;
Float2NaNPropRule float_2nan_prop_rule : 3;
Float3NaNPropRule float_3nan_prop_rule : 7;
FloatInfZeroNaNRule float_infzeronan_rule: 3;
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 184614ea47..559e40d196 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -246,7 +246,7 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
case float_expmax_e4m3:
if (p->frac_hi == 0b111) {
fracN(shl)(p, fmt->frac_shift);
- p->cls = (parts_is_snan_frac(p->frac_hi, status)
+ p->cls = (get_float_e4m3_nan_is_snan(status)
? float_class_snan : float_class_qnan);
return;
}
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
index b97c971ae6..8b765ef623 100644
--- a/fpu/softfloat-specialize.c.inc
+++ b/fpu/softfloat-specialize.c.inc
@@ -104,6 +104,11 @@ static inline bool get_float_rebias_underflow(const float_status *status)
return status->rebias_underflow;
}
+static inline bool get_float_e4m3_nan_is_snan(const float_status *status)
+{
+ return status->e4m3_nan_is_snan;
+}
+
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 29/30] fpu: Fix NaN encoding for E4M3 in parts64_uncanon
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (27 preceding siblings ...)
2026-05-22 18:26 ` [PULL 28/30] fpu: Introduce float_status.e4m3_nan_is_snan Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-22 18:26 ` [PULL 30/30] fpu: Export floatN_minmax Richard Henderson
2026-05-24 19:14 ` [PULL 00/30] fpu patch queue Stefan Hajnoczi
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell
There is only one NaN fractional encoding for E4M3. Retain the
incoming sign, but force the outgoing fraction to the unique value.
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat.c | 2 ++
fpu/softfloat-parts.c.inc | 28 ++++++++++++++++++++++++----
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index be6b02d866..2c3bf01213 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -499,6 +499,8 @@ const FloatFmt float8_e4m3_params = {
/* 110 << frac_shift, with the implicit bit set */
#define E4M3_NORMAL_FRAC_MAX 0xe000000000000000ull
+/* 111 << frac_shift, no implicit bit */
+#define E4M3_NAN_FRAC 0x7000000000000000ull
const FloatFmt float8_e5m2_params = {
FLOAT_PARAMS(5, 2)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 559e40d196..d0064f5d22 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -278,11 +278,16 @@ static void partsN(uncanon_e4m3_overflow)(FloatPartsN *p, float_status *s,
const FloatFmt *fmt, bool saturate)
{
assert(N == 64);
+ p->exp = fmt->exp_max;
if (saturate) {
- p->exp = fmt->exp_max;
p->frac_hi = E4M3_NORMAL_FRAC_MAX;
} else {
- *p = partsN(default_nan)(s);
+ /*
+ * The class isn't actually used after this point in uncanon,
+ * but for clarity while debugging, don't leave it set to normal.
+ */
+ p->cls = float_class_qnan;
+ p->frac_hi = E4M3_NAN_FRAC;
}
}
@@ -507,9 +512,24 @@ static void partsN(uncanon)(FloatPartsN *p, float_status *s,
return;
case float_class_qnan:
case float_class_snan:
- assert(fmt->exp_max_kind != float_expmax_normal);
p->exp = fmt->exp_max;
- fracN(shr)(p, fmt->frac_shift);
+ switch (fmt->exp_max_kind) {
+ case float_expmax_e4m3:
+ /*
+ * There is only one NaN encoding for E4M3, and with a
+ * conversion from another format, the input NaN fraction
+ * may not apply.
+ */
+ assert(N == 64);
+ p->frac_hi = E4M3_NAN_FRAC;
+ /* fall through */
+ case float_expmax_ieee:
+ fracN(shr)(p, fmt->frac_shift);
+ break;
+ case float_expmax_normal:
+ default:
+ g_assert_not_reached();
+ }
return;
default:
break;
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* [PULL 30/30] fpu: Export floatN_minmax
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (28 preceding siblings ...)
2026-05-22 18:26 ` [PULL 29/30] fpu: Fix NaN encoding for E4M3 in parts64_uncanon Richard Henderson
@ 2026-05-22 18:26 ` Richard Henderson
2026-05-24 19:14 ` [PULL 00/30] fpu patch queue Stefan Hajnoczi
30 siblings, 0 replies; 32+ messages in thread
From: Richard Henderson @ 2026-05-22 18:26 UTC (permalink / raw)
To: qemu-devel; +Cc: Philippe Mathieu-Daudé
Allow target access to routines using the minmax flags.
Make the existing min/max wrappers inline.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat.h | 93 ++++++++++++++++++++++-----------------
fpu/softfloat.c | 50 +++------------------
fpu/softfloat-parts.c.inc | 8 ++--
3 files changed, 62 insertions(+), 89 deletions(-)
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index e08d1c374d..d48fc6b043 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -132,6 +132,25 @@ enum {
float_muladd_suppress_add_product_zero = 8,
};
+/*----------------------------------------------------------------------------
+| Options to indicate which negations to perform in float*_minmax()
+*----------------------------------------------------------------------------*/
+
+/* Flags for parts_minmax. */
+enum {
+ /* Set for minimum; clear for maximum. */
+ float_minmax_ismin = 1,
+ /* Set for the IEEE 754-2008 minNum() and maxNum() operations. */
+ float_minmax_isnum = 2,
+ /* Set for the IEEE 754-2008 minNumMag() and minNumMag() operations. */
+ float_minmax_ismag = 4,
+ /*
+ * Set for the IEEE 754-2019 minimumNumber() and maximumNumber()
+ * operations.
+ */
+ float_minmax_isnumber = 8,
+};
+
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
@@ -258,14 +277,7 @@ float16 float16_muladd_scalbn(float16, float16, float16,
int, int, float_status *status);
float16 float16_div(float16, float16, float_status *status);
float16 float16_scalbn(float16, int, float_status *status);
-float16 float16_min(float16, float16, float_status *status);
-float16 float16_max(float16, float16, float_status *status);
-float16 float16_minnum(float16, float16, float_status *status);
-float16 float16_maxnum(float16, float16, float_status *status);
-float16 float16_minnummag(float16, float16, float_status *status);
-float16 float16_maxnummag(float16, float16, float_status *status);
-float16 float16_minimum_number(float16, float16, float_status *status);
-float16 float16_maximum_number(float16, float16, float_status *status);
+float16 float16_minmax(float16, float16, float_status *status, int flags);
float16 float16_sqrt(float16, float_status *status);
FloatRelation float16_compare(float16, float16, float_status *status);
FloatRelation float16_compare_quiet(float16, float16, float_status *status);
@@ -451,14 +463,7 @@ bfloat16 bfloat16_div(bfloat16, bfloat16, float_status *status);
bfloat16 bfloat16_muladd(bfloat16, bfloat16, bfloat16, int,
float_status *status);
float16 bfloat16_scalbn(bfloat16, int, float_status *status);
-bfloat16 bfloat16_min(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_max(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_minnum(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_maxnum(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_minnummag(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_maxnummag(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_minimum_number(bfloat16, bfloat16, float_status *status);
-bfloat16 bfloat16_maximum_number(bfloat16, bfloat16, float_status *status);
+bfloat16 bfloat16_minmax(bfloat16, bfloat16, float_status *status, int flags);
bfloat16 bfloat16_sqrt(bfloat16, float_status *status);
FloatRelation bfloat16_compare(bfloat16, bfloat16, float_status *status);
FloatRelation bfloat16_compare_quiet(bfloat16, bfloat16, float_status *status);
@@ -622,14 +627,7 @@ float32 float32_exp2(float32, float_status *status);
float32 float32_log2(float32, float_status *status);
FloatRelation float32_compare(float32, float32, float_status *status);
FloatRelation float32_compare_quiet(float32, float32, float_status *status);
-float32 float32_min(float32, float32, float_status *status);
-float32 float32_max(float32, float32, float_status *status);
-float32 float32_minnum(float32, float32, float_status *status);
-float32 float32_maxnum(float32, float32, float_status *status);
-float32 float32_minnummag(float32, float32, float_status *status);
-float32 float32_maxnummag(float32, float32, float_status *status);
-float32 float32_minimum_number(float32, float32, float_status *status);
-float32 float32_maximum_number(float32, float32, float_status *status);
+float32 float32_minmax(float32, float32, float_status *status, int flags);
bool float32_is_quiet_nan(float32, float_status *status);
bool float32_is_signaling_nan(float32, float_status *status);
float32 float32_silence_nan(float32, float_status *status);
@@ -818,14 +816,7 @@ float64 float64_sqrt(float64, float_status *status);
float64 float64_log2(float64, float_status *status);
FloatRelation float64_compare(float64, float64, float_status *status);
FloatRelation float64_compare_quiet(float64, float64, float_status *status);
-float64 float64_min(float64, float64, float_status *status);
-float64 float64_max(float64, float64, float_status *status);
-float64 float64_minnum(float64, float64, float_status *status);
-float64 float64_maxnum(float64, float64, float_status *status);
-float64 float64_minnummag(float64, float64, float_status *status);
-float64 float64_maxnummag(float64, float64, float_status *status);
-float64 float64_minimum_number(float64, float64, float_status *status);
-float64 float64_maximum_number(float64, float64, float_status *status);
+float64 float64_minmax(float64, float64, float_status *status, int flags);
bool float64_is_quiet_nan(float64 a, float_status *status);
bool float64_is_signaling_nan(float64, float_status *status);
float64 float64_silence_nan(float64, float_status *status);
@@ -1279,14 +1270,7 @@ float128 float128_rem(float128, float128, float_status *status);
float128 float128_sqrt(float128, float_status *status);
FloatRelation float128_compare(float128, float128, float_status *status);
FloatRelation float128_compare_quiet(float128, float128, float_status *status);
-float128 float128_min(float128, float128, float_status *status);
-float128 float128_max(float128, float128, float_status *status);
-float128 float128_minnum(float128, float128, float_status *status);
-float128 float128_maxnum(float128, float128, float_status *status);
-float128 float128_minnummag(float128, float128, float_status *status);
-float128 float128_maxnummag(float128, float128, float_status *status);
-float128 float128_minimum_number(float128, float128, float_status *status);
-float128 float128_maximum_number(float128, float128, float_status *status);
+float128 float128_minmax(float128, float128, float_status *status, int flags);
bool float128_is_quiet_nan(float128, float_status *status);
bool float128_is_signaling_nan(float128, float_status *status);
float128 float128_silence_nan(float128, float_status *status);
@@ -1388,4 +1372,33 @@ static inline bool float128_unordered_quiet(float128 a, float128 b,
*----------------------------------------------------------------------------*/
float128 float128_default_nan(float_status *status);
+/*----------------------------------------------------------------------------
+| Minumum and maximum functions.
+*----------------------------------------------------------------------------*/
+
+#define MINMAX_1(type, name, flags) \
+ static inline type type##_##name(type a, type b, float_status *s) \
+ { return type##_minmax(a, b, s, flags); }
+
+#define MINMAX_2(type) \
+ MINMAX_1(type, max, 0) \
+ MINMAX_1(type, maxnum, float_minmax_isnum) \
+ MINMAX_1(type, maxnummag, float_minmax_isnum | float_minmax_ismag) \
+ MINMAX_1(type, maximum_number, float_minmax_isnumber) \
+ MINMAX_1(type, min, float_minmax_ismin) \
+ MINMAX_1(type, minnum, float_minmax_ismin | float_minmax_isnum) \
+ MINMAX_1(type, minnummag, \
+ float_minmax_ismin | float_minmax_isnum | float_minmax_ismag) \
+ MINMAX_1(type, minimum_number, \
+ float_minmax_ismin | float_minmax_isnumber)
+
+MINMAX_2(float16)
+MINMAX_2(bfloat16)
+MINMAX_2(float32)
+MINMAX_2(float64)
+MINMAX_2(float128)
+
+#undef MINMAX_1
+#undef MINMAX_2
+
#endif /* SOFTFLOAT_H */
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 2c3bf01213..bc244a44ff 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -397,21 +397,6 @@ float64_gen2(float64 xa, float64 xb, float_status *s,
return soft(ua.s, ub.s, s);
}
-/* Flags for parts_minmax. */
-enum {
- /* Set for minimum; clear for maximum. */
- minmax_ismin = 1,
- /* Set for the IEEE 754-2008 minNum() and maxNum() operations. */
- minmax_isnum = 2,
- /* Set for the IEEE 754-2008 minNumMag() and minNumMag() operations. */
- minmax_ismag = 4,
- /*
- * Set for the IEEE 754-2019 minimumNumber() and maximumNumber()
- * operations.
- */
- minmax_isnumber = 8,
-};
-
/* Simple helpers for checking if, or what kind of, NaN we have */
static inline __attribute__((unused)) bool is_nan(FloatClass c)
{
@@ -4076,7 +4061,7 @@ float128 uint128_to_float128(Int128 a, float_status *status)
* Minimum and maximum
*/
-static float16 float16_minmax(float16 a, float16 b, float_status *s, int flags)
+float16 float16_minmax(float16 a, float16 b, float_status *s, int flags)
{
FloatParts64 pa = float16_unpack_canonical(a, s);
FloatParts64 pb = float16_unpack_canonical(b, s);
@@ -4085,8 +4070,7 @@ static float16 float16_minmax(float16 a, float16 b, float_status *s, int flags)
return float16_round_pack_canonical(pr, s);
}
-static bfloat16 bfloat16_minmax(bfloat16 a, bfloat16 b,
- float_status *s, int flags)
+bfloat16 bfloat16_minmax(bfloat16 a, bfloat16 b, float_status *s, int flags)
{
FloatParts64 pa = bfloat16_unpack_canonical(a, s);
FloatParts64 pb = bfloat16_unpack_canonical(b, s);
@@ -4095,7 +4079,7 @@ static bfloat16 bfloat16_minmax(bfloat16 a, bfloat16 b,
return bfloat16_round_pack_canonical(pr, s);
}
-static float32 float32_minmax(float32 a, float32 b, float_status *s, int flags)
+float32 float32_minmax(float32 a, float32 b, float_status *s, int flags)
{
FloatParts64 pa = float32_unpack_canonical(a, s);
FloatParts64 pb = float32_unpack_canonical(b, s);
@@ -4104,7 +4088,7 @@ static float32 float32_minmax(float32 a, float32 b, float_status *s, int flags)
return float32_round_pack_canonical(pr, s);
}
-static float64 float64_minmax(float64 a, float64 b, float_status *s, int flags)
+float64 float64_minmax(float64 a, float64 b, float_status *s, int flags)
{
FloatParts64 pa = float64_unpack_canonical(a, s);
FloatParts64 pb = float64_unpack_canonical(b, s);
@@ -4113,8 +4097,7 @@ static float64 float64_minmax(float64 a, float64 b, float_status *s, int flags)
return float64_round_pack_canonical(pr, s);
}
-static float128 float128_minmax(float128 a, float128 b,
- float_status *s, int flags)
+float128 float128_minmax(float128 a, float128 b, float_status *s, int flags)
{
FloatParts128 pa = float128_unpack_canonical(a, s);
FloatParts128 pb = float128_unpack_canonical(b, s);
@@ -4123,29 +4106,6 @@ static float128 float128_minmax(float128 a, float128 b,
return float128_round_pack_canonical(pr, s);
}
-#define MINMAX_1(type, name, flags) \
- type type##_##name(type a, type b, float_status *s) \
- { return type##_minmax(a, b, s, flags); }
-
-#define MINMAX_2(type) \
- MINMAX_1(type, max, 0) \
- MINMAX_1(type, maxnum, minmax_isnum) \
- MINMAX_1(type, maxnummag, minmax_isnum | minmax_ismag) \
- MINMAX_1(type, maximum_number, minmax_isnumber) \
- MINMAX_1(type, min, minmax_ismin) \
- MINMAX_1(type, minnum, minmax_ismin | minmax_isnum) \
- MINMAX_1(type, minnummag, minmax_ismin | minmax_isnum | minmax_ismag) \
- MINMAX_1(type, minimum_number, minmax_ismin | minmax_isnumber) \
-
-MINMAX_2(float16)
-MINMAX_2(bfloat16)
-MINMAX_2(float32)
-MINMAX_2(float64)
-MINMAX_2(float128)
-
-#undef MINMAX_1
-#undef MINMAX_2
-
/*
* Floating point compare
*/
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index d0064f5d22..a154faf32b 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -1469,7 +1469,7 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
* if one operand is a QNaN, and the other
* operand is numerical, then return numerical argument.
*/
- if ((flags & (minmax_isnum | minmax_isnumber))
+ if ((flags & (float_minmax_isnum | float_minmax_isnumber))
&& !(ab_mask & float_cmask_snan)
&& (ab_mask & ~float_cmask_qnan)) {
record_denormals_used(ab_mask, s);
@@ -1487,7 +1487,7 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
* but unless both operands are NaNs,
* the SNaN is otherwise ignored and not converted to a QNaN.
*/
- if ((flags & minmax_isnumber)
+ if ((flags & float_minmax_isnumber)
&& (ab_mask & float_cmask_snan)
&& (ab_mask & ~float_cmask_anynan)) {
float_raise(float_flag_invalid, s);
@@ -1542,7 +1542,7 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
* Take the sign into account.
* For ismag, only do this if the magnitudes are equal.
*/
- if (!(flags & minmax_ismag) || cmp == 0) {
+ if (!(flags & float_minmax_ismag) || cmp == 0) {
if (a->sign != b->sign) {
/* For differing signs, the negative operand is less. */
cmp = a->sign ? -1 : 1;
@@ -1552,7 +1552,7 @@ static FloatPartsN *partsN(minmax)(FloatPartsN *a, FloatPartsN *b,
}
}
- if (flags & minmax_ismin) {
+ if (flags & float_minmax_ismin) {
cmp = -cmp;
}
return cmp < 0 ? b : a;
--
2.43.0
^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PULL 00/30] fpu patch queue
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
` (29 preceding siblings ...)
2026-05-22 18:26 ` [PULL 30/30] fpu: Export floatN_minmax Richard Henderson
@ 2026-05-24 19:14 ` Stefan Hajnoczi
30 siblings, 0 replies; 32+ messages in thread
From: Stefan Hajnoczi @ 2026-05-24 19:14 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2026-05-24 19:16 UTC | newest]
Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-22 18:26 [PULL 00/30] fpu patch queue Richard Henderson
2026-05-22 18:26 ` [PULL 01/30] fpu: Return struct from parts{64,128}_scalbn Richard Henderson
2026-05-22 18:26 ` [PULL 02/30] fpu: Reorganize partsN(muladd) Richard Henderson
2026-05-22 18:26 ` [PULL 03/30] fpu: Return struct from parts{64,128}_muladd Richard Henderson
2026-05-22 18:26 ` [PULL 04/30] fpu: Hoist nan check in partsN_addsub Richard Henderson
2026-05-22 18:26 ` [PULL 05/30] fpu: Simplify 0 +/- N case in parts_addsub Richard Henderson
2026-05-22 18:26 ` [PULL 06/30] fpu: Use parts64_round_to_int in parts_s390_divide_to_integer Richard Henderson
2026-05-22 18:26 ` [PULL 07/30] target/s390x: Move float{32,64}_s390_divide_to_integer Richard Henderson
2026-05-22 18:26 ` [PULL 08/30] fpu: Introduce exp_scalbn Richard Henderson
2026-05-22 18:26 ` [PULL 09/30] target/alpha: Remove CONFIG_SOFTFLOAT_INLINE Richard Henderson
2026-05-22 18:26 ` [PULL 10/30] fpu: Introduce FloatExceptionFlags Richard Henderson
2026-05-22 18:26 ` [PULL 11/30] target/alpha: Use FloatExceptionFlags Richard Henderson
2026-05-22 18:26 ` [PULL 12/30] fpu: Introduce frac_msb_is_snan Richard Henderson
2026-05-22 18:26 ` [PULL 13/30] fpu: Introduce FloatSNaNRule Richard Henderson
2026-05-22 18:26 ` [PULL 14/30] fpu: Use {get,set}_float_rounding_mode everywhere Richard Henderson
2026-05-22 18:26 ` [PULL 15/30] fpu: Use of {get, set}_floatx80_rounding_precision everywhere Richard Henderson
2026-05-22 18:26 ` [PULL 16/30] fpu: Use get_floatx80_behaviour everywhere Richard Henderson
2026-05-22 18:26 ` [PULL 17/30] fpu: Use get_float_2nan_prop_rule in partsN_pick_nan Richard Henderson
2026-05-22 18:26 ` [PULL 18/30] fpu: Use get_float_3nan_prop_rule in partsN_pick_nan_muladd Richard Henderson
2026-05-22 18:26 ` [PULL 19/30] fpu: Use get_float_infzeronan_rule " Richard Henderson
2026-05-22 18:26 ` [PULL 20/30] fpu: Use accessors for tininess_before_rounding Richard Henderson
2026-05-22 18:26 ` [PULL 21/30] fpu: Use {get,set}_flush_to_zero everywhere Richard Henderson
2026-05-22 18:26 ` [PULL 22/30] fpu: Use accessors for ftz_before_rounding Richard Henderson
2026-05-22 18:26 ` [PULL 23/30] fpu: Use {get,set}_flush_inputs_to_zero everywhere Richard Henderson
2026-05-22 18:26 ` [PULL 24/30] fpu: Use get_default_nan_mode everywhere Richard Henderson
2026-05-22 18:26 ` [PULL 25/30] fpu: Use get_float_default_nan_pattern in partsN_default_nan Richard Henderson
2026-05-22 18:26 ` [PULL 26/30] fpu: Add accessors for rebias_{underflow,overflow} Richard Henderson
2026-05-22 18:26 ` [PULL 27/30] fpu: Reorg float_status Richard Henderson
2026-05-22 18:26 ` [PULL 28/30] fpu: Introduce float_status.e4m3_nan_is_snan Richard Henderson
2026-05-22 18:26 ` [PULL 29/30] fpu: Fix NaN encoding for E4M3 in parts64_uncanon Richard Henderson
2026-05-22 18:26 ` [PULL 30/30] fpu: Export floatN_minmax Richard Henderson
2026-05-24 19:14 ` [PULL 00/30] fpu patch queue Stefan Hajnoczi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.