target/loongarch: Implement vsat

This patch includes:
- VSAT.{B/H/W/D}[U].

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20230504122810.4094787-18-gaosong@loongson.cn>
This commit is contained in:
Song Gao 2023-05-04 20:27:43 +08:00
parent 4cc4c0f78b
commit cbe44190cc
No known key found for this signature in database
GPG key ID: 40A2FFF239263EDF
5 changed files with 168 additions and 0 deletions

View file

@ -2693,3 +2693,104 @@ TRANS(vmod_bu, gen_vvv, gen_helper_vmod_bu)
TRANS(vmod_hu, gen_vvv, gen_helper_vmod_hu)
TRANS(vmod_wu, gen_vvv, gen_helper_vmod_wu)
TRANS(vmod_du, gen_vvv, gen_helper_vmod_du)
static void gen_vsat_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
{
TCGv_vec min;
min = tcg_temp_new_vec_matching(t);
tcg_gen_not_vec(vece, min, max);
tcg_gen_smax_vec(vece, t, a, min);
tcg_gen_smin_vec(vece, t, t, max);
}
static void do_vsat_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
int64_t imm, uint32_t oprsz, uint32_t maxsz)
{
static const TCGOpcode vecop_list[] = {
INDEX_op_smax_vec, INDEX_op_smin_vec, 0
};
static const GVecGen2s op[4] = {
{
.fniv = gen_vsat_s,
.fno = gen_helper_vsat_b,
.opt_opc = vecop_list,
.vece = MO_8
},
{
.fniv = gen_vsat_s,
.fno = gen_helper_vsat_h,
.opt_opc = vecop_list,
.vece = MO_16
},
{
.fniv = gen_vsat_s,
.fno = gen_helper_vsat_w,
.opt_opc = vecop_list,
.vece = MO_32
},
{
.fniv = gen_vsat_s,
.fno = gen_helper_vsat_d,
.opt_opc = vecop_list,
.vece = MO_64
},
};
tcg_gen_gvec_2s(vd_ofs, vj_ofs, oprsz, maxsz,
tcg_constant_i64((1ll<< imm) -1), &op[vece]);
}
TRANS(vsat_b, gvec_vv_i, MO_8, do_vsat_s)
TRANS(vsat_h, gvec_vv_i, MO_16, do_vsat_s)
TRANS(vsat_w, gvec_vv_i, MO_32, do_vsat_s)
TRANS(vsat_d, gvec_vv_i, MO_64, do_vsat_s)
static void gen_vsat_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
{
tcg_gen_umin_vec(vece, t, a, max);
}
static void do_vsat_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
int64_t imm, uint32_t oprsz, uint32_t maxsz)
{
uint64_t max;
static const TCGOpcode vecop_list[] = {
INDEX_op_umin_vec, 0
};
static const GVecGen2s op[4] = {
{
.fniv = gen_vsat_u,
.fno = gen_helper_vsat_bu,
.opt_opc = vecop_list,
.vece = MO_8
},
{
.fniv = gen_vsat_u,
.fno = gen_helper_vsat_hu,
.opt_opc = vecop_list,
.vece = MO_16
},
{
.fniv = gen_vsat_u,
.fno = gen_helper_vsat_wu,
.opt_opc = vecop_list,
.vece = MO_32
},
{
.fniv = gen_vsat_u,
.fno = gen_helper_vsat_du,
.opt_opc = vecop_list,
.vece = MO_64
},
};
max = (imm == 0x3f) ? UINT64_MAX : (1ull << (imm + 1)) - 1;
tcg_gen_gvec_2s(vd_ofs, vj_ofs, oprsz, maxsz,
tcg_constant_i64(max), &op[vece]);
}
TRANS(vsat_bu, gvec_vv_i, MO_8, do_vsat_u)
TRANS(vsat_hu, gvec_vv_i, MO_16, do_vsat_u)
TRANS(vsat_wu, gvec_vv_i, MO_32, do_vsat_u)
TRANS(vsat_du, gvec_vv_i, MO_64, do_vsat_u)