aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-04-19 13:22:55 -0700
committerPeter Maydell <peter.maydell@linaro.org>2021-04-30 11:16:51 +0100
commitc8f638d99aaf8284b9ba81fb49ad6985d109794f (patch)
treee5c06aa769a5d935d1d584a0eb0377ef1d6d32c0 /target
parenta9e89e539ec3a67f5257ce055a8ed38bd58fc89f (diff)
downloadqemu-c8f638d99aaf8284b9ba81fb49ad6985d109794f.zip
qemu-c8f638d99aaf8284b9ba81fb49ad6985d109794f.tar.gz
qemu-c8f638d99aaf8284b9ba81fb49ad6985d109794f.tar.bz2
target/arm: Enforce alignment for aa64 vector LDn/STn (multiple)
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210419202257.161730-30-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/translate-a64.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d3bda16..2a82dbb 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -3635,7 +3635,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
bool is_postidx = extract32(insn, 23, 1);
bool is_q = extract32(insn, 30, 1);
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
- MemOp endian = s->be_data;
+ MemOp endian, align, mop;
int total; /* total bytes */
int elements; /* elements per vector */
@@ -3703,6 +3703,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
}
/* For our purposes, bytes are always little-endian. */
+ endian = s->be_data;
if (size == 0) {
endian = MO_LE;
}
@@ -3721,11 +3722,17 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
* Consecutive little-endian elements from a single register
* can be promoted to a larger little-endian operation.
*/
+ align = MO_ALIGN;
if (selem == 1 && endian == MO_LE) {
+ align = pow2_align(size);
size = 3;
}
- elements = (is_q ? 16 : 8) >> size;
+ if (!s->align_mem) {
+ align = 0;
+ }
+ mop = endian | size | align;
+ elements = (is_q ? 16 : 8) >> size;
tcg_ebytes = tcg_const_i64(1 << size);
for (r = 0; r < rpt; r++) {
int e;
@@ -3734,9 +3741,9 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
for (xs = 0; xs < selem; xs++) {
int tt = (rt + r + xs) % 32;
if (is_store) {
- do_vec_st(s, tt, e, clean_addr, size | endian);
+ do_vec_st(s, tt, e, clean_addr, mop);
} else {
- do_vec_ld(s, tt, e, clean_addr, size | endian);
+ do_vec_ld(s, tt, e, clean_addr, mop);
}
tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
}