target/arm: Convert SMAXP, SMINP, UMAXP, UMINP to decodetree

These are the last instructions within handle_simd_3same_pair
so remove it.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20240524232121.284515-34-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2024-05-24 16:20:47 -07:00 committed by Peter Maydell
parent a11e54ed29
commit 28b5451bec
6 changed files with 109 additions and 102 deletions

View File

@ -1064,6 +1064,22 @@ DEF_HELPER_FLAGS_4(gvec_addp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_addp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_addp_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_smaxp_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_smaxp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_smaxp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_sminp_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_sminp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_sminp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_umaxp_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_umaxp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_umaxp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_uminp_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_uminp_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_uminp_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
#ifdef TARGET_AARCH64
#include "tcg/helper-a64.h"
#include "tcg/helper-sve.h"

View File

@ -837,6 +837,10 @@ FMINNMP_v 0.10 1110 110 ..... 00000 1 ..... ..... @qrrr_h
FMINNMP_v 0.10 1110 1.1 ..... 11000 1 ..... ..... @qrrr_sd
ADDP_v 0.00 1110 ..1 ..... 10111 1 ..... ..... @qrrr_e
SMAXP_v 0.00 1110 ..1 ..... 10100 1 ..... ..... @qrrr_e
SMINP_v 0.00 1110 ..1 ..... 10101 1 ..... ..... @qrrr_e
UMAXP_v 0.10 1110 ..1 ..... 10100 1 ..... ..... @qrrr_e
UMINP_v 0.10 1110 ..1 ..... 10101 1 ..... ..... @qrrr_e
### Advanced SIMD scalar x indexed element

View File

@ -1622,3 +1622,51 @@ void gen_gvec_addp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
};
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, 0, fns[vece]);
}
void gen_gvec_smaxp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
{
static gen_helper_gvec_3 * const fns[4] = {
gen_helper_gvec_smaxp_b,
gen_helper_gvec_smaxp_h,
gen_helper_gvec_smaxp_s,
};
tcg_debug_assert(vece <= MO_32);
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, 0, fns[vece]);
}
void gen_gvec_sminp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
{
static gen_helper_gvec_3 * const fns[4] = {
gen_helper_gvec_sminp_b,
gen_helper_gvec_sminp_h,
gen_helper_gvec_sminp_s,
};
tcg_debug_assert(vece <= MO_32);
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, 0, fns[vece]);
}
void gen_gvec_umaxp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
{
static gen_helper_gvec_3 * const fns[4] = {
gen_helper_gvec_umaxp_b,
gen_helper_gvec_umaxp_h,
gen_helper_gvec_umaxp_s,
};
tcg_debug_assert(vece <= MO_32);
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, 0, fns[vece]);
}
void gen_gvec_uminp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
{
static gen_helper_gvec_3 * const fns[4] = {
gen_helper_gvec_uminp_b,
gen_helper_gvec_uminp_h,
gen_helper_gvec_uminp_s,
};
tcg_debug_assert(vece <= MO_32);
tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, 0, fns[vece]);
}

View File

