Commit 975a1bd439 for qemu.org
commit 975a1bd4399b0a00f89996e838f418c256fa0b56
Author: Peter Maydell <peter.maydell@linaro.org>
Date: Mon Aug 17 13:38:36 2026 +0100
target/arm: Pull VFP dregs checks out into a function
Currently we directly call dc_isar_feature(aa32_simd_r32, s) for VFP
insns that use D16-D31 to see if they should UNDEF. For some v7A
CPUs (Cortex-A7, Cortex-A9) there is also a CPACR.D32DIS trap bit
that will make VFP (and only VFP, not Neon) insns using D16-D31
UNDEF.
Abstract out the register check for VFP insns into a new function
which will provide us a place where we can make this check.
Since D32DIS takes precedence over traps to EL2 and EL3 and simply
makes the insns UNDEF, we are OK to check it at the same point when
we do the CPU feature check, rather than having to wait until
vfp_access_check().
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20260817123838.1578060-7-peter.maydell@linaro.org
diff --git a/target/arm/tcg/translate-vfp.c b/target/arm/tcg/translate-vfp.c
index 4db4b14841..a8d470ec49 100644
--- a/target/arm/tcg/translate-vfp.c
+++ b/target/arm/tcg/translate-vfp.c
@@ -207,6 +207,23 @@ static void gen_update_fp_context(DisasContext *s)
}
}
+/*
+ * Return true if a VFP insn is OK to access the registers indicated
+ * by regmask, false if it should UNDEF. This checks whether the
+ * D16-D31 regs are implemented by the CPU. Eventually we will also check
+ * CPACR.D32DIS.
+ * Note that Neon insns accessing D16..D31 do not need to check D32DIS,
+ * so this function is for VFP insns only.
+ *
+ * @regmask should be the logical OR of the VFP Dregs being accessed.
+ */
+static bool vfp_dregs_ok(DisasContext *s, int dregmask)
+{
+ int invalid_dreg_mask = dc_isar_feature(aa32_simd_r32, s) ? 0 : 0x10;
+
+ return !(dregmask & invalid_dreg_mask);
+}
+
/*
* Check that VFP access is enabled, A-profile specific version.
*
@@ -347,8 +364,7 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
- ((a->vm | a->vn | a->vd) & 0x10)) {
+ if (sz == 3 && !vfp_dregs_ok(s, a->vm | a->vn | a->vd)) {
return false;
}
@@ -473,8 +489,7 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
- ((a->vm | a->vd) & 0x10)) {
+ if (sz == 3 && !vfp_dregs_ok(s, a->vm | a->vd)) {
return false;
}
@@ -541,7 +556,7 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
+ if (sz == 3 && !vfp_dregs_ok(s, a->vm)) {
return false;
}
@@ -662,7 +677,7 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vn & 0x10)) {
return false;
}
@@ -709,7 +724,7 @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vn & 0x10)) {
return false;
}
@@ -745,7 +760,7 @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vn)) {
return false;
}
@@ -1030,7 +1045,7 @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vm)) {
return false;
}
@@ -1132,7 +1147,7 @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd)) {
return false;
}
@@ -1261,7 +1276,7 @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd + n) > 16) {
+ if (!vfp_dregs_ok(s, a->vd + n - 1)) {
return false;
}
@@ -1513,7 +1528,7 @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
}
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, vd | vn | vm)) {
return false;
}
@@ -1685,7 +1700,7 @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
/* Note that the caller must check the aa32_fpdp_v2 feature. */
/* UNDEF accesses to D16-D31 if they don't exist */
- if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, vd | vm)) {
return false;
}
@@ -2252,8 +2267,7 @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) &&
- ((a->vd | a->vn | a->vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd | a->vn | a->vm)) {
return false;
}
@@ -2380,7 +2394,7 @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
+ if (!vfp_dregs_ok(s, vd)) {
return false;
}
@@ -2555,7 +2569,7 @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd | a->vm)) {
return false;
}
@@ -2621,7 +2635,7 @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd)) {
return false;
}
@@ -2702,7 +2716,7 @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vm)) {
return false;
}
@@ -2777,7 +2791,7 @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd | a->vm)) {
return false;
}
@@ -2856,7 +2870,7 @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd | a->vm)) {
return false;
}
@@ -2930,7 +2944,7 @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd | a->vm)) {
return false;
}
@@ -2956,7 +2970,7 @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd)) {
return false;
}
@@ -2982,7 +2996,7 @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vm)) {
return false;
}
@@ -3063,7 +3077,7 @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd)) {
return false;
}
@@ -3100,7 +3114,7 @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vm)) {
return false;
}
@@ -3240,7 +3254,7 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vd)) {
return false;
}
@@ -3369,7 +3383,7 @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
}
/* UNDEF accesses to D16-D31 if they don't exist. */
- if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
+ if (!vfp_dregs_ok(s, a->vm)) {
return false;
}