|
|
@ -182,9 +182,11 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Generate a call to a gvec-style helper with three vector operands. */ |
|
|
/* Generate a call to a gvec-style helper with three vector operands. */ |
|
|
void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
static void expand_3_ool(TCGv_ptr dbase, uint32_t dofs, |
|
|
uint32_t oprsz, uint32_t maxsz, int32_t data, |
|
|
TCGv_ptr abase, uint32_t aofs, |
|
|
gen_helper_gvec_3 *fn) |
|
|
TCGv_ptr bbase, uint32_t bofs, |
|
|
|
|
|
uint32_t oprsz, uint32_t maxsz, |
|
|
|
|
|
int32_t data, gen_helper_gvec_3 *fn) |
|
|
{ |
|
|
{ |
|
|
TCGv_ptr a0, a1, a2; |
|
|
TCGv_ptr a0, a1, a2; |
|
|
TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data)); |
|
|
TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data)); |
|
|
@ -193,9 +195,9 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
a1 = tcg_temp_ebb_new_ptr(); |
|
|
a1 = tcg_temp_ebb_new_ptr(); |
|
|
a2 = tcg_temp_ebb_new_ptr(); |
|
|
a2 = tcg_temp_ebb_new_ptr(); |
|
|
|
|
|
|
|
|
tcg_gen_addi_ptr(a0, tcg_env, dofs); |
|
|
tcg_gen_addi_ptr(a0, dbase, dofs); |
|
|
tcg_gen_addi_ptr(a1, tcg_env, aofs); |
|
|
tcg_gen_addi_ptr(a1, abase, aofs); |
|
|
tcg_gen_addi_ptr(a2, tcg_env, bofs); |
|
|
tcg_gen_addi_ptr(a2, bbase, bofs); |
|
|
|
|
|
|
|
|
fn(a0, a1, a2, desc); |
|
|
fn(a0, a1, a2, desc); |
|
|
|
|
|
|
|
|
@ -204,6 +206,14 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
tcg_temp_free_ptr(a2); |
|
|
tcg_temp_free_ptr(a2); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
|
|
|
uint32_t oprsz, uint32_t maxsz, int32_t data, |
|
|
|
|
|
gen_helper_gvec_3 *fn) |
|
|
|
|
|
{ |
|
|
|
|
|
expand_3_ool(tcg_env, dofs, tcg_env, aofs, tcg_env, bofs, |
|
|
|
|
|
oprsz, maxsz, data, fn); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* Generate a call to a gvec-style helper with four vector operands. */ |
|
|
/* Generate a call to a gvec-style helper with four vector operands. */ |
|
|
void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
uint32_t cofs, uint32_t oprsz, uint32_t maxsz, |
|
|
uint32_t cofs, uint32_t oprsz, uint32_t maxsz, |
|
|
@ -794,8 +804,10 @@ static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ |
|
|
/* Expand OPSZ bytes worth of three-operand operations using i32 elements. */ |
|
|
static void expand_3_i32(uint32_t dofs, uint32_t aofs, |
|
|
static void expand_3_i32(TCGv_ptr dbase, uint32_t dofs, |
|
|
uint32_t bofs, uint32_t oprsz, bool load_dest, |
|
|
TCGv_ptr abase, uint32_t aofs, |
|
|
|
|
|
TCGv_ptr bbase, uint32_t bofs, |
|
|
|
|
|
uint32_t oprsz, bool load_dest, |
|
|
void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32)) |
|
|
void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32)) |
|
|
{ |
|
|
{ |
|
|
TCGv_i32 t0 = tcg_temp_new_i32(); |
|
|
TCGv_i32 t0 = tcg_temp_new_i32(); |
|
|
@ -804,13 +816,13 @@ static void expand_3_i32(uint32_t dofs, uint32_t aofs, |
|
|
uint32_t i; |
|
|
uint32_t i; |
|
|
|
|
|
|
|
|
for (i = 0; i < oprsz; i += 4) { |
|
|
for (i = 0; i < oprsz; i += 4) { |
|
|
tcg_gen_ld_i32(t0, tcg_env, aofs + i); |
|
|
tcg_gen_ld_i32(t0, abase, aofs + i); |
|
|
tcg_gen_ld_i32(t1, tcg_env, bofs + i); |
|
|
tcg_gen_ld_i32(t1, bbase, bofs + i); |
|
|
if (load_dest) { |
|
|
if (load_dest) { |
|
|
tcg_gen_ld_i32(t2, tcg_env, dofs + i); |
|
|
tcg_gen_ld_i32(t2, dbase, dofs + i); |
|
|
} |
|
|
} |
|
|
fni(t2, t0, t1); |
|
|
fni(t2, t0, t1); |
|
|
tcg_gen_st_i32(t2, tcg_env, dofs + i); |
|
|
tcg_gen_st_i32(t2, dbase, dofs + i); |
|
|
} |
|
|
} |
|
|
tcg_temp_free_i32(t2); |
|
|
tcg_temp_free_i32(t2); |
|
|
tcg_temp_free_i32(t1); |
|
|
tcg_temp_free_i32(t1); |
|
|
@ -958,8 +970,10 @@ static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Expand OPSZ bytes worth of three-operand operations using i64 elements. */ |
|
|
/* Expand OPSZ bytes worth of three-operand operations using i64 elements. */ |
|
|
static void expand_3_i64(uint32_t dofs, uint32_t aofs, |
|
|
static void expand_3_i64(TCGv_ptr dbase, uint32_t dofs, |
|
|
uint32_t bofs, uint32_t oprsz, bool load_dest, |
|
|
TCGv_ptr abase, uint32_t aofs, |
|
|
|
|
|
TCGv_ptr bbase, uint32_t bofs, |
|
|
|
|
|
uint32_t oprsz, bool load_dest, |
|
|
void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64)) |
|
|
void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64)) |
|
|
{ |
|
|
{ |
|
|
TCGv_i64 t0 = tcg_temp_new_i64(); |
|
|
TCGv_i64 t0 = tcg_temp_new_i64(); |
|
|
@ -968,13 +982,13 @@ static void expand_3_i64(uint32_t dofs, uint32_t aofs, |
|
|
uint32_t i; |
|
|
uint32_t i; |
|
|
|
|
|
|
|
|
for (i = 0; i < oprsz; i += 8) { |
|
|
for (i = 0; i < oprsz; i += 8) { |
|
|
tcg_gen_ld_i64(t0, tcg_env, aofs + i); |
|
|
tcg_gen_ld_i64(t0, abase, aofs + i); |
|
|
tcg_gen_ld_i64(t1, tcg_env, bofs + i); |
|
|
tcg_gen_ld_i64(t1, bbase, bofs + i); |
|
|
if (load_dest) { |
|
|
if (load_dest) { |
|
|
tcg_gen_ld_i64(t2, tcg_env, dofs + i); |
|
|
tcg_gen_ld_i64(t2, dbase, dofs + i); |
|
|
} |
|
|
} |
|
|
fni(t2, t0, t1); |
|
|
fni(t2, t0, t1); |
|
|
tcg_gen_st_i64(t2, tcg_env, dofs + i); |
|
|
tcg_gen_st_i64(t2, dbase, dofs + i); |
|
|
} |
|
|
} |
|
|
tcg_temp_free_i64(t2); |
|
|
tcg_temp_free_i64(t2); |
|
|
tcg_temp_free_i64(t1); |
|
|
tcg_temp_free_i64(t1); |
|
|
@ -1119,8 +1133,9 @@ static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Expand OPSZ bytes worth of three-operand operations using host vectors. */ |
|
|
/* Expand OPSZ bytes worth of three-operand operations using host vectors. */ |
|
|
static void expand_3_vec(unsigned vece, uint32_t dofs, uint32_t aofs, |
|
|
static void expand_3_vec(unsigned vece, TCGv_ptr dbase, uint32_t dofs, |
|
|
uint32_t bofs, uint32_t oprsz, |
|
|
TCGv_ptr abase, uint32_t aofs, |
|
|
|
|
|
TCGv_ptr bbase, uint32_t bofs, uint32_t oprsz, |
|
|
uint32_t tysz, TCGType type, bool load_dest, |
|
|
uint32_t tysz, TCGType type, bool load_dest, |
|
|
void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec)) |
|
|
void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec)) |
|
|
{ |
|
|
{ |
|
|
@ -1129,13 +1144,13 @@ static void expand_3_vec(unsigned vece, uint32_t dofs, uint32_t aofs, |
|
|
TCGv_vec t1 = tcg_temp_new_vec(type); |
|
|
TCGv_vec t1 = tcg_temp_new_vec(type); |
|
|
TCGv_vec t2 = tcg_temp_new_vec(type); |
|
|
TCGv_vec t2 = tcg_temp_new_vec(type); |
|
|
|
|
|
|
|
|
tcg_gen_ld_vec(t0, tcg_env, aofs + i); |
|
|
tcg_gen_ld_vec(t0, abase, aofs + i); |
|
|
tcg_gen_ld_vec(t1, tcg_env, bofs + i); |
|
|
tcg_gen_ld_vec(t1, bbase, bofs + i); |
|
|
if (load_dest) { |
|
|
if (load_dest) { |
|
|
tcg_gen_ld_vec(t2, tcg_env, dofs + i); |
|
|
tcg_gen_ld_vec(t2, dbase, dofs + i); |
|
|
} |
|
|
} |
|
|
fni(vece, t2, t0, t1); |
|
|
fni(vece, t2, t0, t1); |
|
|
tcg_gen_st_vec(t2, tcg_env, dofs + i); |
|
|
tcg_gen_st_vec(t2, dbase, dofs + i); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1437,7 +1452,9 @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Expand a vector three-operand operation. */ |
|
|
/* Expand a vector three-operand operation. */ |
|
|
void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
void tcg_gen_gvec_3_var(TCGv_ptr dbase, uint32_t dofs, |
|
|
|
|
|
TCGv_ptr abase, uint32_t aofs, |
|
|
|
|
|
TCGv_ptr bbase, uint32_t bofs, |
|
|
uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g) |
|
|
uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g) |
|
|
{ |
|
|
{ |
|
|
const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; |
|
|
const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty; |
|
|
@ -1446,7 +1463,7 @@ void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
uint32_t some; |
|
|
uint32_t some; |
|
|
|
|
|
|
|
|
check_size_align(oprsz, maxsz, dofs | aofs | bofs); |
|
|
check_size_align(oprsz, maxsz, dofs | aofs | bofs); |
|
|
check_overlap_3(tcg_env, dofs, tcg_env, aofs, tcg_env, bofs, maxsz); |
|
|
check_overlap_3(dbase, dofs, abase, aofs, bbase, bofs, maxsz); |
|
|
|
|
|
|
|
|
type = 0; |
|
|
type = 0; |
|
|
if (g->fniv) { |
|
|
if (g->fniv) { |
|
|
@ -1459,8 +1476,8 @@ void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
* that e.g. size == 80 would be expanded with 2x32 + 1x16. |
|
|
* that e.g. size == 80 would be expanded with 2x32 + 1x16. |
|
|
*/ |
|
|
*/ |
|
|
some = QEMU_ALIGN_DOWN(oprsz, 32); |
|
|
some = QEMU_ALIGN_DOWN(oprsz, 32); |
|
|
expand_3_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, |
|
|
expand_3_vec(g->vece, dbase, dofs, abase, aofs, bbase, bofs, |
|
|
g->load_dest, g->fniv); |
|
|
some, 32, TCG_TYPE_V256, g->load_dest, g->fniv); |
|
|
if (some == oprsz) { |
|
|
if (some == oprsz) { |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
@ -1471,23 +1488,25 @@ void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
maxsz -= some; |
|
|
maxsz -= some; |
|
|
/* fallthru */ |
|
|
/* fallthru */ |
|
|
case TCG_TYPE_V128: |
|
|
case TCG_TYPE_V128: |
|
|
expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, |
|
|
expand_3_vec(g->vece, dbase, dofs, abase, aofs, bbase, bofs, |
|
|
g->load_dest, g->fniv); |
|
|
oprsz, 16, TCG_TYPE_V128, g->load_dest, g->fniv); |
|
|
break; |
|
|
break; |
|
|
case TCG_TYPE_V64: |
|
|
case TCG_TYPE_V64: |
|
|
expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, |
|
|
expand_3_vec(g->vece, dbase, dofs, abase, aofs, bbase, bofs, |
|
|
g->load_dest, g->fniv); |
|
|
oprsz, 8, TCG_TYPE_V64, g->load_dest, g->fniv); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 0: |
|
|
case 0: |
|
|
if (g->fni8 && check_size_impl(oprsz, 8)) { |
|
|
if (g->fni8 && check_size_impl(oprsz, 8)) { |
|
|
expand_3_i64(dofs, aofs, bofs, oprsz, g->load_dest, g->fni8); |
|
|
expand_3_i64(dbase, dofs, abase, aofs, bbase, bofs, |
|
|
|
|
|
oprsz, g->load_dest, g->fni8); |
|
|
} else if (g->fni4 && check_size_impl(oprsz, 4)) { |
|
|
} else if (g->fni4 && check_size_impl(oprsz, 4)) { |
|
|
expand_3_i32(dofs, aofs, bofs, oprsz, g->load_dest, g->fni4); |
|
|
expand_3_i32(dbase, dofs, abase, aofs, bbase, bofs, |
|
|
|
|
|
oprsz, g->load_dest, g->fni4); |
|
|
} else { |
|
|
} else { |
|
|
assert(g->fno != NULL); |
|
|
assert(g->fno != NULL); |
|
|
tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, |
|
|
expand_3_ool(dbase, dofs, abase, aofs, bbase, bofs, |
|
|
maxsz, g->data, g->fno); |
|
|
oprsz, maxsz, g->data, g->fno); |
|
|
oprsz = maxsz; |
|
|
oprsz = maxsz; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
@ -1498,10 +1517,17 @@ void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
tcg_swap_vecop_list(hold_list); |
|
|
tcg_swap_vecop_list(hold_list); |
|
|
|
|
|
|
|
|
if (oprsz < maxsz) { |
|
|
if (oprsz < maxsz) { |
|
|
expand_clr(tcg_env, dofs + oprsz, maxsz - oprsz); |
|
|
expand_clr(dbase, dofs + oprsz, maxsz - oprsz); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
|
|
|
uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g) |
|
|
|
|
|
{ |
|
|
|
|
|
tcg_gen_gvec_3_var(tcg_env, dofs, tcg_env, aofs, tcg_env, bofs, |
|
|
|
|
|
oprsz, maxsz, g); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* Expand a vector operation with three vectors and an immediate. */ |
|
|
/* Expand a vector operation with three vectors and an immediate. */ |
|
|
void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs, |
|
|
uint32_t oprsz, uint32_t maxsz, int64_t c, |
|
|
uint32_t oprsz, uint32_t maxsz, int64_t c, |
|
|
|