/* Resolve tile.size[rs+imm] to a host pointer. */
static TCGv_ptr get_tile_rowcol(DisasContext *s, int esz, int rs,
- int tile, int imm, bool vertical)
+ int tile, int imm, int div_len,
+ int vec_mod, bool vertical)
{
int pos, len, offset;
TCGv_i32 tmp;
/* Compute the final index, which is Rs+imm. */
tmp = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(tmp, cpu_reg(s, rs));
+ /*
+ * Round the vector index down to a multiple of vec_mod if necessary.
+ * We do this before adding the offset, to handle cases like
+ * MOVA (tile to vector, 2 registers) where we want to call this
+ * several times in a loop with an increasing offset. We rely on
+ * the instruction encodings always forcing the initial offset in
+ * [rs + offset] to be a multiple of vec_mod. The pseudocode usually
+ * does the round-down after adding the offset rather than before,
+ * but MOVA is an exception.
+ */
+ if (vec_mod > 1) {
+ tcg_gen_andc_i32(tmp, tmp, tcg_constant_i32(vec_mod - 1));
+ }
tcg_gen_addi_i32(tmp, tmp, imm);
/* Prepare a power-of-two modulo via extraction of @len bits. */
- len = ctz32(streaming_vec_reg_size(s)) - esz;
+ len = ctz32(streaming_vec_reg_size(s) / div_len) - esz;
if (!len) {
/*
return addr;
}
+/* Resolve ZArray[rs+imm] to a host pointer. */
+static TCGv_ptr get_zarray(DisasContext *s, int rs, int imm,
+ int div_len, int vec_mod)
+{
+ /* ZA[n] equates to ZA0H.B[n]. */
+ return get_tile_rowcol(s, MO_8, rs, 0, imm, div_len, vec_mod, false);
+}
+
/*
* Resolve tile.size[0] to a host pointer.
* Used by e.g. outer product insns where we require the entire tile.
return true;
}
- t_za = get_tile_rowcol(s, a->esz, a->rs, a->za, a->off, a->v);
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za, a->off, 1, 0, a->v);
t_zr = vec_full_reg_ptr(s, a->zr);
t_pg = pred_full_reg_ptr(s, a->pg);
return true;
}
- t_za = get_tile_rowcol(s, a->esz, a->rs, a->za, a->off, a->v);
+ t_za = get_tile_rowcol(s, a->esz, a->rs, a->za, a->off, 1, 0, a->v);
t_pg = pred_full_reg_ptr(s, a->pg);
addr = tcg_temp_new_i64();
static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
{
- int svl = streaming_vec_reg_size(s);
- int imm = a->imm;
- TCGv_ptr base;
+ if (sme_za_enabled_check(s)) {
+ int svl = streaming_vec_reg_size(s);
+ int imm = a->imm;
+ TCGv_ptr base = get_zarray(s, a->rv, imm, 1, 0);
- if (!sme_za_enabled_check(s)) {
- return true;
+ fn(s, base, 0, svl, a->rn, imm * svl,
+ s->align_mem ? MO_ALIGN_16 : MO_UNALN);
}
-
- /* ZA[n] equates to ZA0H.B[n]. */
- base = get_tile_rowcol(s, MO_8, a->rv, 0, imm, false);
-
- fn(s, base, 0, svl, a->rn, imm * svl,
- s->align_mem ? MO_ALIGN_16 : MO_UNALN);
return true;
}