target/arm: Export unpredicated ld/st from translate-sve.c

Add a TCGv_ptr base argument, which will be cpu_env for SVE.
We will reuse this for SME save and restore array insns.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220708151540.18136-22-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-07-08 20:45:16 +05:30 committed by Peter Maydell
parent 7390e0e9ab
commit 8713f73e53
2 changed files with 39 additions and 12 deletions

View file

@ -195,4 +195,7 @@ void gen_gvec_xar(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, int64_t shift, uint32_t rm_ofs, int64_t shift,
uint32_t opr_sz, uint32_t max_sz); uint32_t opr_sz, uint32_t max_sz);
void gen_sve_ldr(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
void gen_sve_str(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int imm);
#endif /* TARGET_ARM_TRANSLATE_A64_H */ #endif /* TARGET_ARM_TRANSLATE_A64_H */

View file

@ -4306,7 +4306,8 @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
* The load should begin at the address Rn + IMM. * The load should begin at the address Rn + IMM.
*/ */
static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
int len, int rn, int imm)
{ {
int len_align = QEMU_ALIGN_DOWN(len, 8); int len_align = QEMU_ALIGN_DOWN(len, 8);
int len_remain = len % 8; int len_remain = len % 8;
@ -4332,7 +4333,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
t0 = tcg_temp_new_i64(); t0 = tcg_temp_new_i64();
for (i = 0; i < len_align; i += 8) { for (i = 0; i < len_align; i += 8) {
tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ); tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
tcg_gen_st_i64(t0, cpu_env, vofs + i); tcg_gen_st_i64(t0, base, vofs + i);
tcg_gen_addi_i64(clean_addr, clean_addr, 8); tcg_gen_addi_i64(clean_addr, clean_addr, 8);
} }
tcg_temp_free_i64(t0); tcg_temp_free_i64(t0);
@ -4345,6 +4346,12 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
clean_addr = new_tmp_a64_local(s); clean_addr = new_tmp_a64_local(s);
tcg_gen_mov_i64(clean_addr, t0); tcg_gen_mov_i64(clean_addr, t0);
if (base != cpu_env) {
TCGv_ptr b = tcg_temp_local_new_ptr();
tcg_gen_mov_ptr(b, base);
base = b;
}
gen_set_label(loop); gen_set_label(loop);
t0 = tcg_temp_new_i64(); t0 = tcg_temp_new_i64();
@ -4352,7 +4359,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
tcg_gen_addi_i64(clean_addr, clean_addr, 8); tcg_gen_addi_i64(clean_addr, clean_addr, 8);
tp = tcg_temp_new_ptr(); tp = tcg_temp_new_ptr();
tcg_gen_add_ptr(tp, cpu_env, i); tcg_gen_add_ptr(tp, base, i);
tcg_gen_addi_ptr(i, i, 8); tcg_gen_addi_ptr(i, i, 8);
tcg_gen_st_i64(t0, tp, vofs); tcg_gen_st_i64(t0, tp, vofs);
tcg_temp_free_ptr(tp); tcg_temp_free_ptr(tp);
@ -4360,6 +4367,11 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop); tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
tcg_temp_free_ptr(i); tcg_temp_free_ptr(i);
if (base != cpu_env) {
tcg_temp_free_ptr(base);
assert(len_remain == 0);
}
} }
/* /*
@ -4388,13 +4400,14 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }
tcg_gen_st_i64(t0, cpu_env, vofs + len_align); tcg_gen_st_i64(t0, base, vofs + len_align);
tcg_temp_free_i64(t0); tcg_temp_free_i64(t0);
} }
} }
/* Similarly for stores. */ /* Similarly for stores. */
static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
int len, int rn, int imm)
{ {
int len_align = QEMU_ALIGN_DOWN(len, 8); int len_align = QEMU_ALIGN_DOWN(len, 8);
int len_remain = len % 8; int len_remain = len % 8;
@ -4420,7 +4433,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
t0 = tcg_temp_new_i64(); t0 = tcg_temp_new_i64();
for (i = 0; i < len_align; i += 8) { for (i = 0; i < len_align; i += 8) {
tcg_gen_ld_i64(t0, cpu_env, vofs + i); tcg_gen_ld_i64(t0, base, vofs + i);
tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ); tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
tcg_gen_addi_i64(clean_addr, clean_addr, 8); tcg_gen_addi_i64(clean_addr, clean_addr, 8);
} }
@ -4434,11 +4447,17 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
clean_addr = new_tmp_a64_local(s); clean_addr = new_tmp_a64_local(s);
tcg_gen_mov_i64(clean_addr, t0); tcg_gen_mov_i64(clean_addr, t0);
if (base != cpu_env) {
TCGv_ptr b = tcg_temp_local_new_ptr();
tcg_gen_mov_ptr(b, base);
base = b;
}
gen_set_label(loop); gen_set_label(loop);
t0 = tcg_temp_new_i64(); t0 = tcg_temp_new_i64();
tp = tcg_temp_new_ptr(); tp = tcg_temp_new_ptr();
tcg_gen_add_ptr(tp, cpu_env, i); tcg_gen_add_ptr(tp, base, i);
tcg_gen_ld_i64(t0, tp, vofs); tcg_gen_ld_i64(t0, tp, vofs);
tcg_gen_addi_ptr(i, i, 8); tcg_gen_addi_ptr(i, i, 8);
tcg_temp_free_ptr(tp); tcg_temp_free_ptr(tp);
@ -4449,12 +4468,17 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop); tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
tcg_temp_free_ptr(i); tcg_temp_free_ptr(i);
if (base != cpu_env) {
tcg_temp_free_ptr(base);
assert(len_remain == 0);
}
} }
/* Predicate register stores can be any multiple of 2. */ /* Predicate register stores can be any multiple of 2. */
if (len_remain) { if (len_remain) {
t0 = tcg_temp_new_i64(); t0 = tcg_temp_new_i64();
tcg_gen_ld_i64(t0, cpu_env, vofs + len_align); tcg_gen_ld_i64(t0, base, vofs + len_align);
switch (len_remain) { switch (len_remain) {
case 2: case 2:
@ -4486,7 +4510,7 @@ static bool trans_LDR_zri(DisasContext *s, arg_rri *a)
if (sve_access_check(s)) { if (sve_access_check(s)) {
int size = vec_full_reg_size(s); int size = vec_full_reg_size(s);
int off = vec_full_reg_offset(s, a->rd); int off = vec_full_reg_offset(s, a->rd);
do_ldr(s, off, size, a->rn, a->imm * size); gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
} }
return true; return true;
} }
@ -4499,7 +4523,7 @@ static bool trans_LDR_pri(DisasContext *s, arg_rri *a)
if (sve_access_check(s)) { if (sve_access_check(s)) {
int size = pred_full_reg_size(s); int size = pred_full_reg_size(s);
int off = pred_full_reg_offset(s, a->rd); int off = pred_full_reg_offset(s, a->rd);
do_ldr(s, off, size, a->rn, a->imm * size); gen_sve_ldr(s, cpu_env, off, size, a->rn, a->imm * size);
} }
return true; return true;
} }
@ -4512,7 +4536,7 @@ static bool trans_STR_zri(DisasContext *s, arg_rri *a)
if (sve_access_check(s)) { if (sve_access_check(s)) {
int size = vec_full_reg_size(s); int size = vec_full_reg_size(s);
int off = vec_full_reg_offset(s, a->rd); int off = vec_full_reg_offset(s, a->rd);
do_str(s, off, size, a->rn, a->imm * size); gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
} }
return true; return true;
} }
@ -4525,7 +4549,7 @@ static bool trans_STR_pri(DisasContext *s, arg_rri *a)
if (sve_access_check(s)) { if (sve_access_check(s)) {
int size = pred_full_reg_size(s); int size = pred_full_reg_size(s);
int off = pred_full_reg_offset(s, a->rd); int off = pred_full_reg_offset(s, a->rd);
do_str(s, off, size, a->rn, a->imm * size); gen_sve_str(s, cpu_env, off, size, a->rn, a->imm * size);
} }
return true; return true;
} }