aboutsummaryrefslogtreecommitdiff
path: root/riscv/processor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/processor.cc')
-rw-r--r--riscv/processor.cc19
1 files changed, 16 insertions, 3 deletions
diff --git a/riscv/processor.cc b/riscv/processor.cc
index ad93a42..c05bdac 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -494,6 +494,13 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
}
}
+ if (proc->extension_enabled_const(EXT_SMRNMI)) {
+ csrmap[CSR_MNSCRATCH] = std::make_shared<basic_csr_t>(proc, CSR_MNSCRATCH, 0);
+ csrmap[CSR_MNEPC] = mnepc = std::make_shared<epc_csr_t>(proc, CSR_MNEPC);
+ csrmap[CSR_MNCAUSE] = std::make_shared<const_csr_t>(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1));
+ csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared<mnstatus_csr_t>(proc, CSR_MNSTATUS);
+ }
+
if (proc->extension_enabled_const(EXT_SSTC)) {
stimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_STIMECMP, MIP_STIP);
vstimecmp = std::make_shared<stimecmp_csr_t>(proc, CSR_VSTIMECMP, MIP_VSTIP);
@@ -660,7 +667,8 @@ void processor_t::take_interrupt(reg_t pending_interrupts)
}
}
- if (!state.debug_mode && enabled_interrupts) {
+ const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
+ if (!state.debug_mode && nmie && enabled_interrupts) {
// nonstandard interrupts have highest priority
if (enabled_interrupts >> (IRQ_M_EXT + 1))
enabled_interrupts = enabled_interrupts >> (IRQ_M_EXT + 1) << (IRQ_M_EXT + 1);
@@ -849,8 +857,13 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
} else {
// Handle the trap in M-mode
set_virt(false);
- reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
- state.pc = (state.mtvec->read() & ~(reg_t)1) + vector;
+ const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
+ const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector;
+ // RNMI exception vector is implementation-defined. Since we don't model
+ // RNMI sources, the feature isn't very useful, so pick an invalid address.
+ const reg_t rnmi_trap_handler_address = 0;
+ const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
+ state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
state.mepc->write(epc);
state.mcause->write(t.cause());
state.mtval->write(t.get_tval());