if (supports_extension('Q') && max_xlen < 64)
bad_isa_string(str);
- // advertise support for supervisor and user modes
- isa |= 1L << ('s' - 'a');
- isa |= 1L << ('u' - 'a');
-
max_isa = isa;
}
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)
if (t.cause() == CAUSE_BREAKPOINT && (
(state.prv == PRV_M && state.dcsr.ebreakm) ||
- (state.prv == PRV_H && state.dcsr.ebreakh) ||
(state.prv == PRV_S && state.dcsr.ebreaks) ||
(state.prv == PRV_U && state.dcsr.ebreaku))) {
enter_debug_mode(DCSR_CAUSE_SWBP);
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
state.mideleg = (state.mideleg & ~delegable_ints) | (val & delegable_ints);
break;
case CSR_MEDELEG: {
- reg_t mask = 0;
-#define DECLARE_CAUSE(name, value) mask |= 1ULL << (value);
-#include "encoding.h"
-#undef DECLARE_CAUSE
+ reg_t mask =
+ (1 << CAUSE_MISALIGNED_FETCH) |
+ (1 << CAUSE_BREAKPOINT) |
+ (1 << CAUSE_USER_ECALL) |
+ (1 << CAUSE_FETCH_PAGE_FAULT) |
+ (1 << CAUSE_LOAD_PAGE_FAULT) |
+ (1 << CAUSE_STORE_PAGE_FAULT);
state.medeleg = (state.medeleg & ~mask) | (val & mask);
break;
}