+void processor_t::step(size_t n)
+{
+ size_t instret = 0;
+ reg_t pc = state.pc;
+ mmu_t* _mmu = mmu;
+
+ if (unlikely(!run || !n))
+ return;
+ n = std::min(n, next_timer(&state) | 1U);
+
+ try
+ {
+ take_interrupt();
+
+ if (unlikely(debug))
+ {
+ while (instret++ < n)
+ {
+ insn_fetch_t fetch = mmu->load_insn(pc);
+ disasm(fetch.insn);
+ pc = execute_insn(this, pc, fetch);
+ }
+ }
+ else while (instret < n)
+ {
+ size_t idx = _mmu->icache_index(pc);
+ auto ic_entry = _mmu->access_icache(pc);
+
+ #define ICACHE_ACCESS(idx) { \
+ insn_fetch_t fetch = ic_entry->data; \
+ ic_entry++; \
+ pc = execute_insn(this, pc, fetch); \
+ instret++; \
+ if (idx == mmu_t::ICACHE_ENTRIES-1) break; \
+ if (unlikely(ic_entry->tag != pc)) break; \
+ }
+
+ switch (idx) {
+ #include "icache.h"
+ }
+ }
+ }
+ catch(trap_t& t)
+ {
+ pc = take_trap(t, pc);
+ }
+ catch(serialize_t& s) {}
+
+ state.pc = pc;
+ update_timer(&state, instret);
+}
+
+void processor_t::push_privilege_stack()
+{
+ reg_t s = state.mstatus;
+ s = set_field(s, MSTATUS_PRV2, get_field(state.mstatus, MSTATUS_PRV1));
+ s = set_field(s, MSTATUS_IE2, get_field(state.mstatus, MSTATUS_IE1));
+ s = set_field(s, MSTATUS_PRV1, get_field(state.mstatus, MSTATUS_PRV));
+ s = set_field(s, MSTATUS_IE1, get_field(state.mstatus, MSTATUS_IE));
+ s = set_field(s, MSTATUS_PRV, PRV_M);
+ s = set_field(s, MSTATUS_MPRV, PRV_M);
+ s = set_field(s, MSTATUS_IE, 0);
+ set_csr(CSR_MSTATUS, s);
+}
+
+void processor_t::pop_privilege_stack()
+{
+ reg_t s = state.mstatus;
+ s = set_field(s, MSTATUS_PRV, get_field(state.mstatus, MSTATUS_PRV1));
+ s = set_field(s, MSTATUS_IE, get_field(state.mstatus, MSTATUS_IE1));
+ s = set_field(s, MSTATUS_PRV1, get_field(state.mstatus, MSTATUS_PRV2));
+ s = set_field(s, MSTATUS_IE1, get_field(state.mstatus, MSTATUS_IE2));
+ s = set_field(s, MSTATUS_PRV2, PRV_U);
+ s = set_field(s, MSTATUS_IE2, 1);
+ set_csr(CSR_MSTATUS, s);
+}
+
+reg_t processor_t::take_trap(trap_t& t, reg_t epc)
+{
+ if (debug)
+ fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
+ id, t.name(), epc);
+
+ reg_t tvec = 0x40 * get_field(state.mstatus, MSTATUS_PRV);
+ push_privilege_stack();
+ yield_load_reservation();
+ state.mcause = t.cause();
+ state.mepc = epc;
+ t.side_effects(&state); // might set badvaddr etc.
+ return tvec;
+}
+
+void processor_t::deliver_ipi()
+{
+ state.mstatus |= MSTATUS_MSIP;
+}
+
+void processor_t::disasm(insn_t insn)
+{
+ uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
+ fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
+ id, state.pc, bits, disassembler->disassemble(insn).c_str());
+}
+
+static bool validate_priv(reg_t priv)
+{
+ return priv == PRV_U || priv == PRV_S || priv == PRV_M;
+}
+
+static bool validate_arch(reg_t arch)
+{
+#ifdef RISCV_ENABLE_64BIT
+ if (arch == UA_RV64) return true;
+#endif
+ return arch == UA_RV32;