WIP on priv spec v1.9
authorAndrew Waterman <waterman@cs.berkeley.edu>
Sat, 6 Feb 2016 02:18:06 +0000 (18:18 -0800)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 2 Mar 2016 20:15:25 +0000 (12:15 -0800)
16 files changed:
riscv/decode.h
riscv/encoding.h
riscv/execute.cc
riscv/extension.cc
riscv/htif.cc
riscv/insns/hrts.h [deleted file]
riscv/insns/mrth.h [deleted file]
riscv/insns/mrts.h [deleted file]
riscv/insns/scall.h
riscv/insns/sret.h
riscv/mmu.cc
riscv/processor.cc
riscv/processor.h
riscv/riscv.mk.in
riscv/trap.cc
riscv/trap.h

index f525ff16f1a0670caaffe676a7bcab86a35ec22e..1dfeac1bf7c715be628ff17f9c8338ba499cdab6 100644 (file)
@@ -177,7 +177,7 @@ private:
 #define set_field(reg, mask, val) (((reg) & ~(decltype(reg))(mask)) | (((decltype(reg))(val) * ((mask) & ~((mask) << 1))) & (decltype(reg))(mask)))
 
 #define require(x) if (unlikely(!(x))) throw trap_illegal_instruction()
-#define require_privilege(p) require(get_field(STATE.mstatus, MSTATUS_PRV) >= (p))
+#define require_privilege(p) require(STATE.prv >= (p))
 #define require_rv64 require(xlen == 64)
 #define require_rv32 require(xlen == 32)
 #define require_extension(s) require(p->supports_extension(s))
@@ -207,10 +207,9 @@ private:
 #define validate_csr(which, write) ({ \
   if (!STATE.serialized) return PC_SERIALIZE; \
   STATE.serialized = false; \
-  unsigned my_priv = get_field(STATE.mstatus, MSTATUS_PRV); \
   unsigned csr_priv = get_field((which), 0x300); \
   unsigned csr_read_only = get_field((which), 0xC00) == 3; \
-  if (((write) && csr_read_only) || my_priv < csr_priv) \
+  if (((write) && csr_read_only) || STATE.prv < csr_priv) \
     throw trap_illegal_instruction(); \
   (which); })
 
index e9a495fa9a6504c76c042d0d3a21f84c9be2ca6f..df048453da2186c5e7cee94d4651e5f93dc8b10e 100644 (file)
@@ -3,37 +3,41 @@
 #ifndef RISCV_CSR_ENCODING_H
 #define RISCV_CSR_ENCODING_H
 
-#define MSTATUS_IE          0x00000001
-#define MSTATUS_PRV         0x00000006
-#define MSTATUS_IE1         0x00000008
-#define MSTATUS_PRV1        0x00000030
-#define MSTATUS_IE2         0x00000040
-#define MSTATUS_PRV2        0x00000180
-#define MSTATUS_IE3         0x00000200
-#define MSTATUS_PRV3        0x00000C00
-#define MSTATUS_FS          0x00003000
-#define MSTATUS_XS          0x0000C000
-#define MSTATUS_MPRV        0x00010000
-#define MSTATUS_VM          0x003E0000
+#define MSTATUS_UIE         0x00000001
+#define MSTATUS_SIE         0x00000002
+#define MSTATUS_HIE         0x00000004
+#define MSTATUS_MIE         0x00000008
+#define MSTATUS_UPIE        0x00000010
+#define MSTATUS_SPIE        0x00000020
+#define MSTATUS_HPIE        0x00000040
+#define MSTATUS_MPIE        0x00000080
+#define MSTATUS_SPP         0x00000100
+#define MSTATUS_HPP         0x00000600
+#define MSTATUS_MPP         0x00001800
+#define MSTATUS_FS          0x00006000
+#define MSTATUS_XS          0x00018000
+#define MSTATUS_MPRV        0x00020000
+#define MSTATUS_VM          0x007C0000
 #define MSTATUS32_SD        0x80000000
 #define MSTATUS64_SD        0x8000000000000000
 
