[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 29/76] target/arm: Adjust FP behaviour for FPCR.AH = 1
From: |
Peter Maydell |
Subject: |
[PATCH 29/76] target/arm: Adjust FP behaviour for FPCR.AH = 1 |
Date: |
Fri, 24 Jan 2025 16:27:49 +0000 |
When FPCR.AH is set, various behaviours of AArch64 floating point
operations which are controlled by softfloat config settings change:
* tininess and ftz detection before/after rounding
* NaN propagation order
* result of 0 * Inf + NaN
* default NaN value
When the guest changes the value of the AH bit, switch these config
settings on the fp_status_a64 and fp_status_f16_a64 float_status
fields.
This requires us to make the arm_set_default_fp_behaviours() function
global, since we now need to call it from cpu.c and vfp_helper.c; we
move it to vfp_helper.c so it can be next to the new
arm_set_ah_fp_behaviours().
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/internals.h | 4 +++
target/arm/cpu.c | 23 -----------------
target/arm/vfp_helper.c | 56 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 23 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 863a84edf81..98073acc276 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1828,4 +1828,8 @@ uint64_t gt_virt_cnt_offset(CPUARMState *env);
* all EL1" scope; this covers stage 1 and stage 2.
*/
int alle1_tlbmask(CPUARMState *env);
+
+/* Set the float_status behaviour to match the Arm defaults */
+void arm_set_default_fp_behaviours(float_status *s);
+
#endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 0b4cd872d27..1ba22c4c7aa 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -169,29 +169,6 @@ void arm_register_el_change_hook(ARMCPU *cpu,
ARMELChangeHookFn *hook,
QLIST_INSERT_HEAD(&cpu->el_change_hooks, entry, node);
}
-/*
- * Set the float_status behaviour to match the Arm defaults:
- * * tininess-before-rounding
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
- * operand A over operand B (see FPProcessNaNs() pseudocode)
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
- * but note that for QEMU muladd is a * b + c, whereas for
- * the pseudocode function the arguments are in the order c, a, b.
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
- * and the input NaN if it is signalling
- * * Default NaN has sign bit clear, msb frac bit set
- */
-static void arm_set_default_fp_behaviours(float_status *s)
-{
- set_float_detect_tininess(float_tininess_before_rounding, s);
- set_float_detect_ftz(detect_ftz_before_rounding, s);
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
- set_float_default_nan_pattern(0b01000000, s);
-}
-
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
{
/* Reset a single ARMCPRegInfo register */
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
index 5a0b389f7a3..7507ff24bc0 100644
--- a/target/arm/vfp_helper.c
+++ b/target/arm/vfp_helper.c
@@ -31,6 +31,50 @@
Single precision routines have a "s" suffix, double precision a
"d" suffix. */
+/*
+ * Set the float_status behaviour to match the Arm defaults:
+ * * tininess-before-rounding
+ * * 2-input NaN propagation prefers SNaN over QNaN, and then
+ * operand A over operand B (see FPProcessNaNs() pseudocode)
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
+ * but note that for QEMU muladd is a * b + c, whereas for
+ * the pseudocode function the arguments are in the order c, a, b.
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
+ * and the input NaN if it is signalling
+ * * Default NaN has sign bit clear, msb frac bit set
+ */
+void arm_set_default_fp_behaviours(float_status *s)
+{
+ set_float_detect_tininess(float_tininess_before_rounding, s);
+ set_float_detect_ftz(detect_ftz_before_rounding, s);
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
+ set_float_default_nan_pattern(0b01000000, s);
+}
+
+/*
+ * Set the float_status behaviour to match the FEAT_AFP
+ * FPCR.AH=1 requirements:
+ * * tininess-after-rounding
+ * * 2-input NaN propagation prefers the first NaN
+ * * 3-input NaN propagation prefers a over b over c
+ * * 0 * Inf + NaN always returns the input NaN and doesn't
+ * set Invalid for a QNaN
+ * * default NaN has sign bit set, msb frac bit set
+ */
+static void arm_set_ah_fp_behaviours(float_status *s)
+{
+ set_float_detect_tininess(float_tininess_after_rounding, s);
+ set_float_detect_ftz(detect_ftz_after_rounding, s);
+ set_float_2nan_prop_rule(float_2nan_prop_ab, s);
+ set_float_3nan_prop_rule(float_3nan_prop_abc, s);
+ set_float_infzeronan_rule(float_infzeronan_dnan_never |
+ float_infzeronan_suppress_invalid, s);
+ set_float_default_nan_pattern(0b11000000, s);
+}
+
#ifdef CONFIG_TCG
/* Convert host exception flags to vfp form. */
@@ -171,6 +215,18 @@ static void vfp_set_fpcr_to_host(CPUARMState *env,
uint32_t val, uint32_t mask)
set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16_a32);
set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16_a64);
}
+ if (changed & FPCR_AH) {
+ bool ah_enabled = val & FPCR_AH;
+
+ if (ah_enabled) {
+ /* Change behaviours for A64 FP operations */
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status_a64);
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status_f16_a64);
+ } else {
+ arm_set_default_fp_behaviours(&env->vfp.fp_status_a64);
+ arm_set_default_fp_behaviours(&env->vfp.fp_status_f16_a64);
+ }
+ }
/*
* If any bits changed that we look at in vfp_get_fpsr_from_host(),
* we must sync the float_status flags into vfp.fpsr now (under the
--
2.34.1
- [PATCH 25/76] target/arm: Remove redundant advsimd float16 helpers, (continued)
- [PATCH 25/76] target/arm: Remove redundant advsimd float16 helpers, Peter Maydell, 2025/01/24
- [PATCH 33/76] target/arm: Use FPST_FPCR_AH for FRECPE, FRECPS, FRECPX, FRSQRTE, FRSQRTS, Peter Maydell, 2025/01/24
- [PATCH 36/76] target/arm: Add FPCR.NEP to TBFLAGS, Peter Maydell, 2025/01/24
- [PATCH 45/76] target/arm: Implement FPCR.AH semantics for scalar FMIN/FMAX, Peter Maydell, 2025/01/24
- [PATCH 27/76] target/arm: Define FPCR AH, FIZ, NEP bits, Peter Maydell, 2025/01/24
- [PATCH 29/76] target/arm: Adjust FP behaviour for FPCR.AH = 1,
Peter Maydell <=
- [PATCH 31/76] target/arm: Add FPCR.AH to tbflags, Peter Maydell, 2025/01/24
- [PATCH 32/76] target/arm: Set up float_status to use for FPCR.AH=1 behaviour, Peter Maydell, 2025/01/24
- [PATCH 42/76] target/arm: Handle FPCR.NEP for scalar FABS and FNEG, Peter Maydell, 2025/01/24
- [PATCH 08/76] target/arm: Use fp_status_a32 in vjvct helper, Peter Maydell, 2025/01/24
- [PATCH 50/76] target/arm: Implement FPCR.AH semantics for SVE FMIN/FMAX immediate, Peter Maydell, 2025/01/24