@ -1352,6 +1352,17 @@ static bool do_gvec_fn3(DisasContext *s, arg_qrrr_e *a, GVecGen3Fn *fn)
return true;
}
static bool do_gvec_fn3_no64(DisasContext *s, arg_qrrr_e *a, GVecGen3Fn *fn)
{
if (a->esz == MO_64) {
return false;
}
if (fp_access_check(s)) {
gen_gvec_fn3(s, a->q, a->rd, a->rn, a->rm, fn, a->esz);
}
return true;
}
static bool do_gvec_fn4(DisasContext *s, arg_qrrrr_e *a, GVecGen4Fn *fn)
{
if (!a->q && a->esz == MO_64) {
@ -5246,6 +5257,10 @@ static gen_helper_gvec_3_ptr * const f_vector_fminnmp[3] = {
TRANS(FMINNMP_v, do_fp3_vector, a, f_vector_fminnmp)
TRANS(ADDP_v, do_gvec_fn3, a, gen_gvec_addp)
TRANS(SMAXP_v, do_gvec_fn3_no64, a, gen_gvec_smaxp)
TRANS(SMINP_v, do_gvec_fn3_no64, a, gen_gvec_sminp)
TRANS(UMAXP_v, do_gvec_fn3_no64, a, gen_gvec_umaxp)
TRANS(UMINP_v, do_gvec_fn3_no64, a, gen_gvec_uminp)
/*
* Advanced SIMD scalar/vector x indexed element
@ -10896,84 +10911,6 @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
}
}
/* Pairwise op subgroup of C3.6.16.
*
* This is called directly for float pairwise
* operations where the opcode and size are calculated differently.
*/
static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
int size, int rn, int rm, int rd)
{
int pass;
if (!fp_access_check(s)) {
return;
}
/* These operations work on the concatenated rm:rn, with each pair of
* adjacent elements being operated on to produce an element in the result.
*/
if (size == 3) {
g_assert_not_reached();
} else {
int maxpass = is_q ? 4 : 2;
TCGv_i32 tcg_res[4];
for (pass = 0; pass < maxpass; pass++) {
TCGv_i32 tcg_op1 = tcg_temp_new_i32();
TCGv_i32 tcg_op2 = tcg_temp_new_i32();
NeonGenTwoOpFn *genfn = NULL;
int passreg = pass < (maxpass / 2) ? rn : rm;
int passelt = (is_q && (pass & 1)) ? 2 : 0;
read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_32);
read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_32);
tcg_res[pass] = tcg_temp_new_i32();
switch (opcode) {
case 0x14: /* SMAXP, UMAXP */
{
static NeonGenTwoOpFn * const fns[3][2] = {
{ gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
{ gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
{ tcg_gen_smax_i32, tcg_gen_umax_i32 },
};
genfn = fns[size][u];
break;
}
case 0x15: /* SMINP, UMINP */
{
static NeonGenTwoOpFn * const fns[3][2] = {
{ gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
{ gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
{ tcg_gen_smin_i32, tcg_gen_umin_i32 },
};
genfn = fns[size][u];
break;
}
default:
case 0x17: /* ADDP */
case 0x58: /* FMAXNMP */
case 0x5a: /* FADDP */
case 0x5e: /* FMAXP */
case 0x78: /* FMINNMP */
case 0x7e: /* FMINP */
g_assert_not_reached();
}
/* FP ops called directly, otherwise call now */
if (genfn) {
genfn(tcg_res[pass], tcg_op1, tcg_op2);
}
}
for (pass = 0; pass < maxpass; pass++) {
write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
}
clear_vec_high(s, is_q, rd);
}
}
/* Floating point op subgroup of C3.6.16. */
static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
{
@ -11314,30 +11251,6 @@ static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
case 0x3: /* logic ops */
disas_simd_3same_logic(s, insn);
break;
case 0x14: /* SMAXP, UMAXP */
case 0x15: /* SMINP, UMINP */
{
/* Pairwise operations */
int is_q = extract32(insn, 30, 1);
int u = extract32(insn, 29, 1);
int size = extract32(insn, 22, 2);
int rm = extract32(insn, 16, 5);
int rn = extract32(insn, 5, 5);
int rd = extract32(insn, 0, 5);
if (opcode == 0x17) {
if (u || (size == 3 && !is_q)) {
unallocated_encoding(s);
return;
}
} else {
if (size == 3) {
unallocated_encoding(s);
return;
}
}
handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd);
break;
}
case 0x18 ... 0x31:
/* floating point ops, sz[1] and U are part of opcode */
disas_simd_3same_float(s, insn);
@ -11345,6 +11258,8 @@ static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
default:
disas_simd_3same_int(s, insn);
break;
case 0x14: /* SMAXP, UMAXP */
case 0x15: /* SMINP, UMINP */
case 0x17: /* ADDP */
unallocated_encoding(s);
break;

View File

@ -516,6 +516,14 @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
void gen_gvec_addp(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_smaxp(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_sminp(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_umaxp(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_uminp(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.

View File

@ -2259,6 +2259,22 @@ DO_3OP_PAIR(gvec_addp_s, ADD, uint32_t, H4)
DO_3OP_PAIR(gvec_addp_d, ADD, uint64_t, )
#undef ADD
DO_3OP_PAIR(gvec_smaxp_b, MAX, int8_t, H1)
DO_3OP_PAIR(gvec_smaxp_h, MAX, int16_t, H2)
DO_3OP_PAIR(gvec_smaxp_s, MAX, int32_t, H4)
DO_3OP_PAIR(gvec_umaxp_b, MAX, uint8_t, H1)
DO_3OP_PAIR(gvec_umaxp_h, MAX, uint16_t, H2)
DO_3OP_PAIR(gvec_umaxp_s, MAX, uint32_t, H4)
DO_3OP_PAIR(gvec_sminp_b, MIN, int8_t, H1)
DO_3OP_PAIR(gvec_sminp_h, MIN, int16_t, H2)
DO_3OP_PAIR(gvec_sminp_s, MIN, int32_t, H4)
DO_3OP_PAIR(gvec_uminp_b, MIN, uint8_t, H1)
DO_3OP_PAIR(gvec_uminp_h, MIN, uint16_t, H2)
DO_3OP_PAIR(gvec_uminp_s, MIN, uint32_t, H4)
#undef DO_3OP_PAIR
#define DO_VCVT_FIXED(NAME, FUNC, TYPE) \