-#define SSTATUS_IE          0x00000001
-#define SSTATUS_PIE         0x00000008
-#define SSTATUS_PS          0x00000010
-#define SSTATUS_FS          0x00003000
-#define SSTATUS_XS          0x0000C000
-#define SSTATUS_MPRV        0x00010000
-#define SSTATUS_TIE         0x01000000
+#define SSTATUS_UIE         0x00000001
+#define SSTATUS_SIE         0x00000002
+#define SSTATUS_UPIE        0x00000010
+#define SSTATUS_SPIE        0x00000020
+#define SSTATUS_SPP         0x00000100
+#define SSTATUS_FS          0x00006000
+#define SSTATUS_XS          0x00018000
+#define SSTATUS_VM          0x007C0000
 #define SSTATUS32_SD        0x80000000
 #define SSTATUS64_SD        0x8000000000000000
 
-#define MIP_SSIP            0x00000002
-#define MIP_HSIP            0x00000004
-#define MIP_MSIP            0x00000008
-#define MIP_STIP            0x00000020
-#define MIP_HTIP            0x00000040
-#define MIP_MTIP            0x00000080
+#define MIP_SSIP            (1 << IRQ_S_SOFT)
+#define MIP_HSIP            (1 << IRQ_H_SOFT)
+#define MIP_MSIP            (1 << IRQ_M_SOFT)
+#define MIP_STIP            (1 << IRQ_S_TIMER)
+#define MIP_HTIP            (1 << IRQ_H_TIMER)
+#define MIP_MTIP            (1 << IRQ_M_TIMER)
 
 #define SIP_SSIP MIP_SSIP
 #define SIP_STIP MIP_STIP
 #define VM_SV39  9
 #define VM_SV48  10
 
-#define UA_RV32  0
-#define UA_RV64  4
-#define UA_RV128 8
-
-#define IRQ_SOFT   0
-#define IRQ_TIMER  1
-#define IRQ_HOST   2
-#define IRQ_COP    3
+#define IRQ_S_SOFT   1
+#define IRQ_H_SOFT   2
+#define IRQ_M_SOFT   3
+#define IRQ_S_TIMER  5
+#define IRQ_H_TIMER  6
+#define IRQ_M_TIMER  7
+#define IRQ_COP      8
+#define IRQ_HOST     9
 
 #define IMPL_ROCKET 1
 
 #define MASK_SCALL  0xffffffff
 #define MATCH_SBREAK 0x100073
 #define MASK_SBREAK  0xffffffff
-#define MATCH_SRET 0x10000073
+#define MATCH_SRET 0x10200073
 #define MASK_SRET  0xffffffff
-#define MATCH_SFENCE_VM 0x10100073
+#define MATCH_SFENCE_VM 0x10400073
 #define MASK_SFENCE_VM  0xfff07fff
-#define MATCH_WFI 0x10200073
+#define MATCH_WFI 0x10500073
 #define MASK_WFI  0xffffffff
-#define MATCH_MRTH 0x30600073
-#define MASK_MRTH  0xffffffff
-#define MATCH_MRTS 0x30500073
-#define MASK_MRTS  0xffffffff
-#define MATCH_HRTS 0x20500073
-#define MASK_HRTS  0xffffffff
 #define MATCH_CSRRW 0x1073
 #define MASK_CSRRW  0x707f
 #define MATCH_CSRRS 0x2073
 #define CSR_SIE 0x104
 #define CSR_SSCRATCH 0x140
 #define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_SBADADDR 0x143
 #define CSR_SIP 0x144
 #define CSR_SPTBR 0x180
 #define CSR_SASID 0x181
 #define CSR_TIMEW 0x901
 #define CSR_INSTRETW 0x902
 #define CSR_STIME 0xd01
-#define CSR_SCAUSE 0xd42
-#define CSR_SBADADDR 0xd43
 #define CSR_STIMEW 0xa01
 #define CSR_MSTATUS 0x300
 #define CSR_MTVEC 0x301
-#define CSR_MTDELEG 0x302
+#define CSR_MEDELEG 0x302
+#define CSR_MIDELEG 0x303
 #define CSR_MIE 0x304
 #define CSR_MTIMECMP 0x321
 #define CSR_MSCRATCH 0x340
