mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-22 20:41:04 +00:00
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
This commit is contained in:
parent
60cfe541b2
commit
fa363c3d6d
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue