target/arm: Create gen_gvec_{cmtst,ushl,sshl}

Provide a functional interface for the vector expansion.
This fits better with the existing set of helpers that
we provide for other operations.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200513163245.17915-10-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2020-05-13 09:32:38 -07:00 committed by Peter Maydell
parent e9eee5316f
commit 8161b75357
4 changed files with 95 additions and 102 deletions

View file

@ -577,15 +577,6 @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
is_q ? 16 : 8, vec_full_reg_size(s)); is_q ? 16 : 8, vec_full_reg_size(s));
} }
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
int rn, int rm, const GVecGen3 *gvec_op)
{
tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
vec_full_reg_offset(s, rm), is_q ? 16 : 8,
vec_full_reg_size(s), gvec_op);
}
/* Expand a 3-operand operation using an out-of-line helper. */ /* Expand a 3-operand operation using an out-of-line helper. */
static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd, static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
int rn, int rm, int data, gen_helper_gvec_3 *fn) int rn, int rm, int data, gen_helper_gvec_3 *fn)
@ -11193,8 +11184,11 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
(u ? uqsub_op : sqsub_op) + size); (u ? uqsub_op : sqsub_op) + size);
return; return;
case 0x08: /* SSHL, USHL */ case 0x08: /* SSHL, USHL */
gen_gvec_op3(s, is_q, rd, rn, rm, if (u) {
u ? &ushl_op[size] : &sshl_op[size]); gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_ushl, size);
} else {
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sshl, size);
}
return; return;
case 0x0c: /* SMAX, UMAX */ case 0x0c: /* SMAX, UMAX */
if (u) { if (u) {
@ -11233,7 +11227,7 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
return; return;
case 0x11: case 0x11:
if (!u) { /* CMTST */ if (!u) { /* CMTST */
gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]); gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_cmtst, size);
return; return;
} }
/* else CMEQ */ /* else CMEQ */

View file

@ -603,6 +603,8 @@ DO_3SAME(VBIC, tcg_gen_gvec_andc)
DO_3SAME(VORR, tcg_gen_gvec_or) DO_3SAME(VORR, tcg_gen_gvec_or)
DO_3SAME(VORN, tcg_gen_gvec_orc) DO_3SAME(VORN, tcg_gen_gvec_orc)
DO_3SAME(VEOR, tcg_gen_gvec_xor) DO_3SAME(VEOR, tcg_gen_gvec_xor)
DO_3SAME(VSHL_S, gen_gvec_sshl)
DO_3SAME(VSHL_U, gen_gvec_ushl)
/* These insns are all gvec_bitsel but with the inputs in various orders. */ /* These insns are all gvec_bitsel but with the inputs in various orders. */
#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \ #define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
@ -634,6 +636,7 @@ DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul) DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla) DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls) DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
#define DO_3SAME_CMP(INSN, COND) \ #define DO_3SAME_CMP(INSN, COND) \
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
@ -650,13 +653,6 @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU) DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
DO_3SAME_CMP(VCEQ, TCG_COND_EQ) DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
{
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]);
}
DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s)
#define DO_3SAME_GVEC4(INSN, OPARRAY) \ #define DO_3SAME_GVEC4(INSN, OPARRAY) \
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
uint32_t rn_ofs, uint32_t rm_ofs, \ uint32_t rn_ofs, uint32_t rm_ofs, \
@ -686,16 +682,3 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
} }
return do_3same(s, a, gen_VMUL_p_3s); return do_3same(s, a, gen_VMUL_p_3s);
} }
#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
uint32_t rn_ofs, uint32_t rm_ofs, \
uint32_t oprsz, uint32_t maxsz) \
{ \
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
oprsz, maxsz, &OPARRAY[vece]); \
} \
DO_3SAME(INSN, gen_##INSN##_3s)
DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op)
DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op)

View file