@@ -787,9 +786,6 @@ DECLARE_INSN(sbreak, MATCH_SBREAK, MASK_SBREAK)
 DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
 DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
 DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
-DECLARE_INSN(mrth, MATCH_MRTH, MASK_MRTH)
-DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS)
-DECLARE_INSN(hrts, MATCH_HRTS, MASK_HRTS)
 DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
 DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
 DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
@@ -954,6 +950,8 @@ DECLARE_CSR(stvec, CSR_STVEC)
 DECLARE_CSR(sie, CSR_SIE)
 DECLARE_CSR(sscratch, CSR_SSCRATCH)
 DECLARE_CSR(sepc, CSR_SEPC)
+DECLARE_CSR(scause, CSR_SCAUSE)
+DECLARE_CSR(sbadaddr, CSR_SBADADDR)
 DECLARE_CSR(sip, CSR_SIP)
 DECLARE_CSR(sptbr, CSR_SPTBR)
 DECLARE_CSR(sasid, CSR_SASID)
@@ -961,12 +959,11 @@ DECLARE_CSR(cyclew, CSR_CYCLEW)
 DECLARE_CSR(timew, CSR_TIMEW)
 DECLARE_CSR(instretw, CSR_INSTRETW)
 DECLARE_CSR(stime, CSR_STIME)
-DECLARE_CSR(scause, CSR_SCAUSE)
-DECLARE_CSR(sbadaddr, CSR_SBADADDR)
 DECLARE_CSR(stimew, CSR_STIMEW)
 DECLARE_CSR(mstatus, CSR_MSTATUS)
 DECLARE_CSR(mtvec, CSR_MTVEC)
-DECLARE_CSR(mtdeleg, CSR_MTDELEG)
+DECLARE_CSR(medeleg, CSR_MEDELEG)
+DECLARE_CSR(mideleg, CSR_MIDELEG)
 DECLARE_CSR(mie, CSR_MIE)
 DECLARE_CSR(mtimecmp, CSR_MTIMECMP)
 DECLARE_CSR(mscratch, CSR_MSCRATCH)
index 4711b49b958b2b1e545b7ba59b9b2326306084ea..a2e71a166702c40b4311e576bde229c1d211782c 100644 (file)
@@ -8,7 +8,7 @@
 static void commit_log_stash_privilege(state_t* state)
 {
 #ifdef RISCV_ENABLE_COMMITLOG
-  state->last_inst_priv = get_field(state->mstatus, MSTATUS_PRV);
+  state->last_inst_priv = state->prv;
 #endif
 }
 
index 00cd24ff9bd174daf33b4c4e92bcf83649dfec19..5321c42c17d96b5f7a985716f36691cc1215ecb2 100644 (file)
@@ -14,12 +14,11 @@ void extension_t::illegal_instruction()
 
 void extension_t::raise_interrupt()
 {
-  int priv = get_field(p->get_state()->mstatus, MSTATUS_PRV);
-  int ie = get_field(p->get_state()->mstatus, MSTATUS_IE);
+  reg_t prv = p->get_state()->prv;
+  reg_t mie = get_field(p->get_state()->mstatus, MSTATUS_MIE);
 
-  if (priv < PRV_M || (priv == PRV_M && ie)) {
+  if (prv < PRV_M || (prv == PRV_M && mie))
     p->raise_interrupt(IRQ_COP);
-  }
 
   throw std::logic_error("a COP exception was posted, but interrupts are disabled!");
 }
index ecaaf20d31c042d99fb11a820029d97b6de93ac0..14f6381ec74cc50049cc0a604dc7821f4625d8f1 100644 (file)
@@ -94,7 +94,7 @@ void htif_isasim_t::tick_once()
         case CSR_MFROMHOST:
           old_val = proc->get_state()->fromhost;
           if (write && old_val == 0)
-            proc->get_state()->fromhost = new_val;
+            proc->set_csr(CSR_MFROMHOST, new_val);
           break;
         case CSR_MRESET:
           old_val = !proc->running();
