From fa363c3d6d2e0453f1b57fe13a75564091fb363e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 24 May 2019 18:07:26 -0400 Subject: [PATCH] tcg: Fix missing checks and clears in tcg_gen_gvec_dup_mem The paths through tcg_gen_dup_mem_vec and through MO_128 were missing the check_size_align. The path through MO_128 was also missing the expand_clr. This last was not visible because the only user is ARM SVE, which would set oprsz == maxsz, and not require the clear. Fix by adding the check_size_align and using do_dup directly instead of duplicating the check in tcg_gen_gvec_dup_{i32,i64}. Backports commit 532ba368a13712724137228b5e7e9435994d25e1 from qemu --- qemu/tcg/tcg-op-gvec.c | 48 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/qemu/tcg/tcg-op-gvec.c b/qemu/tcg/tcg-op-gvec.c index 4b9cfaa9..cf9b40f4 100644 --- a/qemu/tcg/tcg-op-gvec.c +++ b/qemu/tcg/tcg-op-gvec.c @@ -1446,36 +1446,35 @@ void tcg_gen_gvec_dup_i64(TCGContext *s, unsigned vece, uint32_t dofs, uint32_t void tcg_gen_gvec_dup_mem(TCGContext *s, unsigned vece, uint32_t dofs, uint32_t aofs, uint32_t oprsz, uint32_t maxsz) { + check_size_align(oprsz, maxsz, dofs); if (vece <= MO_64) { - TCGType type = choose_vector_type(0, vece, oprsz, 0); + TCGType type = choose_vector_type(NULL, vece, oprsz, 0); if (type != 0) { TCGv_vec t_vec = tcg_temp_new_vec(s, type); tcg_gen_dup_mem_vec(s, vece, t_vec, s->cpu_env, aofs); do_dup_store(s, type, dofs, oprsz, maxsz, t_vec); tcg_temp_free_vec(s, t_vec); - return; + } else if (vece <= MO_32) { + TCGv_i32 in = tcg_temp_new_i32(s); + switch (vece) { + case MO_8: + tcg_gen_ld8u_i32(s, in, s->cpu_env, aofs); + break; + case MO_16: + tcg_gen_ld16u_i32(s, in, s->cpu_env, aofs); + break; + default: + tcg_gen_ld_i32(s, in, s->cpu_env, aofs); + break; + } + do_dup(s, vece, dofs, oprsz, maxsz, in, NULL, 0); + tcg_temp_free_i32(s, in); + } else { + TCGv_i64 in = tcg_temp_new_i64(s); + tcg_gen_ld_i64(s, in, s->cpu_env, aofs); + do_dup(s, vece, dofs, oprsz, maxsz, NULL, in, 0); + tcg_temp_free_i64(s, in); } - } - if (vece <= MO_32) { - TCGv_i32 in = tcg_temp_new_i32(s); - switch (vece) { - case MO_8: - tcg_gen_ld8u_i32(s, in, s->cpu_env, aofs); - break; - case MO_16: - tcg_gen_ld16u_i32(s, in, s->cpu_env, aofs); - break; - case MO_32: - tcg_gen_ld_i32(s, in, s->cpu_env, aofs); - break; - } - tcg_gen_gvec_dup_i32(s, vece, dofs, oprsz, maxsz, in); - tcg_temp_free_i32(s, in); - } else if (vece == MO_64) { - TCGv_i64 in = tcg_temp_new_i64(s); - tcg_gen_ld_i64(s, in, s->cpu_env, aofs); - tcg_gen_gvec_dup_i64(s, MO_64, dofs, oprsz, maxsz, in); - tcg_temp_free_i64(s, in); } else { /* 128-bit duplicate. */ /* ??? Dup to 256-bit vector. */ @@ -1504,6 +1503,9 @@ void tcg_gen_gvec_dup_mem(TCGContext *s, unsigned vece, uint32_t dofs, uint32_t tcg_temp_free_i64(s, in0); tcg_temp_free_i64(s, in1); } + if (oprsz < maxsz) { + expand_clr(s, dofs + oprsz, maxsz - oprsz); + } } }