+ // M-ints have highest priority; consider S-ints only if no M-ints pending
+ if (enabled_interrupts == 0)
+ enabled_interrupts = pending_interrupts & state.mideleg & -s_enabled;
+
+ if (state.dcsr.cause == 0 && enabled_interrupts) {
+ // nonstandard interrupts have highest priority
+ if (enabled_interrupts >> IRQ_M_EXT)
+ enabled_interrupts = enabled_interrupts >> IRQ_M_EXT << IRQ_M_EXT;
+ // external interrupts have next-highest priority
+ else if (enabled_interrupts & (MIP_MEIP | MIP_SEIP))
+ enabled_interrupts = enabled_interrupts & (MIP_MEIP | MIP_SEIP);
+ // software interrupts have next-highest priority
+ else if (enabled_interrupts & (MIP_MSIP | MIP_SSIP))
+ enabled_interrupts = enabled_interrupts & (MIP_MSIP | MIP_SSIP);
+ // timer interrupts have next-highest priority
+ else if (enabled_interrupts & (MIP_MTIP | MIP_STIP))
+ enabled_interrupts = enabled_interrupts & (MIP_MTIP | MIP_STIP);
+ else
+ abort();
+
+ throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts));
+ }
+}
+
+static int xlen_to_uxl(int xlen)
+{
+ if (xlen == 32)
+ return 1;
+ if (xlen == 64)
+ return 2;
+ abort();
+}
+
+reg_t processor_t::legalize_privilege(reg_t prv)
+{
+ assert(prv <= PRV_M);
+
+ if (!supports_extension('U'))
+ return PRV_M;
+
+ if (prv == PRV_H || !supports_extension('S'))
+ return PRV_U;