diff --git a/riscv/insns/hrts.h b/riscv/insns/hrts.h
deleted file mode 100644 (file)
index a627bbe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-throw trap_illegal_instruction();
diff --git a/riscv/insns/mrth.h b/riscv/insns/mrth.h
deleted file mode 100644 (file)
index a627bbe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-throw trap_illegal_instruction();
diff --git a/riscv/insns/mrts.h b/riscv/insns/mrts.h
deleted file mode 100644 (file)
index 34675b7..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-require_privilege(PRV_M);
-p->set_csr(CSR_MSTATUS, set_field(STATE.mstatus, MSTATUS_PRV, PRV_S));
-STATE.sbadaddr = STATE.mbadaddr;
-STATE.scause = STATE.mcause;
-STATE.sepc = STATE.mepc;
-set_pc(STATE.stvec);
index e8a055556c4cb24b067a0e118463ce2eaad02171..a933e4d2fa87fc1b5d09030b9ac23fe5b5833ba8 100644 (file)
@@ -1,4 +1,4 @@
-switch (get_field(STATE.mstatus, MSTATUS_PRV))
+switch (STATE.prv)
 {
   case PRV_U: throw trap_user_ecall();
   case PRV_S: throw trap_supervisor_ecall();
index 8c4bb8ef1f4d72ba87d5c8a431063f33f62fad60..eacf5bee5ff9cad6ce9106a8176b1b2281b99a18 100644 (file)
@@ -1,8 +1,16 @@
 require_privilege(PRV_S);
-switch (get_field(STATE.mstatus, MSTATUS_PRV))
+switch (STATE.prv)
 {
   case PRV_S: set_pc(p->get_state()->sepc); break;
   case PRV_M: set_pc(p->get_state()->mepc); break;
   default: abort();
 }
-p->pop_privilege_stack();
+
+reg_t s = STATE.mstatus;
+reg_t pie = get_field(s, MSTATUS_UPIE << STATE.prv);
+reg_t prev_prv = get_field(s, STATE.prv == PRV_S ? MSTATUS_SPP : MSTATUS_MPP);
+s = set_field(s, MSTATUS_UIE << prev_prv, pie); // [[prv]PP]IE = [prv]PIE
+s = set_field(s, MSTATUS_UPIE << STATE.prv, 0); // [prv]PIE <- 0
+p->set_privilege(prev_prv); // prv <- [prv]PP
+s = set_field(s, STATE.prv == PRV_S ? MSTATUS_SPP : MSTATUS_MPP, PRV_U); // [prv]PP = U
+p->set_csr(CSR_MSTATUS, s);
index 0073a8a562e840915353b4947e87b2b5517ff97d..0ba378579b122db6407648d1f5e7ea4aaaff3712 100644 (file)
@@ -34,9 +34,10 @@ reg_t mmu_t::translate(reg_t addr, access_type type)
   if (!proc)
     return addr;
 
-  reg_t mode = get_field(proc->state.mstatus, MSTATUS_PRV);
-  if (type != FETCH && get_field(proc->state.mstatus, MSTATUS_MPRV))
-    mode = get_field(proc->state.mstatus, MSTATUS_PRV1);
+  reg_t mode = proc->state.prv;
+  if (type != FETCH && proc->state.prv == PRV_M &&
+      get_field(proc->state.mstatus, MSTATUS_MPRV))
+    mode = get_field(proc->state.mstatus, MSTATUS_MPP);
   if (get_field(proc->state.mstatus, MSTATUS_VM) == VM_MBARE)
     mode = PRV_M;
 
index 8347b9df185f56115d26b85bcd5b644f50995bb9..a79ee7b635761a7d07d929b845e534c54e163a1f 100644 (file)
@@ -109,9 +109,7 @@ void processor_t::parse_isa_string(const char* str)
 void state_t::reset()
 {
   memset(this, 0, sizeof(*this));
-  mstatus = set_field(mstatus, MSTATUS_PRV, PRV_M);
-  mstatus = set_field(mstatus, MSTATUS_PRV1, PRV_U);
-  mstatus = set_field(mstatus, MSTATUS_PRV2, PRV_U);
+  prv = PRV_M;
   pc = DEFAULT_MTVEC + 0x100;
   load_reservation = -1;
 }
@@ -152,30 +150,28 @@ void processor_t::raise_interrupt(reg_t which)
   throw trap_t(((reg_t)1 << (max_xlen-1)) | which);
 }
 
