aboutsummaryrefslogtreecommitdiff
path: root/target/arm/cpu.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-11-05 10:09:53 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-11-05 10:09:53 +0000
commitd1ff996788a41280e2e0213b9571afeca4d6ca90 (patch)
treed2253df5e538d9731c2056e967b536245b1e0dce /target/arm/cpu.c
parentd22c9949d73d714e1ea2caf033131d882ad1d66a (diff)
downloadqemu-d1ff996788a41280e2e0213b9571afeca4d6ca90.zip
qemu-d1ff996788a41280e2e0213b9571afeca4d6ca90.tar.gz
qemu-d1ff996788a41280e2e0213b9571afeca4d6ca90.tar.bz2
target/arm: Explicitly set 2-NaN propagation rule
Set the 2-NaN propagation rule explicitly in the float_status words we use. We wrap this plus the pre-existing setting of the tininess-before-rounding flag in a new function arm_set_default_fp_behaviours() to avoid repetition, since we have a lot of float_status words at this point. The situation with FPA11 emulation in linux-user is a little odd, and arguably "correct" behaviour there would be to exactly match a real Linux kernel's FPA11 emulation. However FPA11 emulation is essentially dead at this point and so it seems better to continue with QEMU's current behaviour and leave a comment describing the situation. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20241025141254.2141506-4-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/cpu.c')
-rw-r--r--target/arm/cpu.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5b75143..6938161 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -168,6 +168,18 @@ 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)
+ */
+static void arm_set_default_fp_behaviours(float_status *s)
+{
+ set_float_detect_tininess(float_tininess_before_rounding, s);
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
+}
+
static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
{
/* Reset a single ARMCPRegInfo register */
@@ -549,14 +561,11 @@ static void arm_cpu_reset_hold(Object *obj, ResetType type)
set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
set_default_nan_mode(1, &env->vfp.standard_fp_status);
set_default_nan_mode(1, &env->vfp.standard_fp_status_f16);
- set_float_detect_tininess(float_tininess_before_rounding,
- &env->vfp.fp_status);
- set_float_detect_tininess(float_tininess_before_rounding,
- &env->vfp.standard_fp_status);
- set_float_detect_tininess(float_tininess_before_rounding,
- &env->vfp.fp_status_f16);
- set_float_detect_tininess(float_tininess_before_rounding,
- &env->vfp.standard_fp_status_f16);
+ arm_set_default_fp_behaviours(&env->vfp.fp_status);
+ arm_set_default_fp_behaviours(&env->vfp.standard_fp_status);
+ arm_set_default_fp_behaviours(&env->vfp.fp_status_f16);
+ arm_set_default_fp_behaviours(&env->vfp.standard_fp_status_f16);
+
#ifndef CONFIG_USER_ONLY
if (kvm_enabled()) {
kvm_arm_reset_vcpu(cpu);