diff options
-rw-r--r-- | riscv/csrs.cc | 24 | ||||
-rw-r--r-- | riscv/csrs.h | 6 | ||||
-rw-r--r-- | riscv/decode.h | 2 | ||||
-rw-r--r-- | riscv/insns/cm_jalt.h | 23 | ||||
-rw-r--r-- | riscv/mmu.h | 7 | ||||
-rw-r--r-- | riscv/overlap_list.h | 1 | ||||
-rw-r--r-- | riscv/processor.cc | 7 | ||||
-rw-r--r-- | riscv/processor.h | 3 | ||||
-rw-r--r-- | riscv/riscv.mk.in | 4 |
9 files changed, 76 insertions, 1 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 93b0bae..caee943 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1470,3 +1470,27 @@ bool scountovf_csr_t::unlogged_write(const reg_t UNUSED val) noexcept { /* this function is unused */ return false; } + +// implement class jvt_csr_t +jvt_csr_t::jvt_csr_t(processor_t* const proc, const reg_t addr, const reg_t init): + basic_csr_t(proc, addr, init) { +} + +void jvt_csr_t::verify_permissions(insn_t insn, bool write) const { + basic_csr_t::verify_permissions(insn, write); + + if (proc->extension_enabled(EXT_SMSTATEEN)) { + if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & SSTATEEN0_JVT)) + throw trap_illegal_instruction(insn.bits()); + + if (state->v && !(state->hstateen[0]->read() & SSTATEEN0_JVT)) + throw trap_virtual_instruction(insn.bits()); + + if ((proc->extension_enabled('S') && state->prv < PRV_S) && !(state->sstateen[0]->read() & SSTATEEN0_JVT)) { + if (state->v) + throw trap_virtual_instruction(insn.bits()); + else + throw trap_illegal_instruction(insn.bits()); + } + } +} diff --git a/riscv/csrs.h b/riscv/csrs.h index 70fa2f4..b991efd 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -748,4 +748,10 @@ class scountovf_csr_t: public csr_t { protected: virtual bool unlogged_write(const reg_t val) noexcept override; }; + +class jvt_csr_t: public basic_csr_t { + public: + jvt_csr_t(processor_t* const proc, const reg_t addr, const reg_t init); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; #endif diff --git a/riscv/decode.h b/riscv/decode.h index ffc5d58..40111bc 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -131,6 +131,8 @@ public: uint64_t rvc_rlist() { return x(4, 4); } uint64_t rvc_spimm() { return x(2, 2) << 4; } + uint64_t rvc_index() { return x(2, 8); } + uint64_t v_vm() { return x(25, 1); } uint64_t v_wd() { return x(26, 1); } uint64_t v_nf() { return x(29, 3); } diff --git a/riscv/insns/cm_jalt.h b/riscv/insns/cm_jalt.h new file mode 100644 index 0000000..163adaa --- /dev/null +++ b/riscv/insns/cm_jalt.h @@ -0,0 +1,23 @@ +require_extension(EXT_ZCMT); +STATE.jvt->verify_permissions(insn, false); +reg_t jvt = STATE.jvt->read(); +uint8_t mode = get_field(jvt, JVT_MODE); +reg_t base = get_field(jvt, JVT_BASE); +reg_t index = insn.rvc_index(); +reg_t target; +switch (mode) { +case 0: // jump table mode + if (xlen == 32) + target = MMU.fetch_jump_table<int32_t>(base + (index << 2)); + else // xlen = 64 + target = MMU.fetch_jump_table<int64_t>(base + (index << 3)); + + if (index >= 32) // cm.jalt + WRITE_REG(1, npc); + + set_pc(target & ~reg_t(1)); + break; +default: + require(0); + break; +} diff --git a/riscv/mmu.h b/riscv/mmu.h index cee93e3..dd15b79 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -225,6 +225,13 @@ public: return (addr / PC_ALIGN) % ICACHE_ENTRIES; } + template<typename T> + T ALWAYS_INLINE fetch_jump_table(reg_t addr) { + target_endian<T> res; + load_slow_path_intrapage(addr, sizeof(T), (uint8_t*)&res, 0); + return from_target(res); + } + inline icache_entry_t* refill_icache(reg_t addr, icache_entry_t* entry) { if (matched_trigger) diff --git a/riscv/overlap_list.h b/riscv/overlap_list.h index e053191..fc3b307 100644 --- a/riscv/overlap_list.h +++ b/riscv/overlap_list.h @@ -7,4 +7,5 @@ DECLARE_OVERLAP_INSN(cm_popret, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_popretz, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_mva01s, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_mvsa01, EXT_ZCMP) +DECLARE_OVERLAP_INSN(cm_jalt, EXT_ZCMT) DECLARE_OVERLAP_INSN(c_fsd, EXT_ZCD) diff --git a/riscv/processor.cc b/riscv/processor.cc index 0c9da97..0bf6b0e 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -450,7 +450,9 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) } } if (proc->extension_enabled_const(EXT_SMSTATEEN)) { - const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | SSTATEEN0_CS; + const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | + (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) | + SSTATEEN0_CS; const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN; const reg_t mstateen0_mask = hstateen0_mask; for (int i = 0; i < 4; i++) { @@ -492,6 +494,9 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) } } + if (proc->extension_enabled_const(EXT_ZCMT)) + csrmap[CSR_JVT] = jvt = std::make_shared<jvt_csr_t>(proc, CSR_JVT, 0); + serialized = false; #ifdef RISCV_ENABLE_COMMITLOG diff --git a/riscv/processor.h b/riscv/processor.h index a660399..e531852 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -175,6 +175,9 @@ struct state_t dcsr_csr_t_p dcsr; csr_t_p tselect; tdata2_csr_t_p tdata2; + + csr_t_p jvt; + bool debug_mode; mseccfg_csr_t_p mseccfg; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 746b916..7e38aca 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1318,9 +1318,13 @@ riscv_insn_ext_zcmp = \ cm_mva01s \ cm_mvsa01 \ +riscv_insn_ext_zcmt = \ + cm_jalt \ + riscv_insn_ext_zce = \ $(riscv_insn_ext_zcb) \ $(riscv_insn_ext_zcmp) \ + $(riscv_insn_ext_zcmt) \ riscv_insn_ext_cmo = \ cbo_clean \ |