-void processor_t::take_interrupt()
+static int ctz(reg_t val)
 {
-  int priv = get_field(state.mstatus, MSTATUS_PRV);
-  int ie = get_field(state.mstatus, MSTATUS_IE);
-  reg_t interrupts = state.mie & state.mip;
-
-  if (priv < PRV_M || (priv == PRV_M && ie)) {
-    if (interrupts & MIP_MSIP)
-      raise_interrupt(IRQ_SOFT);
-
-    if (interrupts & MIP_MTIP)
-      raise_interrupt(IRQ_TIMER);
+  int res = 0;
+  if (val)
+    while ((val & 1) == 0)
+      val >>= 1, res++;
+  return res;
+}
 
-    if (state.fromhost != 0)
-      raise_interrupt(IRQ_HOST);
-  }
+void processor_t::take_interrupt()
+{
+  reg_t interrupts = state.mip & state.mie;
 
-  if (priv < PRV_S || (priv == PRV_S && ie)) {
-    if (interrupts & MIP_SSIP)
-      raise_interrupt(IRQ_SOFT);
+  reg_t m_interrupts = interrupts & ~state.mideleg;
+  reg_t mie = get_field(state.mstatus, MSTATUS_MIE);
+  if ((state.prv < PRV_M || (state.prv == PRV_M && mie)) && m_interrupts)
+    raise_interrupt(ctz(m_interrupts));
 
-    if (interrupts & MIP_STIP)
-      raise_interrupt(IRQ_TIMER);
-  }
+  reg_t s_interrupts = interrupts & state.mideleg;
+  reg_t sie = get_field(state.mstatus, MSTATUS_SIE);
+  if ((state.prv < PRV_S || (state.prv == PRV_S && sie)) && s_interrupts)
+    raise_interrupt(ctz(s_interrupts));
 }
 
 void processor_t::check_timer()
@@ -184,29 +180,16 @@ void processor_t::check_timer()
     state.mip |= MIP_MTIP;
 }
 
-void processor_t::push_privilege_stack()
+static bool validate_priv(reg_t priv)
 {
-  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, 0);
-  s = set_field(s, MSTATUS_IE, 0);
-  set_csr(CSR_MSTATUS, s);
+  return priv == PRV_U || priv == PRV_S || priv == PRV_M;
 }
 
-void processor_t::pop_privilege_stack()
+void processor_t::set_privilege(reg_t prv)
 {
-  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);
+  assert(validate_priv(prv));
+  mmu->flush_tlb();
+  state.prv = prv;
 }
 
 void processor_t::take_trap(trap_t& t, reg_t epc)
@@ -215,12 +198,41 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
     fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
             id, t.name(), epc);
 
-  state.pc = DEFAULT_MTVEC + 0x40 * get_field(state.mstatus, MSTATUS_PRV);
-  push_privilege_stack();
+  // by default, trap to M-mode, unless delegated to S-mode
+  reg_t bit = t.cause();
+  reg_t deleg = state.medeleg;
+  if (bit & ((reg_t)1 << (max_xlen-1)))
+    deleg = state.mideleg, bit &= ~((reg_t)1 << (max_xlen-1));
+  if (state.prv <= PRV_S && bit < max_xlen && ((deleg >> bit) & 1)) {
+    // handle the trap in S-mode
+    state.pc = state.stvec;
+    state.scause = t.cause();
+    state.sepc = epc;
+    if (t.has_badaddr())
+      state.sbadaddr = t.get_badaddr();
+
+    reg_t s = state.mstatus;
+    s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_UIE << state.prv));
+    s = set_field(s, MSTATUS_SPP, state.prv);
+    s = set_field(s, MSTATUS_SIE, 0);
+    set_csr(CSR_MSTATUS, s);
+    set_privilege(PRV_S);
+  } else {
+    state.pc = DEFAULT_MTVEC + 0x40 * state.prv;
+    state.mcause = t.cause();
+    state.mepc = epc;
+    if (t.has_badaddr())
+      state.mbadaddr = t.get_badaddr();
+
+    reg_t s = state.mstatus;
+    s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_UIE << state.prv));
+    s = set_field(s, MSTATUS_MPP, state.prv);
+    s = set_field(s, MSTATUS_MIE, 0);
+    set_csr(CSR_MSTATUS, s);
+    set_privilege(PRV_M);
+  }
+
   yield_load_reservation();
