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>
This commit is contained in:
Richard Henderson 2021-04-19 13:22:55 -07:00 committed by Peter Maydell
parent a9e89e539e
commit c8f638d99a

View file

@ -3635,7 +3635,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
bool is_postidx = extract32(insn, 23, 1); bool is_postidx = extract32(insn, 23, 1);
bool is_q = extract32(insn, 30, 1); bool is_q = extract32(insn, 30, 1);
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes; TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
MemOp endian = s->be_data; MemOp endian, align, mop;
int total; /* total bytes */ int total; /* total bytes */
int elements; /* elements per vector */ 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. */ /* For our purposes, bytes are always little-endian. */
endian = s->be_data;
if (size == 0) { if (size == 0) {
endian = MO_LE; 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 * Consecutive little-endian elements from a single register
* can be promoted to a larger little-endian operation. * can be promoted to a larger little-endian operation.
*/ */
align = MO_ALIGN;
if (selem == 1 && endian == MO_LE) { if (selem == 1 && endian == MO_LE) {
align = pow2_align(size);
size = 3; 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); tcg_ebytes = tcg_const_i64(1 << size);
for (r = 0; r < rpt; r++) { for (r = 0; r < rpt; r++) {
int e; int e;
@ -3734,9 +3741,9 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
for (xs = 0; xs < selem; xs++) { for (xs = 0; xs < selem; xs++) {
int tt = (rt + r + xs) % 32; int tt = (rt + r + xs) % 32;
if (is_store) { if (is_store) {
do_vec_st(s, tt, e, clean_addr, size | endian); do_vec_st(s, tt, e, clean_addr, mop);
} else { } 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); tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
} }