aboutsummaryrefslogtreecommitdiff
path: root/riscv/csrs.cc
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2023-07-25 15:19:53 -0700
committerGitHub <noreply@github.com>2023-07-25 15:19:53 -0700
commit60c08b1ea5e3d96a97c235db87d472a7cfb2611b (patch)
treeafc79314b2e7cb6d46225ef75fa97115b0fbe010 /riscv/csrs.cc
parent4d0171931c4e8f03d9038da98eb4003789b1ac4c (diff)
parentbc5842f94517c5fa760409cf8c956bbc7c37ead5 (diff)
downloadspike-60c08b1ea5e3d96a97c235db87d472a7cfb2611b.zip
spike-60c08b1ea5e3d96a97c235db87d472a7cfb2611b.tar.gz
spike-60c08b1ea5e3d96a97c235db87d472a7cfb2611b.tar.bz2
Merge pull request #1383 from rivosinc/sscrind_feature
Add Smcsrind / Sscsrind support
Diffstat (limited to 'riscv/csrs.cc')
-rw-r--r--riscv/csrs.cc62
1 files changed, 62 insertions, 0 deletions
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;
+}