-  state.mcause = t.cause();
-  state.mepc = epc;
-  t.side_effects(&state); // might set badvaddr etc.
 }
 
 void processor_t::disasm(insn_t insn)
@@ -230,11 +242,6 @@ void processor_t::disasm(insn_t insn)
           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_vm(int max_xlen, reg_t vm)
 {
   if (max_xlen == 64 && (vm == VM_SV39 || vm == VM_SV48))
@@ -246,6 +253,8 @@ static bool validate_vm(int max_xlen, reg_t vm)
 
 void processor_t::set_csr(int which, reg_t val)
 {
+  reg_t all_ints = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP | (1UL << IRQ_HOST);
+  reg_t s_ints = MIP_SSIP | MIP_STIP;
   switch (which)
   {
     case CSR_FFLAGS:
@@ -294,20 +303,17 @@ void processor_t::set_csr(int which, reg_t val)
       state.suinstret_delta = (val << 32) | (uint32_t)state.suinstret_delta;
       break;
     case CSR_MSTATUS: {
-      if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV))
+      if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_MPP | MSTATUS_MPRV))
         mmu->flush_tlb();
 
-      reg_t mask = MSTATUS_IE | MSTATUS_IE1 | MSTATUS_IE2 | MSTATUS_MPRV
-                   | MSTATUS_FS | (ext ? MSTATUS_XS : 0);
+      reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
+                 | MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_FS
+                 | (ext ? MSTATUS_XS : 0);
 
       if (validate_vm(max_xlen, get_field(val, MSTATUS_VM)))
         mask |= MSTATUS_VM;
-      if (validate_priv(get_field(val, MSTATUS_PRV)))
-        mask |= MSTATUS_PRV;
-      if (validate_priv(get_field(val, MSTATUS_PRV1)))
-        mask |= MSTATUS_PRV1;
-      if (validate_priv(get_field(val, MSTATUS_PRV2)))
-        mask |= MSTATUS_PRV2;
+      if (validate_priv(get_field(val, MSTATUS_MPP)))
+        mask |= MSTATUS_MPP;
 
       state.mstatus = (state.mstatus & ~mask) | (val & mask);
 
@@ -324,36 +330,40 @@ void processor_t::set_csr(int which, reg_t val)
       break;
     }
     case CSR_MIP: {
-      reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
+      reg_t mask = all_ints &~ MIP_MTIP;
       state.mip = (state.mip & ~mask) | (val & mask);
       break;
     }
-    case CSR_MIPI: {
+    case CSR_MIPI:
       state.mip = set_field(state.mip, MIP_MSIP, val & 1);
       break;
-    }
-    case CSR_MIE: {
-      reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP;
-      state.mie = (state.mie & ~mask) | (val & mask);
+    case CSR_MIE:
+      state.mie = (state.mie & ~all_ints) | (val & all_ints);
+      break;
+    case CSR_MIDELEG:
+      state.mideleg = (state.mideleg & ~s_ints) | (val & s_ints);
+      break;
+    case CSR_MEDELEG: {
+      reg_t mask = 0;
+#define DECLARE_CAUSE(name, value) mask |= 1ULL << (value);
+#include "encoding.h"
+#undef DECLARE_CAUSE
+      state.medeleg = (state.medeleg & ~mask) | (val & mask);
       break;
     }
     case CSR_SSTATUS: {
-      reg_t ms = state.mstatus;
-      ms = set_field(ms, MSTATUS_IE, get_field(val, SSTATUS_IE));
-      ms = set_field(ms, MSTATUS_IE1, get_field(val, SSTATUS_PIE));
-      ms = set_field(ms, MSTATUS_PRV1, get_field(val, SSTATUS_PS));
-      ms = set_field(ms, MSTATUS_FS, get_field(val, SSTATUS_FS));
-      ms = set_field(ms, MSTATUS_XS, get_field(val, SSTATUS_XS));
-      ms = set_field(ms, MSTATUS_MPRV, get_field(val, SSTATUS_MPRV));
-      return set_csr(CSR_MSTATUS, ms);
+      reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
+                 | SSTATUS_XS;
+      set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask));
+      break;
     }
     case CSR_SIP: {
-      reg_t mask = MIP_SSIP;
+      reg_t mask = s_ints &~ MIP_STIP;
       state.mip = (state.mip & ~mask) | (val & mask);
       break;
     }
     case CSR_SIE: {
-      reg_t mask = MIP_SSIP | MIP_STIP;
+      reg_t mask = s_ints;
       state.mie = (state.mie & ~mask) | (val & mask);
       break;
     }
