mirror of https://github.com/xemu-project/xemu.git
target/arm: Vectorize SABA/UABA
Include 64-bit element size in preparation for SVE2. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20200513163245.17915-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
50c160d44e
commit
cfdb2c0c95
|
@ -284,13 +284,6 @@ DEF_HELPER_2(neon_pmax_s8, i32, i32, i32)
|
||||||
DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
|
DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
|
||||||
DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
|
DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
|
||||||
|
|
||||||
DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
|
|
||||||
DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
|
|
||||||
DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
|
|
||||||
DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
|
|
||||||
DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
|
|
||||||
DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
|
|
||||||
|
|
||||||
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
|
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
|
||||||
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
|
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
|
||||||
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
|
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
|
||||||
|
@ -741,6 +734,16 @@ DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_saba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_saba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_saba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_saba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_uaba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_uaba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_uaba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
DEF_HELPER_FLAGS_4(gvec_uaba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
#ifdef TARGET_AARCH64
|
||||||
#include "helper-a64.h"
|
#include "helper-a64.h"
|
||||||
#include "helper-sve.h"
|
#include "helper-sve.h"
|
||||||
|
|
|
@ -576,16 +576,6 @@ NEON_POP(pmax_s16, neon_s16, 2)
|
||||||
NEON_POP(pmax_u16, neon_u16, 2)
|
NEON_POP(pmax_u16, neon_u16, 2)
|
||||||
#undef NEON_FN
|
#undef NEON_FN
|
||||||
|
|
||||||
#define NEON_FN(dest, src1, src2) \
|
|
||||||
dest = (src1 > src2) ? (src1 - src2) : (src2 - src1)
|
|
||||||
NEON_VOP(abd_s8, neon_s8, 4)
|
|
||||||
NEON_VOP(abd_u8, neon_u8, 4)
|
|
||||||
NEON_VOP(abd_s16, neon_s16, 2)
|
|
||||||
NEON_VOP(abd_u16, neon_u16, 2)
|
|
||||||
NEON_VOP(abd_s32, neon_s32, 1)
|
|
||||||
NEON_VOP(abd_u32, neon_u32, 1)
|
|
||||||
#undef NEON_FN
|
|
||||||
|
|
||||||
#define NEON_FN(dest, src1, src2) do { \
|
#define NEON_FN(dest, src1, src2) do { \
|
||||||
int8_t tmp; \
|
int8_t tmp; \
|
||||||
tmp = (int8_t)src2; \
|
tmp = (int8_t)src2; \
|
||||||
|
|
|
@ -11197,6 +11197,13 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
|
||||||
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
|
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
case 0xf: /* SABA, UABA */
|
||||||
|
if (u) {
|
||||||
|
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uaba, size);
|
||||||
|
} else {
|
||||||
|
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_saba, size);
|
||||||
|
}
|
||||||
|
return;
|
||||||
case 0x10: /* ADD, SUB */
|
case 0x10: /* ADD, SUB */
|
||||||
if (u) {
|
if (u) {
|
||||||
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
|
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
|
||||||
|
@ -11329,16 +11336,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
|
||||||
genenvfn = fns[size][u];
|
genenvfn = fns[size][u];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xf: /* SABA, UABA */
|
|
||||||
{
|
|
||||||
static NeonGenTwoOpFn * const fns[3][2] = {
|
|
||||||
{ gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
|
|
||||||
{ gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
|
|
||||||
{ gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
|
|
||||||
};
|
|
||||||
genfn = fns[size][u];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x16: /* SQDMULH, SQRDMULH */
|
case 0x16: /* SQDMULH, SQRDMULH */
|
||||||
{
|
{
|
||||||
static NeonGenTwoOpEnvFn * const fns[2][2] = {
|
static NeonGenTwoOpEnvFn * const fns[2][2] = {
|
||||||
|
|
|
@ -5222,6 +5222,124 @@ void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||||
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
|
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
|
||||||
|
{
|
||||||
|
TCGv_i32 t = tcg_temp_new_i32();
|
||||||
|
gen_sabd_i32(t, a, b);
|
||||||
|
tcg_gen_add_i32(d, d, t);
|
||||||
|
tcg_temp_free_i32(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
|
||||||
|
{
|
||||||
|
TCGv_i64 t = tcg_temp_new_i64();
|
||||||
|
gen_sabd_i64(t, a, b);
|
||||||
|
tcg_gen_add_i64(d, d, t);
|
||||||
|
tcg_temp_free_i64(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
|
||||||
|
{
|
||||||
|
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||||
|
gen_sabd_vec(vece, t, a, b);
|
||||||
|
tcg_gen_add_vec(vece, d, d, t);
|
||||||
|
tcg_temp_free_vec(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||||
|
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
|
||||||
|
{
|
||||||
|
static const TCGOpcode vecop_list[] = {
|
||||||
|
INDEX_op_sub_vec, INDEX_op_add_vec,
|
||||||
|
INDEX_op_smin_vec, INDEX_op_smax_vec, 0
|
||||||
|
};
|
||||||
|
static const GVecGen3 ops[4] = {
|
||||||
|
{ .fniv = gen_saba_vec,
|
||||||
|
.fno = gen_helper_gvec_saba_b,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_8 },
|
||||||
|
{ .fniv = gen_saba_vec,
|
||||||
|
.fno = gen_helper_gvec_saba_h,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_16 },
|
||||||
|
{ .fni4 = gen_saba_i32,
|
||||||
|
.fniv = gen_saba_vec,
|
||||||
|
.fno = gen_helper_gvec_saba_s,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_32 },
|
||||||
|
{ .fni8 = gen_saba_i64,
|
||||||
|
.fniv = gen_saba_vec,
|
||||||
|
.fno = gen_helper_gvec_saba_d,
|
||||||
|
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_64 },
|
||||||
|
};
|
||||||
|
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
|
||||||
|
{
|
||||||
|
TCGv_i32 t = tcg_temp_new_i32();
|
||||||
|
gen_uabd_i32(t, a, b);
|
||||||
|
tcg_gen_add_i32(d, d, t);
|
||||||
|
tcg_temp_free_i32(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
|
||||||
|
{
|
||||||
|
TCGv_i64 t = tcg_temp_new_i64();
|
||||||
|
gen_uabd_i64(t, a, b);
|
||||||
|
tcg_gen_add_i64(d, d, t);
|
||||||
|
tcg_temp_free_i64(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
|
||||||
|
{
|
||||||
|
TCGv_vec t = tcg_temp_new_vec_matching(d);
|
||||||
|
gen_uabd_vec(vece, t, a, b);
|
||||||
|
tcg_gen_add_vec(vece, d, d, t);
|
||||||
|
tcg_temp_free_vec(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||||
|
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
|
||||||
|
{
|
||||||
|
static const TCGOpcode vecop_list[] = {
|
||||||
|
INDEX_op_sub_vec, INDEX_op_add_vec,
|
||||||
|
INDEX_op_umin_vec, INDEX_op_umax_vec, 0
|
||||||
|
};
|
||||||
|
static const GVecGen3 ops[4] = {
|
||||||
|
{ .fniv = gen_uaba_vec,
|
||||||
|
.fno = gen_helper_gvec_uaba_b,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_8 },
|
||||||
|
{ .fniv = gen_uaba_vec,
|
||||||
|
.fno = gen_helper_gvec_uaba_h,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_16 },
|
||||||
|
{ .fni4 = gen_uaba_i32,
|
||||||
|
.fniv = gen_uaba_vec,
|
||||||
|
.fno = gen_helper_gvec_uaba_s,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_32 },
|
||||||
|
{ .fni8 = gen_uaba_i64,
|
||||||
|
.fniv = gen_uaba_vec,
|
||||||
|
.fno = gen_helper_gvec_uaba_d,
|
||||||
|
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
|
||||||
|
.opt_opc = vecop_list,
|
||||||
|
.load_dest = true,
|
||||||
|
.vece = MO_64 },
|
||||||
|
};
|
||||||
|
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
|
||||||
|
}
|
||||||
|
|
||||||
/* Translate a NEON data processing instruction. Return nonzero if the
|
/* Translate a NEON data processing instruction. Return nonzero if the
|
||||||
instruction is invalid.
|
instruction is invalid.
|
||||||
We process data in a mixture of 32-bit and 64-bit chunks.
|
We process data in a mixture of 32-bit and 64-bit chunks.
|
||||||
|
@ -5366,6 +5484,16 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case NEON_3R_VABA:
|
||||||
|
if (u) {
|
||||||
|
gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs,
|
||||||
|
vec_size, vec_size);
|
||||||
|
} else {
|
||||||
|
gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs,
|
||||||
|
vec_size, vec_size);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
case NEON_3R_VADD_VSUB:
|
case NEON_3R_VADD_VSUB:
|
||||||
case NEON_3R_LOGIC:
|
case NEON_3R_LOGIC:
|
||||||
case NEON_3R_VMAX:
|
case NEON_3R_VMAX:
|
||||||
|
@ -5510,12 +5638,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
|
||||||
case NEON_3R_VQRSHL:
|
case NEON_3R_VQRSHL:
|
||||||
GEN_NEON_INTEGER_OP_ENV(qrshl);
|
GEN_NEON_INTEGER_OP_ENV(qrshl);
|
||||||
break;
|
break;
|
||||||
case NEON_3R_VABA:
|
|
||||||
GEN_NEON_INTEGER_OP(abd);
|
|
||||||
tcg_temp_free_i32(tmp2);
|
|
||||||
tmp2 = neon_load_reg(rd, pass);
|
|
||||||
gen_neon_add(size, tmp, tmp2);
|
|
||||||
break;
|
|
||||||
case NEON_3R_VPMAX:
|
case NEON_3R_VPMAX:
|
||||||
GEN_NEON_INTEGER_OP(pmax);
|
GEN_NEON_INTEGER_OP(pmax);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -342,6 +342,11 @@ void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||||
void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
void gen_gvec_uabd(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);
|
||||||
|
|
||||||
|
void gen_gvec_saba(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_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
|
||||||
|
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward to the isar_feature_* tests given a DisasContext pointer.
|
* Forward to the isar_feature_* tests given a DisasContext pointer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1431,3 +1431,27 @@ DO_ABD(gvec_uabd_s, uint32_t)
|
||||||
DO_ABD(gvec_uabd_d, uint64_t)
|
DO_ABD(gvec_uabd_d, uint64_t)
|
||||||
|
|
||||||
#undef DO_ABD
|
#undef DO_ABD
|
||||||
|
|
||||||
|
#define DO_ABA(NAME, TYPE) \
|
||||||
|
void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
|
||||||
|
{ \
|
||||||
|
intptr_t i, opr_sz = simd_oprsz(desc); \
|
||||||
|
TYPE *d = vd, *n = vn, *m = vm; \
|
||||||
|
\
|
||||||
|
for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
|
||||||
|
d[i] += n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
|
||||||
|
} \
|
||||||
|
clear_tail(d, opr_sz, simd_maxsz(desc)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
DO_ABA(gvec_saba_b, int8_t)
|
||||||
|
DO_ABA(gvec_saba_h, int16_t)
|
||||||
|
DO_ABA(gvec_saba_s, int32_t)
|
||||||
|
DO_ABA(gvec_saba_d, int64_t)
|
||||||
|
|
||||||
|
DO_ABA(gvec_uaba_b, uint8_t)
|
||||||
|
DO_ABA(gvec_uaba_h, uint16_t)
|
||||||
|
DO_ABA(gvec_uaba_s, uint32_t)
|
||||||
|
DO_ABA(gvec_uaba_d, uint64_t)
|
||||||
|
|
||||||
|
#undef DO_ABA
|
||||||
|
|
Loading…
Reference in New Issue