@ -4606,27 +4606,31 @@ static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a); tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
} }
static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 }; void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
const GVecGen3 cmtst_op[4] = { {
{ .fni4 = gen_helper_neon_tst_u8, static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
.fniv = gen_cmtst_vec, static const GVecGen3 ops[4] = {
.opt_opc = vecop_list_cmtst, { .fni4 = gen_helper_neon_tst_u8,
.vece = MO_8 }, .fniv = gen_cmtst_vec,
{ .fni4 = gen_helper_neon_tst_u16, .opt_opc = vecop_list,
.fniv = gen_cmtst_vec, .vece = MO_8 },
.opt_opc = vecop_list_cmtst, { .fni4 = gen_helper_neon_tst_u16,
.vece = MO_16 }, .fniv = gen_cmtst_vec,
{ .fni4 = gen_cmtst_i32, .opt_opc = vecop_list,
.fniv = gen_cmtst_vec, .vece = MO_16 },
.opt_opc = vecop_list_cmtst, { .fni4 = gen_cmtst_i32,
.vece = MO_32 }, .fniv = gen_cmtst_vec,
{ .fni8 = gen_cmtst_i64, .opt_opc = vecop_list,
.fniv = gen_cmtst_vec, .vece = MO_32 },
.prefer_i64 = TCG_TARGET_REG_BITS == 64, { .fni8 = gen_cmtst_i64,
.opt_opc = vecop_list_cmtst, .fniv = gen_cmtst_vec,
.vece = MO_64 }, .prefer_i64 = TCG_TARGET_REG_BITS == 64,
}; .opt_opc = vecop_list,
.vece = MO_64 },
};
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
}
void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift) void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
{ {
@ -4744,29 +4748,33 @@ static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
tcg_temp_free_vec(rsh); tcg_temp_free_vec(rsh);
} }
static const TCGOpcode ushl_list[] = { void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
INDEX_op_neg_vec, INDEX_op_shlv_vec, uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0 {
}; static const TCGOpcode vecop_list[] = {
INDEX_op_neg_vec, INDEX_op_shlv_vec,
const GVecGen3 ushl_op[4] = { INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
{ .fniv = gen_ushl_vec, };
.fno = gen_helper_gvec_ushl_b, static const GVecGen3 ops[4] = {
.opt_opc = ushl_list, { .fniv = gen_ushl_vec,
.vece = MO_8 }, .fno = gen_helper_gvec_ushl_b,
{ .fniv = gen_ushl_vec, .opt_opc = vecop_list,
.fno = gen_helper_gvec_ushl_h, .vece = MO_8 },
.opt_opc = ushl_list, { .fniv = gen_ushl_vec,
.vece = MO_16 }, .fno = gen_helper_gvec_ushl_h,
{ .fni4 = gen_ushl_i32, .opt_opc = vecop_list,
.fniv = gen_ushl_vec, .vece = MO_16 },
.opt_opc = ushl_list, { .fni4 = gen_ushl_i32,
.vece = MO_32 }, .fniv = gen_ushl_vec,
{ .fni8 = gen_ushl_i64, .opt_opc = vecop_list,
.fniv = gen_ushl_vec, .vece = MO_32 },
.opt_opc = ushl_list, { .fni8 = gen_ushl_i64,
.vece = MO_64 }, .fniv = gen_ushl_vec,
}; .opt_opc = vecop_list,
.vece = MO_64 },
};
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
}
void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift) void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
{ {
@ -4878,29 +4886,33 @@ static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
tcg_temp_free_vec(tmp); tcg_temp_free_vec(tmp);
} }
static const TCGOpcode sshl_list[] = { void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec, uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0 {
}; static const TCGOpcode vecop_list[] = {
INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
const GVecGen3 sshl_op[4] = { INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
{ .fniv = gen_sshl_vec, };
.fno = gen_helper_gvec_sshl_b, static const GVecGen3 ops[4] = {
.opt_opc = sshl_list, { .fniv = gen_sshl_vec,
.vece = MO_8 }, .fno = gen_helper_gvec_sshl_b,
{ .fniv = gen_sshl_vec, .opt_opc = vecop_list,
.fno = gen_helper_gvec_sshl_h, .vece = MO_8 },
.opt_opc = sshl_list, { .fniv = gen_sshl_vec,
.vece = MO_16 }, .fno = gen_helper_gvec_sshl_h,
{ .fni4 = gen_sshl_i32, .opt_opc = vecop_list,
.fniv = gen_sshl_vec, .vece = MO_16 },
.opt_opc = sshl_list, { .fni4 = gen_sshl_i32,
.vece = MO_32 }, .fniv = gen_sshl_vec,
{ .fni8 = gen_sshl_i64, .opt_opc = vecop_list,
.fniv = gen_sshl_vec, .vece = MO_32 },
.opt_opc = sshl_list, { .fni8 = gen_sshl_i64,
.vece = MO_64 }, .fniv = gen_sshl_vec,
}; .opt_opc = vecop_list,
.vece = MO_64 },
};
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
}
static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat, static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
TCGv_vec a, TCGv_vec b) TCGv_vec a, TCGv_vec b)

View file

@ -291,9 +291,13 @@ void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz); uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
extern const GVecGen3 cmtst_op[4]; void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
extern const GVecGen3 sshl_op[4]; uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
extern const GVecGen3 ushl_op[4]; void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
extern const GVecGen4 uqadd_op[4]; extern const GVecGen4 uqadd_op[4];
extern const GVecGen4 sqadd_op[4]; extern const GVecGen4 sqadd_op[4];
extern const GVecGen4 uqsub_op[4]; extern const GVecGen4 uqsub_op[4];