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;