@samitouri / QOSamiQemu / commits / 44d5b628fb

target/arm: Pull Neon dregs checks out into a function

Abstract out the register check for Neon insns into a new function, similarly to what we have for VFP. We don't have any extra checks that we need to add here, but having a neon_dregs_ok() is cleaner and means the Neon decode isn't oddly different to the VFP decode. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260817123838.1578060-9-peter.maydell@linaro.org

Peter Maydell committed Aug 17, 2026 at 13:38 UTC 44d5b628fbce1612f3d8529699905e8dc9f57b1b
3 files changed +53 -67
target/arm/tcg/translate-neon.c
+51 -67
@@ -118,11 +118,24 @@ static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var)
118 }
119 }
120
121 +/*
122 + * Return true if a Neon insn is OK to access the registers indicated
123 + * by regmask, false if it should UNDEF. This checks whether the
124 + * D16-D31 regs are implemented by the CPU.
125 + * Note that Neon insns accessing D16..D31 do not need to check D32DIS.
126 + *
127 + * @regmask should be the logical OR of the Dregs being accessed.
128 + */
129 +static bool neon_dregs_ok(DisasContext *s, int dregmask)
130 +{
131 + return !(dregmask & s->invalid_neon_dreg_mask);
132 +}
133 +
134 static bool do_neon_ddda(DisasContext *s, int q, int vd, int vn, int vm,
135 int data, gen_helper_gvec_4 *fn_gvec)
136 {
137 /* UNDEF accesses to D16-D31 if they don't exist. */
125 - if (((vd | vn | vm) & 0x10) && !dc_isar_feature(aa32_simd_r32, s)) {
138 + if (!neon_dregs_ok(s, vd | vn | vm)) {
139 return false;
140 }
141
@@ -152,7 +165,7 @@ static bool do_neon_ddda_env(DisasContext *s, int q, int vd, int vn, int vm,
165 int data, gen_helper_gvec_4_ptr *fn_gvec)
166 {
167 /* UNDEF accesses to D16-D31 if they don't exist. */
155 - if (((vd | vn | vm) & 0x10) && !dc_isar_feature(aa32_simd_r32, s)) {
168 + if (!neon_dregs_ok(s, vd | vn | vm)) {
169 return false;
170 }
171
@@ -184,7 +197,7 @@ static bool do_neon_ddda_fpst(DisasContext *s, int q, int vd, int vn, int vm,
197 gen_helper_gvec_4_ptr *fn_gvec_ptr)
198 {
199 /* UNDEF accesses to D16-D31 if they don't exist. */
187 - if (((vd | vn | vm) & 0x10) && !dc_isar_feature(aa32_simd_r32, s)) {
200 + if (!neon_dregs_ok(s, vd | vn | vm)) {
201 return false;
202 }
203
@@ -240,8 +253,7 @@ static bool trans_VCADD(DisasContext *s, arg_VCADD *a)
253 }
254
255 /* UNDEF accesses to D16-D31 if they don't exist. */
243 - if (!dc_isar_feature(aa32_simd_r32, s) &&
244 - ((a->vd | a->vn | a->vm) & 0x10)) {
256 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
257 return false;
258 }
259
@@ -310,8 +322,7 @@ static bool trans_VFML(DisasContext *s, arg_VFML *a)
322 }
323
324 /* UNDEF accesses to D16-D31 if they don't exist. */
313 - if (!dc_isar_feature(aa32_simd_r32, s) &&
314 - (a->vd & 0x10)) {
325 + if (!neon_dregs_ok(s, a->vd)) {
326 return false;
327 }
328
@@ -398,14 +409,14 @@ static bool trans_VDOT_b16_scal(DisasContext *s, arg_VDOT_b16_scal *a)
409 static bool trans_VFML_scalar(DisasContext *s, arg_VFML_scalar *a)
410 {
411 int opr_sz;
412 + int dregmask = a->vd | (a->q ? a->vn : 0);
413
414 if (!dc_isar_feature(aa32_fhm, s)) {
415 return false;
416 }
417
418 /* UNDEF accesses to D16-D31 if they don't exist. */
407 - if (!dc_isar_feature(aa32_simd_r32, s) &&
408 - ((a->vd & 0x10) || (a->q && (a->vn & 0x10)))) {
419 + if (!neon_dregs_ok(s, dregmask)) {
420 return false;
421 }
422
@@ -478,7 +489,7 @@ static bool trans_VLDST_multiple(DisasContext *s, arg_VLDST_multiple *a)
489 }
490
491 /* UNDEF accesses to D16-D31 if they don't exist */
481 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
492 + if (!neon_dregs_ok(s, a->vd)) {
493 return false;
494 }
495 if (a->itype > 10) {
@@ -580,7 +591,7 @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a)
591 }
592
593 /* UNDEF accesses to D16-D31 if they don't exist */
583 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
594 + if (!neon_dregs_ok(s, a->vd)) {
595 return false;
596 }
597
@@ -672,7 +683,7 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
683 }
684
685 /* UNDEF accesses to D16-D31 if they don't exist */
675 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
686 + if (!neon_dregs_ok(s, a->vd)) {
687 return false;
688 }
689
@@ -789,8 +800,7 @@ static bool do_3same(DisasContext *s, arg_3same *a, GVecGen3Fn fn)
800 }
801
802 /* UNDEF accesses to D16-D31 if they don't exist. */
792 - if (!dc_isar_feature(aa32_simd_r32, s) &&
793 - ((a->vd | a->vn | a->vm) & 0x10)) {
803 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
804 return false;
805 }
806
@@ -1067,8 +1077,7 @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
1077 }
1078
1079 /* UNDEF accesses to D16-D31 if they don't exist. */
1070 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1071 - ((a->vd | a->vm) & 0x10)) {
1080 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
1081 return false;
1082 }
1083
@@ -1117,8 +1126,7 @@ static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
1126 }
1127
1128 /* UNDEF accesses to D16-D31 if they don't exist. */
1120 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1121 - ((a->vd | a->vm) & 0x10)) {
1129 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
1130 return false;
1131 }
1132
@@ -1168,8 +1176,7 @@ static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
1176 }
1177
1178 /* UNDEF accesses to D16-D31 if they don't exist. */
1171 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1172 - ((a->vd | a->vm) & 0x10)) {
1179 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
1180 return false;
1181 }
1182
@@ -1293,8 +1300,7 @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
1300 }
1301
1302 /* UNDEF accesses to D16-D31 if they don't exist. */
1296 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1297 - ((a->vd | a->vm) & 0x10)) {
1303 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
1304 return false;
1305 }
1306
@@ -1383,8 +1389,7 @@ static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
1389 }
1390
1391 /* UNDEF accesses to D16-D31 if they don't exist. */
1386 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1387 - ((a->vd | a->vm) & 0x10)) {
1392 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
1393 return false;
1394 }
1395
@@ -1428,7 +1433,7 @@ static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a,
1433 }
1434
1435 /* UNDEF accesses to D16-D31 if they don't exist. */
1431 - if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
1436 + if (!neon_dregs_ok(s, a->vd)) {
1437 return false;
1438 }
1439
@@ -1485,8 +1490,7 @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a,
1490 }
1491
1492 /* UNDEF accesses to D16-D31 if they don't exist. */
1488 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1489 - ((a->vd | a->vn | a->vm) & 0x10)) {
1493 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
1494 return false;
1495 }
1496
@@ -1592,8 +1596,7 @@ static bool do_narrow_3d(DisasContext *s, arg_3diff *a,
1596 }
1597
1598 /* UNDEF accesses to D16-D31 if they don't exist. */
1595 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1596 - ((a->vd | a->vn | a->vm) & 0x10)) {
1599 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
1600 return false;
1601 }
1602
@@ -1682,8 +1685,7 @@ static bool do_long_3d(DisasContext *s, arg_3diff *a,
1685 }
1686
1687 /* UNDEF accesses to D16-D31 if they don't exist. */
1685 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1686 - ((a->vd | a->vn | a->vm) & 0x10)) {
1688 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
1689 return false;
1690 }
1691
@@ -1944,8 +1946,7 @@ static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a)
1946 }
1947
1948 /* UNDEF accesses to D16-D31 if they don't exist. */
1947 - if (!dc_isar_feature(aa32_simd_r32, s) &&
1948 - ((a->vd | a->vn | a->vm) & 0x10)) {
1949 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
1950 return false;
1951 }
1952
@@ -2027,8 +2028,7 @@ static bool do_2scalar(DisasContext *s, arg_2scalar *a,
2028 }
2029
2030 /* UNDEF accesses to D16-D31 if they don't exist. */
2030 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2031 - ((a->vd | a->vn | a->vm) & 0x10)) {
2031 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
2032 return false;
2033 }
2034
@@ -2125,8 +2125,7 @@ static bool do_2scalar_fp_vec(DisasContext *s, arg_2scalar *a,
2125 }
2126
2127 /* UNDEF accesses to D16-D31 if they don't exist. */
2128 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2129 - ((a->vd | a->vn | a->vm) & 0x10)) {
2128 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
2129 return false;
2130 }
2131
@@ -2222,8 +2221,7 @@ static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a,
2221 }
2222
2223 /* UNDEF accesses to D16-D31 if they don't exist. */
2225 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2226 - ((a->vd | a->vn | a->vm) & 0x10)) {
2224 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
2225 return false;
2226 }
2227
@@ -2293,8 +2291,7 @@ static bool do_2scalar_long(DisasContext *s, arg_2scalar *a,
2291 }
2292
2293 /* UNDEF accesses to D16-D31 if they don't exist. */
2296 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2297 - ((a->vd | a->vn | a->vm) & 0x10)) {
2294 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
2295 return false;
2296 }
2297
@@ -2438,8 +2435,7 @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a)
2435 }
2436
2437 /* UNDEF accesses to D16-D31 if they don't exist. */
2441 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2442 - ((a->vd | a->vn | a->vm) & 0x10)) {
2438 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
2439 return false;
2440 }
2441
@@ -2507,8 +2503,7 @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
2503 }
2504
2505 /* UNDEF accesses to D16-D31 if they don't exist. */
2510 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2511 - ((a->vd | a->vn | a->vm) & 0x10)) {
2506 + if (!neon_dregs_ok(s, a->vd | a->vn | a->vm)) {
2507 return false;
2508 }
2509
@@ -2546,8 +2541,7 @@ static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a)
2541 }
2542
2543 /* UNDEF accesses to D16-D31 if they don't exist. */
2549 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2550 - ((a->vd | a->vm) & 0x10)) {
2544 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2545 return false;
2546 }
2547
@@ -2577,8 +2571,7 @@ static bool do_zip_uzp(DisasContext *s, arg_2misc *a,
2571 }
2572
2573 /* UNDEF accesses to D16-D31 if they don't exist. */
2580 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2581 - ((a->vd | a->vm) & 0x10)) {
2574 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2575 return false;
2576 }
2577
@@ -2647,8 +2640,7 @@ static bool do_vmovn(DisasContext *s, arg_2misc *a,
2640 }
2641
2642 /* UNDEF accesses to D16-D31 if they don't exist. */
2650 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2651 - ((a->vd | a->vm) & 0x10)) {
2643 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2644 return false;
2645 }
2646
@@ -2711,8 +2703,7 @@ static bool trans_VSHLL(DisasContext *s, arg_2misc *a)
2703 }
2704
2705 /* UNDEF accesses to D16-D31 if they don't exist. */
2714 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2715 - ((a->vd | a->vm) & 0x10)) {
2706 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2707 return false;
2708 }
2709
@@ -2755,8 +2746,7 @@ static bool trans_VCVT_B16_F32(DisasContext *s, arg_2misc *a)
2746 }
2747
2748 /* UNDEF accesses to D16-D31 if they don't exist. */
2758 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2759 - ((a->vd | a->vm) & 0x10)) {
2749 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2750 return false;
2751 }
2752
@@ -2795,8 +2785,7 @@ static bool trans_VCVT_F16_F32(DisasContext *s, arg_2misc *a)
2785 }
2786
2787 /* UNDEF accesses to D16-D31 if they don't exist. */
2798 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2799 - ((a->vd | a->vm) & 0x10)) {
2788 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2789 return false;
2790 }
2791
@@ -2841,8 +2830,7 @@ static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a)
2830 }
2831
2832 /* UNDEF accesses to D16-D31 if they don't exist. */
2844 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2845 - ((a->vd | a->vm) & 0x10)) {
2833 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2834 return false;
2835 }
2836
@@ -2887,8 +2875,7 @@ static bool do_2misc_vec(DisasContext *s, arg_2misc *a, GVecGen2Fn *fn)
2875 }
2876
2877 /* UNDEF accesses to D16-D31 if they don't exist. */
2890 - if (!dc_isar_feature(aa32_simd_r32, s) &&
2891 - ((a->vd | a->vm) & 0x10)) {
2878 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
2879 return false;
2880 }
2881
@@ -3015,8 +3002,7 @@ static bool do_2misc(DisasContext *s, arg_2misc *a, NeonGenOneOpFn *fn)
3002 }
3003
3004 /* UNDEF accesses to D16-D31 if they don't exist. */
3018 - if (!dc_isar_feature(aa32_simd_r32, s) &&
3019 - ((a->vd | a->vm) & 0x10)) {
3005 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
3006 return false;
3007 }
3008
@@ -3219,8 +3205,7 @@ static bool trans_VSWP(DisasContext *s, arg_2misc *a)
3205 }
3206
3207 /* UNDEF accesses to D16-D31 if they don't exist. */
3222 - if (!dc_isar_feature(aa32_simd_r32, s) &&
3223 - ((a->vd | a->vm) & 0x10)) {
3208 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
3209 return false;
3210 }
3211
@@ -3292,8 +3277,7 @@ static bool trans_VTRN(DisasContext *s, arg_2misc *a)
3277 }
3278
3279 /* UNDEF accesses to D16-D31 if they don't exist. */
3295 - if (!dc_isar_feature(aa32_simd_r32, s) &&
3296 - ((a->vd | a->vm) & 0x10)) {
3280 + if (!neon_dregs_ok(s, a->vd | a->vm)) {
3281 return false;
3282 }
3283
target/arm/tcg/translate.c
+1
@@ -6410,6 +6410,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
6410
6411 dc->invalid_vfp_dreg_mask =
6412 (d32dis || !dc_isar_feature(aa32_simd_r32, dc)) ? 0x10 : 0;
6413 + dc->invalid_neon_dreg_mask = !dc_isar_feature(aa32_simd_r32, dc) ? 0x10 : 0;
6414
6415 dc->lse2 = false; /* applies only to aarch64 */
6416 dc->cp_regs = cpu->cp_regs;
target/arm/tcg/translate.h
+1
@@ -95,6 +95,7 @@ typedef struct DisasContext {
95 int max_any_vl; /* maximum implemented vector length */
96 bool vfp_enabled; /* FP enabled via FPSCR.EN */
97 int invalid_vfp_dreg_mask; /* mask for whether VFP D16..D31 should UNDEF */
98 + int invalid_neon_dreg_mask; /* ditto, for Neon */
99 int vec_len;
100 int vec_stride;
101 bool v7m_handler_mode;