diff options
author | Song Gao <gaosong@loongson.cn> | 2023-09-14 10:26:39 +0800 |
---|---|---|
committer | Song Gao <gaosong@loongson.cn> | 2023-09-20 14:33:42 +0800 |
commit | f5ce2c8f2c0a9c95b76984b520fe77fa2ff16f3e (patch) | |
tree | 61e3b7ec91bb0bac7f13811a7312f1ada21fbdec /target/loongarch | |
parent | f3dfcc8b2334dad831e2bfd9a69ee02dbd6f9eb3 (diff) |
target/loongarch: Implement xvinsgr2vr xvpickve2gr
This patch includes:
- XVINSGR2VR.{W/D};
- XVPICKVE2GR.{W/D}[U].
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230914022645.1151356-52-gaosong@loongson.cn>
Diffstat (limited to 'target/loongarch')
-rw-r--r-- | target/loongarch/disas.c | 17 | ||||
-rw-r--r-- | target/loongarch/insn_trans/trans_vec.c.inc | 208 | ||||
-rw-r--r-- | target/loongarch/insns.decode | 7 | ||||
-rw-r--r-- | target/loongarch/translate.c | 12 |
4 files changed, 74 insertions, 170 deletions
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c index abe113b150..04f9f9fa4b 100644 --- a/target/loongarch/disas.c +++ b/target/loongarch/disas.c @@ -1738,6 +1738,16 @@ static void output_vv_x(DisasContext *ctx, arg_vv *a, const char *mnemonic) output(ctx, mnemonic, "x%d, x%d", a->vd, a->vj); } +static void output_vr_i_x(DisasContext *ctx, arg_vr_i *a, const char *mnemonic) +{ + output(ctx, mnemonic, "x%d, r%d, 0x%x", a->vd, a->rj, a->imm); +} + +static void output_rv_i_x(DisasContext *ctx, arg_rv_i *a, const char *mnemonic) +{ + output(ctx, mnemonic, "r%d, x%d, 0x%x", a->rd, a->vj, a->imm); +} + INSN_LASX(xvadd_b, vvv) INSN_LASX(xvadd_h, vvv) INSN_LASX(xvadd_w, vvv) @@ -2497,6 +2507,13 @@ INSN_LASX(xvsetallnez_h, cv) INSN_LASX(xvsetallnez_w, cv) INSN_LASX(xvsetallnez_d, cv) +INSN_LASX(xvinsgr2vr_w, vr_i) +INSN_LASX(xvinsgr2vr_d, vr_i) +INSN_LASX(xvpickve2gr_w, rv_i) +INSN_LASX(xvpickve2gr_d, rv_i) +INSN_LASX(xvpickve2gr_wu, rv_i) +INSN_LASX(xvpickve2gr_du, rv_i) + INSN_LASX(xvreplgr2vr_b, vr) INSN_LASX(xvreplgr2vr_h, vr) INSN_LASX(xvreplgr2vr_w, vr) diff --git a/target/loongarch/insn_trans/trans_vec.c.inc b/target/loongarch/insn_trans/trans_vec.c.inc index 0dec3dfffe..e1ba54075e 100644 --- a/target/loongarch/insn_trans/trans_vec.c.inc +++ b/target/loongarch/insn_trans/trans_vec.c.inc @@ -4829,209 +4829,77 @@ TRANS(xvsetallnez_h, LASX, gen_cx, gen_helper_vsetallnez_h) TRANS(xvsetallnez_w, LASX, gen_cx, gen_helper_vsetallnez_w) TRANS(xvsetallnez_d, LASX, gen_cx, gen_helper_vsetallnez_d) -static bool trans_vinsgr2vr_b(DisasContext *ctx, arg_vr_i *a) +static bool gen_g2v_vl(DisasContext *ctx, arg_vr_i *a, uint32_t oprsz, MemOp mop, + void (*func)(TCGv, TCGv_ptr, tcg_target_long)) { TCGv src = gpr_src(ctx, a->rj, EXT_NONE); - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_st8_i64(src, cpu_env, - offsetof(CPULoongArchState, fpr[a->vd].vreg.B(a->imm))); - return true; -} - -static bool trans_vinsgr2vr_h(DisasContext *ctx, arg_vr_i *a) -{ - TCGv src = gpr_src(ctx, a->rj, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_st16_i64(src, cpu_env, - offsetof(CPULoongArchState, fpr[a->vd].vreg.H(a->imm))); - return true; -} - -static bool trans_vinsgr2vr_w(DisasContext *ctx, arg_vr_i *a) -{ - TCGv src = gpr_src(ctx, a->rj, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { + if (!check_vec(ctx, oprsz)) { return true; } - tcg_gen_st32_i64(src, cpu_env, - offsetof(CPULoongArchState, fpr[a->vd].vreg.W(a->imm))); - return true; -} - -static bool trans_vinsgr2vr_d(DisasContext *ctx, arg_vr_i *a) -{ - TCGv src = gpr_src(ctx, a->rj, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } + func(src, cpu_env, vec_reg_offset(a->vd, a->imm, mop)); - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_st_i64(src, cpu_env, - offsetof(CPULoongArchState, fpr[a->vd].vreg.D(a->imm))); return true; } -static bool trans_vpickve2gr_b(DisasContext *ctx, arg_rv_i *a) +static bool gen_g2v(DisasContext *ctx, arg_vr_i *a, MemOp mop, + void (*func)(TCGv, TCGv_ptr, tcg_target_long)) { - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld8s_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm))); - return true; + return gen_g2v_vl(ctx, a, 16, mop, func); } -static bool trans_vpickve2gr_h(DisasContext *ctx, arg_rv_i *a) +static bool gen_g2x(DisasContext *ctx, arg_vr_i *a, MemOp mop, + void (*func)(TCGv, TCGv_ptr, tcg_target_long)) { - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld16s_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm))); - return true; + return gen_g2v_vl(ctx, a, 32, mop, func); } -static bool trans_vpickve2gr_w(DisasContext *ctx, arg_rv_i *a) -{ - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); +TRANS(vinsgr2vr_b, LSX, gen_g2v, MO_8, tcg_gen_st8_i64) +TRANS(vinsgr2vr_h, LSX, gen_g2v, MO_16, tcg_gen_st16_i64) +TRANS(vinsgr2vr_w, LSX, gen_g2v, MO_32, tcg_gen_st32_i64) +TRANS(vinsgr2vr_d, LSX, gen_g2v, MO_64, tcg_gen_st_i64) +TRANS(xvinsgr2vr_w, LASX, gen_g2x, MO_32, tcg_gen_st32_i64) +TRANS(xvinsgr2vr_d, LASX, gen_g2x, MO_64, tcg_gen_st_i64) - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld32s_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm))); - return true; -} - -static bool trans_vpickve2gr_d(DisasContext *ctx, arg_rv_i *a) +static bool gen_v2g_vl(DisasContext *ctx, arg_rv_i *a, uint32_t oprsz, MemOp mop, + void (*func)(TCGv, TCGv_ptr, tcg_target_long)) { TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { + if (!check_vec(ctx, oprsz)) { return true; } - tcg_gen_ld_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm))); - return true; -} + func(dst, cpu_env, vec_reg_offset(a->vj, a->imm, mop)); -static bool trans_vpickve2gr_bu(DisasContext *ctx, arg_rv_i *a) -{ - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld8u_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm))); return true; } -static bool trans_vpickve2gr_hu(DisasContext *ctx, arg_rv_i *a) +static bool gen_v2g(DisasContext *ctx, arg_rv_i *a, MemOp mop, + void (*func)(TCGv, TCGv_ptr, tcg_target_long)) { - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld16u_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm))); - return true; + return gen_v2g_vl(ctx, a, 16, mop, func); } -static bool trans_vpickve2gr_wu(DisasContext *ctx, arg_rv_i *a) +static bool gen_x2g(DisasContext *ctx, arg_rv_i *a, MemOp mop, + void (*func)(TCGv, TCGv_ptr, tcg_target_long)) { - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld32u_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm))); - return true; + return gen_v2g_vl(ctx, a, 32, mop, func); } -static bool trans_vpickve2gr_du(DisasContext *ctx, arg_rv_i *a) -{ - TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE); - - if (!avail_LSX(ctx)) { - return false; - } - - if (!check_vec(ctx, 16)) { - return true; - } - - tcg_gen_ld_i64(dst, cpu_env, - offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm))); - return true; -} +TRANS(vpickve2gr_b, LSX, gen_v2g, MO_8, tcg_gen_ld8s_i64) +TRANS(vpickve2gr_h, LSX, gen_v2g, MO_16, tcg_gen_ld16s_i64) +TRANS(vpickve2gr_w, LSX, gen_v2g, MO_32, tcg_gen_ld32s_i64) +TRANS(vpickve2gr_d, LSX, gen_v2g, MO_64, tcg_gen_ld_i64) +TRANS(vpickve2gr_bu, LSX, gen_v2g, MO_8, tcg_gen_ld8u_i64) +TRANS(vpickve2gr_hu, LSX, gen_v2g, MO_16, tcg_gen_ld16u_i64) +TRANS(vpickve2gr_wu, LSX, gen_v2g, MO_32, tcg_gen_ld32u_i64) +TRANS(vpickve2gr_du, LSX, gen_v2g, MO_64, tcg_gen_ld_i64) +TRANS(xvpickve2gr_w, LASX, gen_x2g, MO_32, tcg_gen_ld32s_i64) +TRANS(xvpickve2gr_d, LASX, gen_x2g, MO_64, tcg_gen_ld_i64) +TRANS(xvpickve2gr_wu, LASX, gen_x2g, MO_32, tcg_gen_ld32u_i64) +TRANS(xvpickve2gr_du, LASX, gen_x2g, MO_64, tcg_gen_ld_i64) static bool gvec_dup_vl(DisasContext *ctx, arg_vr *a, uint32_t oprsz, MemOp mop) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index ad6751fdfb..bb3bb447ae 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -1976,6 +1976,13 @@ xvsetallnez_h 0111 01101001 11001 01101 ..... 00 ... @cv xvsetallnez_w 0111 01101001 11001 01110 ..... 00 ... @cv xvsetallnez_d 0111 01101001 11001 01111 ..... 00 ... @cv +xvinsgr2vr_w 0111 01101110 10111 10 ... ..... ..... @vr_ui3 +xvinsgr2vr_d 0111 01101110 10111 110 .. ..... ..... @vr_ui2 +xvpickve2gr_w 0111 01101110 11111 10 ... ..... ..... @rv_ui3 +xvpickve2gr_d 0111 01101110 11111 110 .. ..... ..... @rv_ui2 +xvpickve2gr_wu 0111 01101111 00111 10 ... ..... ..... @rv_ui3 +xvpickve2gr_du 0111 01101111 00111 110 .. ..... ..... @rv_ui2 + xvreplgr2vr_b 0111 01101001 11110 00000 ..... ..... @vr xvreplgr2vr_h 0111 01101001 11110 00001 ..... ..... @vr xvreplgr2vr_w 0111 01101001 11110 00010 ..... ..... @vr diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 10e2fe8ff6..f6038fc567 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -37,6 +37,18 @@ static inline int vec_full_offset(int regno) return offsetof(CPULoongArchState, fpr[regno]); } +static inline int vec_reg_offset(int regno, int index, MemOp mop) +{ + const uint8_t size = 1 << mop; + int offs = index * size; + + if (HOST_BIG_ENDIAN && size < 8 ) { + offs ^= (8 - size); + } + + return offs + vec_full_offset(regno); +} + static inline void get_vreg64(TCGv_i64 dest, int regno, int index) { tcg_gen_ld_i64(dest, cpu_env, |