From cd79d2a91588d009d665be157b1e05e9d52921a7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 1 Mar 2021 18:09:12 -0500 Subject: [PATCH] tcg: Implement 256-bit dup for tcg_gen_gvec_dup_mem We already support duplication of 128-bit blocks. This extends that support to 256-bit blocks. This will be needed by SVE2. Backports commit fe4b0b5bfa96c38ad1cad0689a86cca9f307e353 --- qemu/tcg/tcg-op-gvec.c | 52 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/qemu/tcg/tcg-op-gvec.c b/qemu/tcg/tcg-op-gvec.c index 809fef66..b27c47f9 100644 --- a/qemu/tcg/tcg-op-gvec.c +++ b/qemu/tcg/tcg-op-gvec.c @@ -1571,12 +1571,10 @@ void tcg_gen_gvec_dup_mem(TCGContext *s, unsigned vece, uint32_t dofs, uint32_t do_dup(s, vece, dofs, oprsz, maxsz, NULL, in, 0); tcg_temp_free_i64(s, in); } - } else { + } else if (vece == 4) { /* 128-bit duplicate. */ - /* ??? Dup to 256-bit vector. */ int i; - tcg_debug_assert(vece == 4); tcg_debug_assert(oprsz >= 16); if (TCG_TARGET_HAS_v128) { TCGv_vec in = tcg_temp_new_vec(s, TCG_TYPE_V128); @@ -1602,6 +1600,54 @@ void tcg_gen_gvec_dup_mem(TCGContext *s, unsigned vece, uint32_t dofs, uint32_t if (oprsz < maxsz) { expand_clr(s, dofs + oprsz, maxsz - oprsz); } + } else if (vece == 5) { + /* 256-bit duplicate. */ + int i; + + tcg_debug_assert(oprsz >= 32); + tcg_debug_assert(oprsz % 32 == 0); + if (TCG_TARGET_HAS_v256) { + TCGv_vec in = tcg_temp_new_vec(s, TCG_TYPE_V256); + + tcg_gen_ld_vec(s, in, s->cpu_env, aofs); + for (i = (aofs == dofs) * 32; i < oprsz; i += 32) { + tcg_gen_st_vec(s, in, s->cpu_env, dofs + i); + } + tcg_temp_free_vec(s, in); + } else if (TCG_TARGET_HAS_v128) { + TCGv_vec in0 = tcg_temp_new_vec(s, TCG_TYPE_V128); + TCGv_vec in1 = tcg_temp_new_vec(s, TCG_TYPE_V128); + + tcg_gen_ld_vec(s, in0, s->cpu_env, aofs); + tcg_gen_ld_vec(s, in1, s->cpu_env, aofs + 16); + for (i = (aofs == dofs) * 32; i < oprsz; i += 32) { + tcg_gen_st_vec(s, in0, s->cpu_env, dofs + i); + tcg_gen_st_vec(s, in1, s->cpu_env, dofs + i + 16); + } + tcg_temp_free_vec(s, in0); + tcg_temp_free_vec(s, in1); + } else { + TCGv_i64 in[4]; + int j; + + for (j = 0; j < 4; ++j) { + in[j] = tcg_temp_new_i64(s); + tcg_gen_ld_i64(s, in[j], s->cpu_env, aofs + j * 8); + } + for (i = (aofs == dofs) * 32; i < oprsz; i += 32) { + for (j = 0; j < 4; ++j) { + tcg_gen_st_i64(s, in[j], s->cpu_env, dofs + i + j * 8); + } + } + for (j = 0; j < 4; ++j) { + tcg_temp_free_i64(s, in[j]); + } + } + if (oprsz < maxsz) { + expand_clr(s, dofs + oprsz, maxsz - oprsz); + } + } else { + g_assert_not_reached(); } }