summaryrefslogtreecommitdiff
path: root/tcg/tcg-op-gvec.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2019-05-16 12:48:18 -0700
committerRichard Henderson <richard.henderson@linaro.org>2019-05-22 15:09:43 -0400
commit532ba368a13712724137228b5e7e9435994d25e1 (patch)
treeb21f05b89e2c6d34012993f04dce8eda529018d9 /tcg/tcg-op-gvec.c
parent7b60ef3264e9627ac6efb34e9a6130647e9b55c0 (diff)
downloadqemu-532ba368a13712724137228b5e7e9435994d25e1.zip
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}. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tcg/tcg-op-gvec.c')
-rw-r--r--tcg/tcg-op-gvec.c48
1 files changed, 25 insertions, 23 deletions
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 338ddd9d9e..bbf70e3cd9 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -1446,36 +1446,35 @@ void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t oprsz,
void tcg_gen_gvec_dup_mem(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(type);
tcg_gen_dup_mem_vec(vece, t_vec, cpu_env, aofs);
do_dup_store(type, dofs, oprsz, maxsz, t_vec);
tcg_temp_free_vec(t_vec);
- return;
- }
- }
- if (vece <= MO_32) {
- TCGv_i32 in = tcg_temp_new_i32();
- switch (vece) {
- case MO_8:
- tcg_gen_ld8u_i32(in, cpu_env, aofs);
- break;
- case MO_16:
- tcg_gen_ld16u_i32(in, cpu_env, aofs);
- break;
- case MO_32:
- tcg_gen_ld_i32(in, cpu_env, aofs);
- break;
+ } else if (vece <= MO_32) {
+ TCGv_i32 in = tcg_temp_new_i32();
+ switch (vece) {
+ case MO_8:
+ tcg_gen_ld8u_i32(in, cpu_env, aofs);
+ break;
+ case MO_16:
+ tcg_gen_ld16u_i32(in, cpu_env, aofs);
+ break;
+ default:
+ tcg_gen_ld_i32(in, cpu_env, aofs);
+ break;
+ }
+ do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0);
+ tcg_temp_free_i32(in);
+ } else {
+ TCGv_i64 in = tcg_temp_new_i64();
+ tcg_gen_ld_i64(in, cpu_env, aofs);
+ do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0);
+ tcg_temp_free_i64(in);
}
- tcg_gen_gvec_dup_i32(vece, dofs, oprsz, maxsz, in);
- tcg_temp_free_i32(in);
- } else if (vece == MO_64) {
- TCGv_i64 in = tcg_temp_new_i64();
- tcg_gen_ld_i64(in, cpu_env, aofs);
- tcg_gen_gvec_dup_i64(MO_64, dofs, oprsz, maxsz, in);
- tcg_temp_free_i64(in);
} else {
/* 128-bit duplicate. */
/* ??? Dup to 256-bit vector. */
@@ -1504,6 +1503,9 @@ void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs,
tcg_temp_free_i64(in0);
tcg_temp_free_i64(in1);
}
+ if (oprsz < maxsz) {
+ expand_clr(dofs + oprsz, maxsz - oprsz);
+ }
}
}