When sew <= 32bits, not need to extend scalar reg. When sew > 32bits, if xlen is less that sew, we should sign extend the scalar register, except explicitly specified by the spec.
Signed-off-by: LIU Zhiwei <zhiwei_...@c-sky.com> --- target/riscv/insn_trans/trans_rvv.c.inc | 5 +++-- target/riscv/internals.h | 1 + target/riscv/vector_helper.c | 11 +++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 41c7c88904..0a956cac5b 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -846,7 +846,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - src1 = get_gpr(s, rs1, EXT_NONE); + src1 = get_gpr(s, rs1, EXT_SIGN); data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); @@ -2670,6 +2670,7 @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) /* This instruction ignores LMUL and vector register groups */ int maxsz = s->vlen >> 3; TCGv_i64 t1; + TCGv src1 = get_gpr(s, a->rs1, EXT_ZERO); TCGLabel *over = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); @@ -2679,7 +2680,7 @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) } t1 = tcg_temp_new_i64(); - tcg_gen_extu_tl_i64(t1, cpu_gpr[a->rs1]); + tcg_gen_extu_tl_i64(t1, src1); vec_element_storei(s, a->rd, 0, t1); tcg_temp_free_i64(t1); done: diff --git a/target/riscv/internals.h b/target/riscv/internals.h index b15ad394bb..07e882160d 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -27,6 +27,7 @@ FIELD(VDATA, VM, 8, 1) FIELD(VDATA, LMUL, 9, 2) FIELD(VDATA, NF, 11, 4) FIELD(VDATA, WD, 11, 1) +FIELD(VDATA, TRUNC, 15, 1) /* float point classify helpers */ target_ulong fclass_h(uint64_t frs1); diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 0b297f6bc8..51bcf63d65 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -112,6 +112,11 @@ static uint32_t vext_wd(uint32_t desc) return (simd_data(desc) >> 11) & 0x1; } +static inline bool vext_trunc(uint32_t desc) +{ + return FIELD_EX32(simd_data(desc), VDATA, TRUNC); +} + /* * Get vector group length in bytes. Its range is [64, 2048]. * @@ -4748,6 +4753,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t mlen = vext_mlen(desc); \ uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ uint32_t vm = vext_vm(desc); \ + bool trunc = vext_trunc(desc); \ uint32_t vl = env->vl; \ uint32_t i; \ \ @@ -4756,7 +4762,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ continue; \ } \ if (i == 0) { \ - *((ETYPE *)vd + H(i)) = s1; \ + *((ETYPE *)vd + H(i)) = trunc ? (s1 & UINT32_MAX) : s1; \ } else { \ *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - 1)); \ } \ @@ -4777,6 +4783,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t mlen = vext_mlen(desc); \ uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ uint32_t vm = vext_vm(desc); \ + bool trunc = vext_trunc(desc); \ uint32_t vl = env->vl; \ uint32_t i; \ \ @@ -4785,7 +4792,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ continue; \ } \ if (i == vl - 1) { \ - *((ETYPE *)vd + H(i)) = s1; \ + *((ETYPE *)vd + H(i)) = trunc ? (s1 & UINT32_MAX) : s1; \ } else { \ *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + 1)); \ } \ -- 2.25.1