Skip to content

Commit

Permalink
target/loongarch: Implement vsat
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
gaosong-loongson committed May 6, 2023
1 parent 4cc4c0f commit cbe4419
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 0 deletions.
9 changes: 9 additions & 0 deletions target/loongarch/disas.c
Original file line number Diff line number Diff line change
Expand Up @@ -1061,3 +1061,12 @@ INSN_LSX(vmod_bu, vvv)
INSN_LSX(vmod_hu, vvv)
INSN_LSX(vmod_wu, vvv)
INSN_LSX(vmod_du, vvv)

INSN_LSX(vsat_b, vv_i)
INSN_LSX(vsat_h, vv_i)
INSN_LSX(vsat_w, vv_i)
INSN_LSX(vsat_d, vv_i)
INSN_LSX(vsat_bu, vv_i)
INSN_LSX(vsat_hu, vv_i)
INSN_LSX(vsat_wu, vv_i)
INSN_LSX(vsat_du, vv_i)
9 changes: 9 additions & 0 deletions target/loongarch/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,12 @@ DEF_HELPER_4(vmod_bu, void, env, i32, i32, i32)
DEF_HELPER_4(vmod_hu, void, env, i32, i32, i32)
DEF_HELPER_4(vmod_wu, void, env, i32, i32, i32)
DEF_HELPER_4(vmod_du, void, env, i32, i32, i32)

DEF_HELPER_FLAGS_4(vsat_b, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_w, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_bu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_hu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_wu, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
DEF_HELPER_FLAGS_4(vsat_du, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
101 changes: 101 additions & 0 deletions target/loongarch/insn_trans/trans_lsx.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
12 changes: 12 additions & 0 deletions target/loongarch/insns.decode
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,10 @@ dbcl 0000 00000010 10101 ............... @i15
#
@vv .... ........ ..... ..... vj:5 vd:5 &vv
@vvv .... ........ ..... vk:5 vj:5 vd:5 &vvv
@vv_ui3 .... ........ ..... .. imm:3 vj:5 vd:5 &vv_i
@vv_ui4 .... ........ ..... . imm:4 vj:5 vd:5 &vv_i
@vv_ui5 .... ........ ..... imm:5 vj:5 vd:5 &vv_i
@vv_ui6 .... ........ .... imm:6 vj:5 vd:5 &vv_i
@vv_i5 .... ........ ..... imm:s5 vj:5 vd:5 &vv_i

vadd_b 0111 00000000 10100 ..... ..... ..... @vvv
Expand Down Expand Up @@ -757,3 +760,12 @@ vmod_bu 0111 00001110 01100 ..... ..... ..... @vvv
vmod_hu 0111 00001110 01101 ..... ..... ..... @vvv
vmod_wu 0111 00001110 01110 ..... ..... ..... @vvv
vmod_du 0111 00001110 01111 ..... ..... ..... @vvv

vsat_b 0111 00110010 01000 01 ... ..... ..... @vv_ui3
vsat_h 0111 00110010 01000 1 .... ..... ..... @vv_ui4
vsat_w 0111 00110010 01001 ..... ..... ..... @vv_ui5
vsat_d 0111 00110010 0101 ...... ..... ..... @vv_ui6
vsat_bu 0111 00110010 10000 01 ... ..... ..... @vv_ui3
vsat_hu 0111 00110010 10000 1 .... ..... ..... @vv_ui4
vsat_wu 0111 00110010 10001 ..... ..... ..... @vv_ui5
vsat_du 0111 00110010 1001 ...... ..... ..... @vv_ui6
37 changes: 37 additions & 0 deletions target/loongarch/lsx_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,3 +590,40 @@ VDIV(vmod_bu, 8, UB, DO_REMU)
VDIV(vmod_hu, 16, UH, DO_REMU)
VDIV(vmod_wu, 32, UW, DO_REMU)
VDIV(vmod_du, 64, UD, DO_REMU)

#define VSAT_S(NAME, BIT, E) \
void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t v) \
{ \
int i; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
typedef __typeof(Vd->E(0)) TD; \
\
for (i = 0; i < LSX_LEN/BIT; i++) { \
Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : \
Vj->E(i) < (TD)~max ? (TD)~max: Vj->E(i); \
} \
}

VSAT_S(vsat_b, 8, B)
VSAT_S(vsat_h, 16, H)
VSAT_S(vsat_w, 32, W)
VSAT_S(vsat_d, 64, D)

#define VSAT_U(NAME, BIT, E) \
void HELPER(NAME)(void *vd, void *vj, uint64_t max, uint32_t v) \
{ \
int i; \
VReg *Vd = (VReg *)vd; \
VReg *Vj = (VReg *)vj; \
typedef __typeof(Vd->E(0)) TD; \
\
for (i = 0; i < LSX_LEN/BIT; i++) { \
Vd->E(i) = Vj->E(i) > (TD)max ? (TD)max : Vj->E(i); \
} \
}

VSAT_U(vsat_bu, 8, UB)
VSAT_U(vsat_hu, 16, UH)
VSAT_U(vsat_wu, 32, UW)
VSAT_U(vsat_du, 64, UD)

0 comments on commit cbe4419

Please sign in to comment.