target/riscv: rvv-1.0: implement vstart CSR

* Update and check vstart value for vector instructions.
* Add whole register move instruction helper functions as we have to
  call helper function for case where vstart is not zero.
* Remove probe_pages() calls in vector load/store instructions
  (except fault-only-first loads) to raise the memory access exception
  at the exact processed vector element.

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20211210075704.23951-67-frank.chang@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Frank Chang
2021-12-20 14:53:31 +10:00
committed by Alistair Francis
parent 8a4b52575a
commit f714361ed7
5 changed files with 197 additions and 101 deletions
+5 -1
View File
@@ -343,7 +343,11 @@ static RISCVException write_vstart(CPURISCVState *env, int csrno,
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
env->mstatus |= MSTATUS_VS; env->mstatus |= MSTATUS_VS;
#endif #endif
env->vstart = val; /*
* The vstart CSR is defined to have only enough writable bits
* to hold the largest element index, i.e. lg2(VLEN) bits.
*/
env->vstart = val & ~(~0ULL << ctzl(env_archcpu(env)->cfg.vlen));
return RISCV_EXCP_NONE; return RISCV_EXCP_NONE;
} }
+5
View File
@@ -1073,6 +1073,11 @@ DEF_HELPER_6(vcompress_vm_h, void, ptr, ptr, ptr, ptr, env, i32)
DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32)
DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32)
DEF_HELPER_4(vmv1r_v, void, ptr, ptr, env, i32)
DEF_HELPER_4(vmv2r_v, void, ptr, ptr, env, i32)
DEF_HELPER_4(vmv4r_v, void, ptr, ptr, env, i32)
DEF_HELPER_4(vmv8r_v, void, ptr, ptr, env, i32)
DEF_HELPER_5(vzext_vf2_h, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vzext_vf2_h, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_5(vzext_vf2_w, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vzext_vf2_w, void, ptr, ptr, ptr, env, i32)
DEF_HELPER_5(vzext_vf2_d, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vzext_vf2_d, void, ptr, ptr, ptr, env, i32)
+46 -25
View File
@@ -490,7 +490,7 @@ static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
*/ */
static bool vext_check_reduction(DisasContext *s, int vs2) static bool vext_check_reduction(DisasContext *s, int vs2)
{ {
return require_align(vs2, s->lmul); return require_align(vs2, s->lmul) && (s->vstart == 0);
} }
/* /*
@@ -2786,7 +2786,8 @@ GEN_MM_TRANS(vmxnor_mm)
static bool trans_vcpop_m(DisasContext *s, arg_rmr *a) static bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
{ {
if (require_rvv(s) && if (require_rvv(s) &&
vext_check_isa_ill(s)) { vext_check_isa_ill(s) &&
s->vstart == 0) {
TCGv_ptr src2, mask; TCGv_ptr src2, mask;
TCGv dst; TCGv dst;
TCGv_i32 desc; TCGv_i32 desc;
@@ -2817,7 +2818,8 @@ static bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
static bool trans_vfirst_m(DisasContext *s, arg_rmr *a) static bool trans_vfirst_m(DisasContext *s, arg_rmr *a)
{ {
if (require_rvv(s) && if (require_rvv(s) &&
vext_check_isa_ill(s)) { vext_check_isa_ill(s) &&
s->vstart == 0) {
TCGv_ptr src2, mask; TCGv_ptr src2, mask;
TCGv dst; TCGv dst;
TCGv_i32 desc; TCGv_i32 desc;
@@ -2852,7 +2854,8 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
if (require_rvv(s) && \ if (require_rvv(s) && \
vext_check_isa_ill(s) && \ vext_check_isa_ill(s) && \
require_vm(a->vm, a->rd) && \ require_vm(a->vm, a->rd) && \
(a->rd != a->rs2)) { \ (a->rd != a->rs2) && \
(s->vstart == 0)) { \
uint32_t data = 0; \ uint32_t data = 0; \
gen_helper_gvec_3_ptr *fn = gen_helper_##NAME; \ gen_helper_gvec_3_ptr *fn = gen_helper_##NAME; \
TCGLabel *over = gen_new_label(); \ TCGLabel *over = gen_new_label(); \
@@ -2888,7 +2891,8 @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
vext_check_isa_ill(s) && vext_check_isa_ill(s) &&
!is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) && !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
require_vm(a->vm, a->rd) && require_vm(a->vm, a->rd) &&
require_align(a->rd, s->lmul)) { require_align(a->rd, s->lmul) &&
(s->vstart == 0)) {
uint32_t data = 0; uint32_t data = 0;
TCGLabel *over = gen_new_label(); TCGLabel *over = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
@@ -3109,6 +3113,7 @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a)
TCGLabel *over = gen_new_label(); TCGLabel *over = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
t1 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64();
@@ -3161,8 +3166,9 @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a)
TCGv_i64 t1; TCGv_i64 t1;
TCGLabel *over = gen_new_label(); TCGLabel *over = gen_new_label();
/* if vl == 0, skip vector register write back */ /* if vl == 0 or vstart >= vl, skip vector register write back */
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
/* NaN-box f[rs1] */ /* NaN-box f[rs1] */
t1 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64();
@@ -3333,7 +3339,8 @@ static bool vcompress_vm_check(DisasContext *s, arg_r *a)
require_align(a->rd, s->lmul) && require_align(a->rd, s->lmul) &&
require_align(a->rs2, s->lmul) && require_align(a->rs2, s->lmul) &&
(a->rd != a->rs2) && (a->rd != a->rs2) &&
!is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1); !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1) &&
(s->vstart == 0);
} }
static bool trans_vcompress_vm(DisasContext *s, arg_r *a) static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
@@ -3363,26 +3370,40 @@ static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
* Whole Vector Register Move Instructions ignore vtype and vl setting. * Whole Vector Register Move Instructions ignore vtype and vl setting.
* Thus, we don't need to check vill bit. (Section 16.6) * Thus, we don't need to check vill bit. (Section 16.6)
*/ */
#define GEN_VMV_WHOLE_TRANS(NAME, LEN) \ #define GEN_VMV_WHOLE_TRANS(NAME, LEN, SEQ) \
static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \
{ \ { \
if (require_rvv(s) && \ if (require_rvv(s) && \
QEMU_IS_ALIGNED(a->rd, LEN) && \ QEMU_IS_ALIGNED(a->rd, LEN) && \
QEMU_IS_ALIGNED(a->rs2, LEN)) { \ QEMU_IS_ALIGNED(a->rs2, LEN)) { \
/* EEW = 8 */ \ uint32_t maxsz = (s->vlen >> 3) * LEN; \
tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd), \ if (s->vstart == 0) { \
vreg_ofs(s, a->rs2), \ /* EEW = 8 */ \
s->vlen / 8 * LEN, s->vlen / 8 * LEN); \ tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd), \
mark_vs_dirty(s); \ vreg_ofs(s, a->rs2), maxsz, maxsz); \
return true; \ mark_vs_dirty(s); \
} \ } else { \
return false; \ TCGLabel *over = gen_new_label(); \
tcg_gen_brcondi_tl(TCG_COND_GEU, cpu_vstart, maxsz, over); \
\
static gen_helper_gvec_2_ptr * const fns[4] = { \
gen_helper_vmv1r_v, gen_helper_vmv2r_v, \
gen_helper_vmv4r_v, gen_helper_vmv8r_v, \
}; \
tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \
cpu_env, maxsz, maxsz, 0, fns[SEQ]); \
mark_vs_dirty(s); \
gen_set_label(over); \
} \
return true; \
} \
return false; \
} }
GEN_VMV_WHOLE_TRANS(vmv1r_v, 1) GEN_VMV_WHOLE_TRANS(vmv1r_v, 1, 0)
GEN_VMV_WHOLE_TRANS(vmv2r_v, 2) GEN_VMV_WHOLE_TRANS(vmv2r_v, 2, 1)
GEN_VMV_WHOLE_TRANS(vmv4r_v, 4) GEN_VMV_WHOLE_TRANS(vmv4r_v, 4, 2)
GEN_VMV_WHOLE_TRANS(vmv8r_v, 8) GEN_VMV_WHOLE_TRANS(vmv8r_v, 8, 3)
static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div) static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div)
{ {
+5 -1
View File
@@ -33,7 +33,7 @@
#include "internals.h" #include "internals.h"
/* global register indices */ /* global register indices */
static TCGv cpu_gpr[32], cpu_pc, cpu_vl; static TCGv cpu_gpr[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */ static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
static TCGv load_res; static TCGv load_res;
static TCGv load_val; static TCGv load_val;
@@ -96,6 +96,7 @@ typedef struct DisasContext {
int8_t lmul; int8_t lmul;
uint8_t sew; uint8_t sew;
uint16_t vlen; uint16_t vlen;
target_ulong vstart;
bool vl_eq_vlmax; bool vl_eq_vlmax;
uint8_t ntemp; uint8_t ntemp;
CPUState *cs; CPUState *cs;
@@ -710,6 +711,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL); ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW); ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3); ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
ctx->vstart = env->vstart;
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL); ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
ctx->cs = cs; ctx->cs = cs;
@@ -828,6 +830,8 @@ void riscv_translate_init(void)
cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc"); cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc");
cpu_vl = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vl), "vl"); cpu_vl = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vl), "vl");
cpu_vstart = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vstart),
"vstart");
load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res), load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res),
"load_res"); "load_res");
load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val), load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val),
File diff suppressed because it is too large Load Diff