@@ -361,6 +371,8 @@ void processor_t::set_csr(int which, reg_t val)
     case CSR_STVEC: state.stvec = val >> 2 << 2; break;
     case CSR_SPTBR: state.sptbr = zext_xlen(val & -PGSIZE); break;
     case CSR_SSCRATCH: state.sscratch = val; break;
+    case CSR_SCAUSE: state.scause = val; break;
+    case CSR_SBADADDR: state.sbadaddr = val; break;
     case CSR_MEPC: state.mepc = val; break;
     case CSR_MSCRATCH: state.mscratch = val; break;
     case CSR_MCAUSE: state.mcause = val; break;
@@ -373,7 +385,10 @@ void processor_t::set_csr(int which, reg_t val)
       if (state.tohost == 0)
         state.tohost = val;
       break;
-    case CSR_MFROMHOST: state.fromhost = val; break;
+    case CSR_MFROMHOST:
+      state.mip = (state.mip & ~(1 << IRQ_HOST)) | (val ? (1 << IRQ_HOST) : 0);
+      state.fromhost = val;
+      break;
   }
 }
 
@@ -425,16 +440,12 @@ reg_t processor_t::get_csr(int which)
         break;
       return (state.minstret + state.suinstret_delta) >> 32;
     case CSR_SSTATUS: {
-      reg_t ss = 0;
-      ss = set_field(ss, SSTATUS_IE, get_field(state.mstatus, MSTATUS_IE));
-      ss = set_field(ss, SSTATUS_PIE, get_field(state.mstatus, MSTATUS_IE1));
-      ss = set_field(ss, SSTATUS_PS, get_field(state.mstatus, MSTATUS_PRV1));
-      ss = set_field(ss, SSTATUS_FS, get_field(state.mstatus, MSTATUS_FS));
-      ss = set_field(ss, SSTATUS_XS, get_field(state.mstatus, MSTATUS_XS));
-      ss = set_field(ss, SSTATUS_MPRV, get_field(state.mstatus, MSTATUS_MPRV));
-      if (get_field(state.mstatus, MSTATUS64_SD))
-        ss = set_field(ss, (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD), 1);
-      return ss;
+      reg_t sstatus = state.mstatus &
+        (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS);
+      if ((sstatus & SSTATUS_FS) == SSTATUS_FS ||
+          (sstatus & SSTATUS_XS) == SSTATUS_XS)
+        sstatus |= (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD);
+      return sstatus;
     }
     case CSR_SIP: return state.mip & (MIP_SSIP | MIP_STIP);
     case CSR_SIE: return state.mie & (MIP_SSIP | MIP_STIP);
@@ -461,7 +472,8 @@ reg_t processor_t::get_csr(int which)
     case CSR_MIMPID: return IMPL_ROCKET;
     case CSR_MHARTID: return id;
     case CSR_MTVEC: return DEFAULT_MTVEC;
-    case CSR_MTDELEG: return 0;
+    case CSR_MEDELEG: return state.medeleg;
+    case CSR_MIDELEG: return state.mideleg;
     case CSR_MTOHOST:
       sim->get_htif()->tick(); // not necessary, but faster
       return state.tohost;
