@samitouri / QOSamiQemu / commits / 975a1bd439

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

Peter Maydell committed Aug 17, 2026 at 13:38 UTC 975a1bd4399b0a00f89996e838f418c256fa0b56
1 file changed +42 -28
target/arm/tcg/translate-vfp.c
+42 -28
@@ -207,6 +207,23 @@ static void gen_update_fp_context(DisasContext *s)
207 }
208 }
209
210 +/*
211 + * Return true if a VFP insn is OK to access the registers indicated
212 + * by regmask, false if it should UNDEF. This checks whether the
213 + * D16-D31 regs are implemented by the CPU. Eventually we will also check
214 + * CPACR.D32DIS.
215 + * Note that Neon insns accessing D16..D31 do not need to check D32DIS,
216 + * so this function is for VFP insns only.
217 + *
218 + * @regmask should be the logical OR of the VFP Dregs being accessed.
219 + */
220 +static bool vfp_dregs_ok(DisasContext *s, int dregmask)
221 +{
222 + int invalid_dreg_mask = dc_isar_feature(aa32_simd_r32, s) ? 0 : 0x10;
223 +
224 + return !(dregmask & invalid_dreg_mask);
225 +}
226 +
227 /*
228 * Check that VFP access is enabled, A-profile specific version.
229 *
@@ -347,8 +364,7 @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
364 }
365
366 /* UNDEF accesses to D16-D31 if they don't exist */
350 - if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
351 - ((a->vm | a->vn | a->vd) & 0x10)) {
367 + if (sz == 3 && !vfp_dregs_ok(s, a->vm | a->vn | a->vd)) {
368 return false;
369 }
370
@@ -473,8 +489,7 @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
489 }
490
491 /* UNDEF accesses to D16-D31 if they don't exist */
476 - if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) &&
477 - ((a->vm | a->vd) & 0x10)) {
492 + if (sz == 3 && !vfp_dregs_ok(s, a->vm | a->vd)) {
493 return false;
494 }
495
@@ -541,7 +556,7 @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
556 }
557
558 /* UNDEF accesses to D16-D31 if they don't exist */
544 - if (sz == 3 && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
559 + if (sz == 3 && !vfp_dregs_ok(s, a->vm)) {
560 return false;
561 }
562
@@ -662,7 +677,7 @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
677 }
678
679 /* UNDEF accesses to D16-D31 if they don't exist */
665 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
680 + if (!vfp_dregs_ok(s, a->vn & 0x10)) {
681 return false;
682 }
683
@@ -709,7 +724,7 @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
724 }
725
726 /* UNDEF accesses to D16-D31 if they don't exist */
712 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
727 + if (!vfp_dregs_ok(s, a->vn & 0x10)) {
728 return false;
729 }
730
@@ -745,7 +760,7 @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
760 }
761
762 /* UNDEF accesses to D16-D31 if they don't exist */
748 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
763 + if (!vfp_dregs_ok(s, a->vn)) {
764 return false;
765 }
766
@@ -1030,7 +1045,7 @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
1045 }
1046
1047 /* UNDEF accesses to D16-D31 if they don't exist */
1033 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
1048 + if (!vfp_dregs_ok(s, a->vm)) {
1049 return false;
1050 }
1051
@@ -1132,7 +1147,7 @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
1147 }
1148
1149 /* UNDEF accesses to D16-D31 if they don't exist */
1135 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
1150 + if (!vfp_dregs_ok(s, a->vd)) {
1151 return false;
1152 }
1153
@@ -1261,7 +1276,7 @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
1276 }
1277
1278 /* UNDEF accesses to D16-D31 if they don't exist */
1264 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd + n) > 16) {
1279 + if (!vfp_dregs_ok(s, a->vd + n - 1)) {
1280 return false;
1281 }
1282
@@ -1513,7 +1528,7 @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
1528 }
1529
1530 /* UNDEF accesses to D16-D31 if they don't exist */
1516 - if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
1531 + if (!vfp_dregs_ok(s, vd | vn | vm)) {
1532 return false;
1533 }
1534
@@ -1685,7 +1700,7 @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
1700 /* Note that the caller must check the aa32_fpdp_v2 feature. */
1701
1702 /* UNDEF accesses to D16-D31 if they don't exist */
1688 - if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
1703 + if (!vfp_dregs_ok(s, vd | vm)) {
1704 return false;
1705 }
1706
@@ -2252,8 +2267,7 @@ static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
2267 }
2268
2269 /* UNDEF accesses to D16-D31 if they don't exist. */
2255 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2256 - ((a->vd | a->vn | a->vm) & 0x10)) {
2270 + if (!vfp_dregs_ok(s, a->vd | a->vn | a->vm)) {
2271 return false;
2272 }
2273
@@ -2380,7 +2394,7 @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
2394 }
2395
2396 /* UNDEF accesses to D16-D31 if they don't exist. */
2383 - if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
2397 + if (!vfp_dregs_ok(s, vd)) {
2398 return false;
2399 }
2400
@@ -2555,7 +2569,7 @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
2569 }
2570
2571 /* UNDEF accesses to D16-D31 if they don't exist. */
2558 - if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2572 + if (!vfp_dregs_ok(s, a->vd | a->vm)) {
2573 return false;
2574 }
2575
@@ -2621,7 +2635,7 @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
2635 }
2636
2637 /* UNDEF accesses to D16-D31 if they don't exist. */
2624 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2638 + if (!vfp_dregs_ok(s, a->vd)) {
2639 return false;
2640 }
2641
@@ -2702,7 +2716,7 @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
2716 }
2717
2718 /* UNDEF accesses to D16-D31 if they don't exist. */
2705 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
2719 + if (!vfp_dregs_ok(s, a->vm)) {
2720 return false;
2721 }
2722
@@ -2777,7 +2791,7 @@ static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
2791 }
2792
2793 /* UNDEF accesses to D16-D31 if they don't exist. */
2780 - if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2794 + if (!vfp_dregs_ok(s, a->vd | a->vm)) {
2795 return false;
2796 }
2797
@@ -2856,7 +2870,7 @@ static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
2870 }
2871
2872 /* UNDEF accesses to D16-D31 if they don't exist. */
2859 - if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2873 + if (!vfp_dregs_ok(s, a->vd | a->vm)) {
2874 return false;
2875 }
2876
@@ -2930,7 +2944,7 @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
2944 }
2945
2946 /* UNDEF accesses to D16-D31 if they don't exist. */
2933 - if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2947 + if (!vfp_dregs_ok(s, a->vd | a->vm)) {
2948 return false;
2949 }
2950
@@ -2956,7 +2970,7 @@ static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
2970 }
2971
2972 /* UNDEF accesses to D16-D31 if they don't exist. */
2959 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2973 + if (!vfp_dregs_ok(s, a->vd)) {
2974 return false;
2975 }
2976
@@ -2982,7 +2996,7 @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
2996 }
2997
2998 /* UNDEF accesses to D16-D31 if they don't exist. */
2985 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
2999 + if (!vfp_dregs_ok(s, a->vm)) {
3000 return false;
3001 }
3002
@@ -3063,7 +3077,7 @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
3077 }
3078
3079 /* UNDEF accesses to D16-D31 if they don't exist. */
3066 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
3080 + if (!vfp_dregs_ok(s, a->vd)) {
3081 return false;
3082 }
3083
@@ -3100,7 +3114,7 @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
3114 }
3115
3116 /* UNDEF accesses to D16-D31 if they don't exist. */
3103 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
3117 + if (!vfp_dregs_ok(s, a->vm)) {
3118 return false;
3119 }
3120
@@ -3240,7 +3254,7 @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
3254 }
3255
3256 /* UNDEF accesses to D16-D31 if they don't exist. */
3243 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
3257 + if (!vfp_dregs_ok(s, a->vd)) {
3258 return false;
3259 }
3260
@@ -3369,7 +3383,7 @@ static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
3383 }
3384
3385 /* UNDEF accesses to D16-D31 if they don't exist. */
3372 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
3386 + if (!vfp_dregs_ok(s, a->vm)) {
3387 return false;
3388 }
3389