diff options
Diffstat (limited to 'riscv/processor.cc')
-rw-r--r-- | riscv/processor.cc | 19 |
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()); |