diff options
-rw-r--r-- | disasm/isa_parser.cc | 4 | ||||
-rw-r--r-- | riscv/csrs.cc | 62 | ||||
-rw-r--r-- | riscv/csrs.h | 28 | ||||
-rw-r--r-- | riscv/encoding.h | 32 | ||||
-rw-r--r-- | riscv/isa_parser.h | 2 | ||||
-rw-r--r-- | riscv/processor.cc | 40 |
6 files changed, 167 insertions, 1 deletions
diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index c18a72d..f4d9da4 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -286,6 +286,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) } else if (ext_str == "zvkt") { } else if (ext_str == "sstc") { extension_table[EXT_SSTC] = true; + } else if (ext_str == "smcsrind") { + extension_table[EXT_SMCSRIND] = true; + } else if (ext_str == "sscsrind") { + extension_table[EXT_SSCSRIND] = true; } else if (ext_str[0] == 'x') { extension_table['X'] = true; if (ext_str.size() == 1) { diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 34c03a5..9849ea2 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1587,3 +1587,65 @@ void jvt_csr_t::verify_permissions(insn_t insn, bool write) const { } } } + +virtualized_indirect_csr_t::virtualized_indirect_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt): + virtualized_csr_t(proc, orig, virt) { +} + +void virtualized_indirect_csr_t::verify_permissions(insn_t insn, bool write) const { + virtualized_csr_t::verify_permissions(insn, write); + if (state->v) + virt_csr->verify_permissions(insn, write); + else + orig_csr->verify_permissions(insn, write); +} + +sscsrind_reg_csr_t::sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p iselect) : + csr_t(proc, addr), + iselect(iselect) { +} + +void sscsrind_reg_csr_t::verify_permissions(insn_t insn, bool write) const { + // Don't call base verify_permission for VS registers remapped to S-mode + if (insn.csr() == address) + csr_t::verify_permissions(insn, write); + + csr_t_p proxy_csr = get_reg(); + if (proxy_csr == nullptr) { + if (!state->v) { + throw trap_illegal_instruction(insn.bits()); + } else { + throw trap_virtual_instruction(insn.bits()); + } + } + proxy_csr->verify_permissions(insn, write); +} + + +reg_t sscsrind_reg_csr_t::read() const noexcept { + csr_t_p target_csr = get_reg(); + if (target_csr != nullptr) { + return target_csr->read(); + } + return 0; +} + +bool sscsrind_reg_csr_t::unlogged_write(const reg_t val) noexcept { + csr_t_p proxy_csr = get_reg(); + if (proxy_csr != nullptr) { + proxy_csr->write(val); + } + return false; +} + +// Returns the actual CSR that maps to value in *siselect or nullptr if no mapping exists +csr_t_p sscsrind_reg_csr_t::get_reg() const noexcept { + auto proxy = ireg_proxy; + auto isel = iselect->read(); + auto it = proxy.find(isel); + return it != proxy.end() ? it->second : nullptr; +} + +void sscsrind_reg_csr_t::add_ireg_proxy(const reg_t iselect_value, csr_t_p csr) { + ireg_proxy[iselect_value] = csr; +} diff --git a/riscv/csrs.h b/riscv/csrs.h index e483ea3..cf48673 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -6,8 +6,12 @@ #include "encoding.h" // For reg_t: #include "decode.h" +// For std::unordered_map +#include <unordered_map> // For std::shared_ptr #include <memory> +// For std::optional +#include <optional> // For access_type: #include "memtracer.h" #include <cassert> @@ -794,4 +798,28 @@ class jvt_csr_t: public basic_csr_t { 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; }; + +// Sscsrind registers needs permissions checked +// (the original virtualized_csr_t does not call verify_permission of the underlying CSRs) +class virtualized_indirect_csr_t: public virtualized_csr_t { + public: + virtualized_indirect_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; + +class sscsrind_reg_csr_t : public csr_t { + public: + typedef std::shared_ptr<sscsrind_reg_csr_t> sscsrind_reg_csr_t_p; + sscsrind_reg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p iselect); + reg_t read() const noexcept override; + virtual void verify_permissions(insn_t insn, bool write) const override; + void add_ireg_proxy(const reg_t iselect_val, csr_t_p proxy_csr); + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; + private: + csr_t_p iselect; + std::unordered_map<reg_t, csr_t_p> ireg_proxy; + csr_t_p get_reg() const noexcept; +}; + #endif diff --git a/riscv/encoding.h b/riscv/encoding.h index db7b021..9666774 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -4,7 +4,7 @@ /* * This file is auto-generated by running 'make' in - * https://github.com/riscv/riscv-opcodes (3ca60c5) + * https://github.com/riscv/riscv-opcodes (be53d24) */ #ifndef RISCV_CSR_ENCODING_H @@ -3059,6 +3059,11 @@ #define CSR_STIMECMP 0x14d #define CSR_SISELECT 0x150 #define CSR_SIREG 0x151 +#define CSR_SIREG2 0x152 +#define CSR_SIREG3 0x153 +#define CSR_SIREG4 0x155 +#define CSR_SIREG5 0x156 +#define CSR_SIREG6 0x157 #define CSR_STOPEI 0x15c #define CSR_SATP 0x180 #define CSR_SCONTEXT 0x5a8 @@ -3073,6 +3078,11 @@ #define CSR_VSTIMECMP 0x24d #define CSR_VSISELECT 0x250 #define CSR_VSIREG 0x251 +#define CSR_VSIREG2 0x252 +#define CSR_VSIREG3 0x253 +#define CSR_VSIREG4 0x255 +#define CSR_VSIREG5 0x256 +#define CSR_VSIREG6 0x257 #define CSR_VSTOPEI 0x25c #define CSR_VSATP 0x280 #define CSR_HSTATUS 0x600 @@ -3140,6 +3150,11 @@ #define CSR_MTVAL2 0x34b #define CSR_MISELECT 0x350 #define CSR_MIREG 0x351 +#define CSR_MIREG2 0x352 +#define CSR_MIREG3 0x353 +#define CSR_MIREG4 0x355 +#define CSR_MIREG5 0x356 +#define CSR_MIREG6 0x357 #define CSR_MTOPEI 0x35c #define CSR_PMPCFG0 0x3a0 #define CSR_PMPCFG1 0x3a1 @@ -4926,6 +4941,11 @@ DECLARE_CSR(sip, CSR_SIP) DECLARE_CSR(stimecmp, CSR_STIMECMP) DECLARE_CSR(siselect, CSR_SISELECT) DECLARE_CSR(sireg, CSR_SIREG) +DECLARE_CSR(sireg2, CSR_SIREG2) +DECLARE_CSR(sireg3, CSR_SIREG3) +DECLARE_CSR(sireg4, CSR_SIREG4) +DECLARE_CSR(sireg5, CSR_SIREG5) +DECLARE_CSR(sireg6, CSR_SIREG6) DECLARE_CSR(stopei, CSR_STOPEI) DECLARE_CSR(satp, CSR_SATP) DECLARE_CSR(scontext, CSR_SCONTEXT) @@ -4940,6 +4960,11 @@ DECLARE_CSR(vsip, CSR_VSIP) DECLARE_CSR(vstimecmp, CSR_VSTIMECMP) DECLARE_CSR(vsiselect, CSR_VSISELECT) DECLARE_CSR(vsireg, CSR_VSIREG) +DECLARE_CSR(vsireg2, CSR_VSIREG2) +DECLARE_CSR(vsireg3, CSR_VSIREG3) +DECLARE_CSR(vsireg4, CSR_VSIREG4) +DECLARE_CSR(vsireg5, CSR_VSIREG5) +DECLARE_CSR(vsireg6, CSR_VSIREG6) DECLARE_CSR(vstopei, CSR_VSTOPEI) DECLARE_CSR(vsatp, CSR_VSATP) DECLARE_CSR(hstatus, CSR_HSTATUS) @@ -5007,6 +5032,11 @@ DECLARE_CSR(mtinst, CSR_MTINST) DECLARE_CSR(mtval2, CSR_MTVAL2) DECLARE_CSR(miselect, CSR_MISELECT) DECLARE_CSR(mireg, CSR_MIREG) +DECLARE_CSR(mireg2, CSR_MIREG2) +DECLARE_CSR(mireg3, CSR_MIREG3) +DECLARE_CSR(mireg4, CSR_MIREG4) +DECLARE_CSR(mireg5, CSR_MIREG5) +DECLARE_CSR(mireg6, CSR_MIREG6) DECLARE_CSR(mtopei, CSR_MTOPEI) DECLARE_CSR(pmpcfg0, CSR_PMPCFG0) DECLARE_CSR(pmpcfg1, CSR_PMPCFG1) diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 335a42b..bba5a91 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -77,6 +77,8 @@ typedef enum { EXT_SSTC, EXT_ZACAS, EXT_INTERNAL_ZFH_MOVE, + EXT_SMCSRIND, + EXT_SSCSRIND, NUM_ISA_EXTENSIONS } isa_extension_t; diff --git a/riscv/processor.cc b/riscv/processor.cc index 2f458bf..ff64f5a 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -524,6 +524,46 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) if (proc->extension_enabled(EXT_ZCMT)) csrmap[CSR_JVT] = jvt = std::make_shared<jvt_csr_t>(proc, CSR_JVT, 0); + + // Smcsrind / Sscsrind + csr_t_p miselect; + csr_t_p siselect; + csr_t_p vsiselect; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6]; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6]; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6]; + + if (proc->extension_enabled_const(EXT_SMCSRIND)) { + const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; + auto i = 0; + for (auto csr : mireg_csrs) { + csrmap[csr] = mireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, miselect); + i++; + } + } + + if (proc->extension_enabled_const(EXT_SSCSRIND)) { + vsiselect = std::make_shared<basic_csr_t>(proc, CSR_VSISELECT, 0); + csrmap[CSR_VSISELECT] = vsiselect; + siselect = std::make_shared<basic_csr_t>(proc, CSR_SISELECT, 0); + csrmap[CSR_SISELECT] = std::make_shared<virtualized_csr_t>(proc, siselect, vsiselect); + + const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; + auto i = 0; + for (auto csr : vsireg_csrs) { + csrmap[csr] = vsireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, vsiselect); + i++; + } + + const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; + i = 0; + for (auto csr : sireg_csrs) { + sireg[i] = std::make_shared<sscsrind_reg_csr_t>(proc, csr, siselect); + csrmap[csr] = std::make_shared<virtualized_indirect_csr_t>(proc, sireg[i], vsireg[i]); + i++; + } + } + serialized = false; log_reg_write.clear(); |