abort();
}
-void processor_t::set_privilege(reg_t prv)
+reg_t processor_t::legalize_privilege(reg_t prv)
{
assert(prv <= PRV_M);
- if (prv == PRV_H)
- prv = PRV_U;
+
+ if (!supports_extension('U'))
+ return PRV_M;
+
+ if (prv == PRV_H || !supports_extension('S'))
+ return PRV_U;
+
+ return prv;
+}
+
+void processor_t::set_privilege(reg_t prv)
+{
mmu->flush_tlb();
- state.prv = prv;
+ state.prv = legalize_privilege(prv);
}
void processor_t::enter_debug_mode(uint8_t cause)
mmu->flush_tlb();
reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
- | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM
- | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
+ | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM
+ | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
| MSTATUS_TSR | MSTATUS_UXL | MSTATUS_SXL |
(ext ? MSTATUS_XS : 0);
+ reg_t requested_mpp = legalize_privilege(get_field(val, MSTATUS_MPP));
+ state.mstatus = set_field(state.mstatus, MSTATUS_MPP, requested_mpp);
+ if (supports_extension('S'))
+ mask |= MSTATUS_SPP;
+
state.mstatus = (state.mstatus & ~mask) | (val & mask);
bool dirty = (state.mstatus & MSTATUS_FS) == MSTATUS_FS;
else
state.mstatus = set_field(state.mstatus, MSTATUS64_SD, dirty);
+ state.mstatus = set_field(state.mstatus, MSTATUS_UXL, xlen_to_uxl(max_xlen));
state.mstatus = set_field(state.mstatus, MSTATUS_UXL, xlen_to_uxl(max_xlen));
state.mstatus = set_field(state.mstatus, MSTATUS_SXL, xlen_to_uxl(max_xlen));
// U-XLEN == S-XLEN == M-XLEN
if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
return ext >= 'A' && ext <= 'Z' && ((isa >> (ext - 'A')) & 1);
}
+ reg_t legalize_privilege(reg_t);
void set_privilege(reg_t);
void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
void update_histogram(reg_t pc);