LD1_zprz 1100010 11 1. ..... 11. ... ..... ..... \
@rprr_g_load_sc esz=3 msz=3 u=1
-# LD1Q
-LD1_zprz 1100 0100 000 rm:5 101 pg:3 rn:5 rd:5 \
- &rprr_gather_load u=1 ff=0 xs=2 esz=4 msz=4 scale=0
+# LD1Q. Note that this is subtly different from LD1_zprz because
+# it is vector + scalar, not scalar + vector.
+LD1Q 1100 0100 000 rm:5 101 pg:3 rn:5 rd:5
# SVE 64-bit gather load (vector plus immediate)
LD1_zpiz 1100010 .. 01 ..... 1.. ... ..... ..... \
ST1_zprz 1110010 .. 00 ..... 101 ... ..... ..... \
@rprr_scatter_store xs=2 esz=3 scale=0
-# ST1Q
-ST1_zprz 1110 0100 001 rm:5 001 pg:3 rn:5 rd:5 \
- &rprr_scatter_store xs=2 msz=4 esz=4 scale=0
+# ST1Q. Note that this is subtly different from ST1_zprz because
+# it is vector + scalar, not scalar + vector.
+ST1Q 1110 0100 001 rm:5 001 pg:3 rn:5 rd:5
# SVE 64-bit scatter store (vector plus immediate)
ST1_zpiz 1110010 .. 10 ..... 101 ... ..... ..... \
bool be = s->be_data == MO_BE;
bool mte = s->mte_active[0];
- if (a->esz < MO_128
- ? !dc_isar_feature(aa64_sve, s)
- : !dc_isar_feature(aa64_sve2p1, s)) {
+ if (!dc_isar_feature(aa64_sve, s)) {
return false;
}
s->is_nonstreaming = true;
case MO_64:
fn = gather_load_fn64[mte][be][a->ff][a->xs][a->u][a->msz];
break;
- case MO_128:
- assert(!a->ff && a->u && a->xs == 2 && a->msz == MO_128);
- fn = gather_load_fn128[mte][be];
- break;
default:
g_assert_not_reached();
}
return true;
}
+static bool trans_LD1Q(DisasContext *s, arg_LD1Q *a)
+{
+ gen_helper_gvec_mem_scatter *fn = NULL;
+ bool be = s->be_data == MO_BE;
+ bool mte = s->mte_active[0];
+
+ if (!dc_isar_feature(aa64_sve2p1, s)) {
+ return false;
+ }
+ s->is_nonstreaming = true;
+ if (!sve_access_check(s)) {
+ return true;
+ }
+
+ fn = gather_load_fn128[mte][be];
+ assert(fn != NULL);
+
+ /*
+ * Unlike LD1_zprz, a->rm is the scalar register and it can be XZR, not XSP.
+ * a->rn is the vector register.
+ */
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0,
+ cpu_reg(s, a->rm), MO_128, false, fn);
+ return true;
+}
+
static bool trans_LD1_zpiz(DisasContext *s, arg_LD1_zpiz *a)
{
gen_helper_gvec_mem_scatter *fn = NULL;
if (a->esz < a->msz || (a->msz == 0 && a->scale)) {
return false;
}
- if (a->esz < MO_128
- ? !dc_isar_feature(aa64_sve, s)
- : !dc_isar_feature(aa64_sve2p1, s)) {
+ if (!dc_isar_feature(aa64_sve, s)) {
return false;
}
s->is_nonstreaming = true;
case MO_64:
fn = scatter_store_fn64[mte][be][a->xs][a->msz];
break;
- case MO_128:
- assert(a->xs == 2 && a->msz == MO_128);
- fn = scatter_store_fn128[mte][be];
- break;
default:
g_assert_not_reached();
}
return true;
}
+static bool trans_ST1Q(DisasContext *s, arg_ST1Q *a)
+{
+ gen_helper_gvec_mem_scatter *fn;
+ bool be = s->be_data == MO_BE;
+ bool mte = s->mte_active[0];
+
+ if (!dc_isar_feature(aa64_sve2p1, s)) {
+ return false;
+ }
+ s->is_nonstreaming = true;
+ if (!sve_access_check(s)) {
+ return true;
+ }
+ fn = scatter_store_fn128[mte][be];
+ /*
+ * Unlike ST1_zprz, a->rm is the scalar register, and it
+ * can be XZR, not XSP. a->rn is the vector register.
+ */
+ do_mem_zpz(s, a->rd, a->pg, a->rn, 0,
+ cpu_reg(s, a->rm), MO_128, true, fn);
+ return true;
+}
+
static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a)
{
gen_helper_gvec_mem_scatter *fn = NULL;