Remove redundant U/S mode advertisement
[riscv-isa-sim.git] / riscv / processor.cc
index ae021657b680819b89b766eca566582731ebf29d..2dd27496775c45b305ac8135f2f0d8e03bc155f4 100644 (file)
@@ -112,10 +112,6 @@ void processor_t::parse_isa_string(const char* str)
   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;
 }
 
@@ -193,13 +189,23 @@ static int xlen_to_uxl(int xlen)
   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)
@@ -232,7 +238,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
 
   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);
@@ -328,11 +333,16 @@ void processor_t::set_csr(int which, reg_t val)
         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;
@@ -342,6 +352,7 @@ void processor_t::set_csr(int which, reg_t val)
       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
@@ -360,10 +371,13 @@ void processor_t::set_csr(int which, reg_t val)
       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;
     }