index 13c4cbbcf91c7a803fbf4fc4c299a0b7e30193c9..80cea366c94d6509f524b981807064163a9a910d 100644 (file)
@@ -41,6 +41,7 @@ struct state_t
   regfile_t<freg_t, NFPR, false> FPR;
 
   // control and status registers
+  reg_t prv;
   reg_t mstatus;
   reg_t mepc;
   reg_t mbadaddr;
@@ -50,6 +51,8 @@ struct state_t
   reg_t minstret;
   reg_t mie;
   reg_t mip;
+  reg_t medeleg;
+  reg_t mideleg;
   reg_t sepc;
   reg_t sbadaddr;
   reg_t sscratch;
@@ -94,8 +97,7 @@ public:
     if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
     return ext >= 'A' && ext <= 'Z' && ((cpuid >> (ext - 'A')) & 1);
   }
-  void push_privilege_stack();
-  void pop_privilege_stack();
+  void set_privilege(reg_t);
   void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
   void update_histogram(reg_t pc);
 
@@ -114,8 +116,8 @@ private:
   state_t state;
   reg_t cpuid;
   uint32_t id;
-  int max_xlen;
-  int xlen;
+  unsigned max_xlen;
+  unsigned xlen;
   std::string isa;
   bool run; // !reset
   bool debug;
index 7d71fb51f3faf0fd81ae70ce3e70d981128fadf4..1d9b301344b7a190979800879353c1e1eac4753f 100644 (file)
@@ -190,7 +190,6 @@ riscv_insn_list = \
        fsub_d \
        fsub_s \
        fsw \
-       hrts \
        jal \
        jalr \
        lb \
@@ -203,8 +202,6 @@ riscv_insn_list = \
        lui \
        lw \
        lwu \
-       mrth \
-       mrts \
        mul \
        mulh \
        mulhsu \
index 5add05d75d3f1be86c57f668d278ed0f8b5c4d48..4ac2f1f717423ca0ba133840b54abfcfb37c0a3e 100644 (file)
@@ -10,8 +10,3 @@ const char* trap_t::name()
   sprintf(_name, fmt, uint8_t(which));
   return _name;
 }
-
-void mem_trap_t::side_effects(state_t* state)
-{
-  state->mbadaddr = badvaddr;
-}
index b03bf67a83a5134b8f0d39fe80b14e9c4464c65a..7f35c5f69c40669e9be6f3495a57340789640193 100644 (file)
@@ -4,6 +4,7 @@
 #define _RISCV_TRAP_H
 
 #include "decode.h"
+#include <stdlib.h>
 
 struct state_t;
 
@@ -12,7 +13,8 @@ class trap_t
  public:
   trap_t(reg_t which) : which(which) {}
   virtual const char* name();
-  virtual void side_effects(state_t* state) {}
+  virtual bool has_badaddr() { return false; }
+  virtual reg_t get_badaddr() { abort(); }
   reg_t cause() { return which; }
  private:
   char _name[16];
@@ -22,12 +24,12 @@ class trap_t
 class mem_trap_t : public trap_t
 {
  public:
-  mem_trap_t(reg_t which, reg_t badvaddr)
-    : trap_t(which), badvaddr(badvaddr) {}
-  void side_effects(state_t* state);
-  reg_t get_badvaddr() { return badvaddr; }
+  mem_trap_t(reg_t which, reg_t badaddr)
+    : trap_t(which), badaddr(badaddr) {}
+  bool has_badaddr() override { return true; }
+  reg_t get_badaddr() override { return badaddr; }
  private:
-  reg_t badvaddr;
+  reg_t badaddr;
 };
 
 #define DECLARE_TRAP(n, x) class trap_##x : public trap_t { \
@@ -38,7 +40,7 @@ class mem_trap_t : public trap_t
 
 #define DECLARE_MEM_TRAP(n, x) class trap_##x : public mem_trap_t { \
  public: \
-  trap_##x(reg_t badvaddr) : mem_trap_t(n, badvaddr) {} \
+  trap_##x(reg_t badaddr) : mem_trap_t(n, badaddr) {} \
   const char* name() { return "trap_"#x; } \
 };