aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-06-28 14:58:18 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-07-02 11:48:36 +0100
commitd59ccc30f64249d5727bc084e0f3cf4b2483117b (patch)
tree19fe72be98c38645546b15aaf6f1e4d7e04fcec6
parente3bcf57c1a3c498fe7bd1f18744614a802d8859a (diff)
target/arm: Fix MVE widening/narrowing VLDR/VSTR offset calculation
In do_ldst(), the calculation of the offset needs to be based on the size of the memory access, not the size of the elements in the vector. This meant we were getting it wrong for the widening and narrowing variants of the various VLDR and VSTR insns. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210628135835.6690-2-peter.maydell@linaro.org
-rw-r--r--target/arm/translate-mve.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
index 67462bdf27..e9a5442a72 100644
--- a/target/arm/translate-mve.c
+++ b/target/arm/translate-mve.c
@@ -120,7 +120,8 @@ static bool mve_skip_first_beat(DisasContext *s)
}
}
-static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
+static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn,
+ unsigned msize)
{
TCGv_i32 addr;
uint32_t offset;
@@ -141,7 +142,7 @@ static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
return true;
}
- offset = a->imm << a->size;
+ offset = a->imm << msize;
if (!a->a) {
offset = -offset;
}
@@ -178,22 +179,22 @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
{ gen_helper_mve_vstrw, gen_helper_mve_vldrw },
{ NULL, NULL }
};
- return do_ldst(s, a, ldstfns[a->size][a->l]);
+ return do_ldst(s, a, ldstfns[a->size][a->l], a->size);
}
-#define DO_VLDST_WIDE_NARROW(OP, SLD, ULD, ST) \
+#define DO_VLDST_WIDE_NARROW(OP, SLD, ULD, ST, MSIZE) \
static bool trans_##OP(DisasContext *s, arg_VLDR_VSTR *a) \
{ \
static MVEGenLdStFn * const ldstfns[2][2] = { \
{ gen_helper_mve_##ST, gen_helper_mve_##SLD }, \
{ NULL, gen_helper_mve_##ULD }, \
}; \
- return do_ldst(s, a, ldstfns[a->u][a->l]); \
+ return do_ldst(s, a, ldstfns[a->u][a->l], MSIZE); \
}
-DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
-DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
-DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
+DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h, MO_8)
+DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w, MO_8)
+DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w, MO_16)
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
{