Update to new privileged spec
authorAndrew Waterman <waterman@cs.berkeley.edu>
Fri, 13 Mar 2015 00:32:43 +0000 (17:32 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Fri, 13 Mar 2015 00:32:43 +0000 (17:32 -0700)
Sorry, everyone.

74 files changed:
hwacha/decode_hwacha.h
hwacha/hwacha.cc
hwacha/insns_ut/ut_fcvt_h_l.h
hwacha/insns_ut/ut_fcvt_h_lu.h
hwacha/insns_ut/ut_fcvt_l_h.h
hwacha/insns_ut/ut_fcvt_lu_h.h
riscv/decode.h
riscv/encoding.h
riscv/extension.cc
riscv/htif.cc
riscv/insns/addiw.h
riscv/insns/addw.h
riscv/insns/amoadd_d.h
riscv/insns/amoand_d.h
riscv/insns/amomax_d.h
riscv/insns/amomaxu_d.h
riscv/insns/amomin_d.h
riscv/insns/amominu_d.h
riscv/insns/amoor_d.h
riscv/insns/amoswap_d.h
riscv/insns/amoxor_d.h
riscv/insns/csrrc.h
riscv/insns/csrrci.h
riscv/insns/csrrs.h
riscv/insns/csrrsi.h
riscv/insns/csrrw.h
riscv/insns/csrrwi.h
riscv/insns/divuw.h
riscv/insns/divw.h
riscv/insns/fcvt_d_l.h
riscv/insns/fcvt_d_lu.h
riscv/insns/fcvt_l_d.h
riscv/insns/fcvt_l_s.h
riscv/insns/fcvt_lu_d.h
riscv/insns/fcvt_lu_s.h
riscv/insns/fcvt_s_l.h
riscv/insns/fcvt_s_lu.h
riscv/insns/fmv_d_x.h
riscv/insns/fmv_x_d.h
riscv/insns/ld.h
riscv/insns/lr_d.h
riscv/insns/lwu.h
riscv/insns/mcall.h [new file with mode: 0644]
riscv/insns/mret.h [new file with mode: 0644]
riscv/insns/mrts.h [new file with mode: 0644]
riscv/insns/mulh.h
riscv/insns/mulhsu.h
riscv/insns/mulhu.h
riscv/insns/mulw.h
riscv/insns/remuw.h
riscv/insns/remw.h
riscv/insns/sc_d.h
riscv/insns/scall.h
riscv/insns/sd.h
riscv/insns/sfence_vm.h [new file with mode: 0644]
riscv/insns/slli.h
riscv/insns/slliw.h
riscv/insns/sllw.h
riscv/insns/srai.h
riscv/insns/sraiw.h
riscv/insns/sraw.h
riscv/insns/sret.h
riscv/insns/srl.h
riscv/insns/srli.h
riscv/insns/srliw.h
riscv/insns/srlw.h
riscv/insns/subw.h
riscv/interactive.cc
riscv/mmu.cc
riscv/processor.cc
riscv/processor.h
riscv/rocc.cc
riscv/trap.cc
riscv/trap.h

index 5e85bf6b5d17a0a1a1cc5890b4de935f58f7c348..b00c6af94e27952fa8be49bf4cc54dff930044ae 100644 (file)
@@ -99,7 +99,7 @@ static inline void write_fpr(hwacha_t* h, insn_t insn, uint32_t idx, size_t dst,
   }
 
 #define require_supervisor_hwacha \
-  if (unlikely(!(p->get_state()->sr & SR_S))) \
+  if (get_field(p->get_state()->mstatus, MSTATUS_PRV) < PRV_S) \
     h->take_exception(HWACHA_CAUSE_PRIVILEGED_INSTRUCTION, uint32_t(insn.bits()));
 
 #endif
index a56db12409f127640a80a5f468d4051871799b9a..972e151b9c53592c414b0db308f1a745b660d0a6 100644 (file)
@@ -20,9 +20,7 @@ void ct_state_t::reset()
 
 void ut_state_t::reset()
 {
-  run = false;
-  XPR.reset();
-  FPR.reset();
+  memset(this, 0, sizeof(*this));
 }
 
 void hwacha_t::reset()
@@ -105,7 +103,5 @@ void hwacha_t::take_exception(reg_t c, reg_t a)
   cause = c;
   aux = a;
   raise_interrupt();
-  if (!(p->get_state()->sr & SR_EI))
-    throw std::logic_error("hwacha exception posted, but SR_EI bit not set!");
-  throw std::logic_error("hwacha exception posted, but IM[COP] bit not set!");
+  throw std::logic_error("a hwacha exception was posted, but interrupts are disabled!");
 }
index fe75c27475067b692405f49bf27f787b3c8a6c01..69f39ec37a0b1f3a8fe1cc0d1d93105c75ea4365 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_HFRD(i64_to_f32(RS1));
index 38fc8a7e742580d85d7f18e19060569e141f3d2f..ab749771edcc50c850daabf45aa615937f58f51a 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_HFRD(ui64_to_f32(RS1));
index 1551ce2ef7fbd90deecad9e298543b8ea4a3f8c9..d3128d64359952ef635a5860933aef7a11b6499a 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_RD(f32_to_i64(HFRS1, RM, true));
index b2fc5fdc8441b7c7794cb68c854c2dc0103d70e3..a1cedea682d544ef7c977ad281ab569aeedf1aef 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_RD(f32_to_ui64(HFRS1, RM, true));
index 6ac465a07c74ba6cf942ab963dc96d29cb108848..2fdb042f5074b18090664aad86ff295699ad26e5 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <cstdint>
 #include <string.h>
+#include <strings.h>
 #include "encoding.h"
 #include "config.h"
 #include "common.h"
@@ -80,10 +81,6 @@ template <class T, size_t N, bool zero_reg>
 class regfile_t
 {
 public:
-  void reset()
-  {
-    memset(data, 0, sizeof(data));
-  }
   void write(size_t i, T value)
   {
     if (!zero_reg || i != 0)
@@ -116,14 +113,17 @@ private:
 #define FRS1 STATE.FPR[insn.rs1()]
 #define FRS2 STATE.FPR[insn.rs2()]
 #define FRS3 STATE.FPR[insn.rs3()]
-#define WRITE_FRD(value) STATE.FPR.write(insn.rd(), value)
+#define dirty_fp_state (STATE.mstatus |= MSTATUS_FS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
+#define dirty_ext_state (STATE.mstatus |= MSTATUS_XS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
+#define do_write_frd(value) (STATE.FPR.write(insn.rd(), value), dirty_fp_state)
  
-#ifdef RISCV_ENABLE_COMMITLOG
-  #undef WRITE_FRD 
-  #define WRITE_FRD(value) ({ \
-        freg_t wdata = value; /* value is a func with side-effects */ \
+#ifndef RISCV_ENABLE_COMMITLOG
+# define WRITE_FRD(value) do_write_frd(value)
+#else
+# define WRITE_FRD(value) ({ \
+        freg_t wdata = (value); /* value may have side effects */ \
         STATE.log_reg_write = (commit_log_reg_t){(insn.rd() << 1) | 1, wdata}; \
-        STATE.FPR.write(insn.rd(), wdata); \
+        do_write_frd(wdata); \
       })
 #endif
  
@@ -135,17 +135,14 @@ private:
               if(rm > 4) throw trap_illegal_instruction(); \
               rm; })
 
-#define xpr64 (xlen == 64)
+#define get_field(reg, mask) (((reg) & (decltype(reg))(mask)) / ((mask) & ~((mask) << 1)))
+#define set_field(reg, mask, val) (((reg) & ~(decltype(reg))(mask)) | (((decltype(reg))(val) * ((mask) & ~((mask) << 1))) & (decltype(reg))(mask)))
 
-#define require_supervisor if(unlikely(!(STATE.sr & SR_S))) throw trap_privileged_instruction()
-#define require_xpr64 if(unlikely(!xpr64)) throw trap_illegal_instruction()
-#define require_xpr32 if(unlikely(xpr64)) throw trap_illegal_instruction()
-#ifndef RISCV_ENABLE_FPU
-# define require_fp throw trap_illegal_instruction()
-#else
-# define require_fp if(unlikely(!(STATE.sr & SR_EF))) throw trap_fp_disabled()
-#endif
-#define require_accelerator if(unlikely(!(STATE.sr & SR_EA))) throw trap_accelerator_disabled()
+#define require_privilege(p) if (get_field(STATE.mstatus, MSTATUS_PRV) < (p)) throw trap_illegal_instruction()
+#define require_rv64 if(unlikely(xlen != 64)) throw trap_illegal_instruction()
+#define require_rv32 if(unlikely(xlen != 32)) throw trap_illegal_instruction()
+#define require_fp if (unlikely((STATE.mstatus & MSTATUS_FS) == 0)) throw trap_illegal_instruction()
+#define require_accelerator if (unlikely((STATE.mstatus & MSTATUS_XS) == 0)) throw trap_illegal_instruction()
 
 #define cmp_trunc(reg) (reg_t(reg) << (64-xlen))
 #define set_fp_exceptions ({ STATE.fflags |= softfloat_exceptionFlags; \
@@ -159,12 +156,11 @@ private:
 #define set_pc(x) (npc = sext_xlen(x))
 
 #define validate_csr(which, write) ({ \
-  unsigned my_priv = (STATE.sr & SR_S) ? 1 : 0; \
-  unsigned read_priv = ((which) >> 10) & 3; \
-  unsigned write_priv = (((which) >> 8) & 3); \
-  if (read_priv == 3) read_priv = write_priv, write_priv = -1; \
-  if (my_priv < ((write) ? write_priv : read_priv)) \
-    throw trap_privileged_instruction(); \
+  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) \
+    throw trap_illegal_instruction(); \
   (which); })
 
 #endif
index 089a8a99ea85a19175dcfaf431d2e3687f2d1ded..4b929d395e81c1ddfd150a2606faa826e42743d6 100644 (file)
@@ -3,25 +3,61 @@
 #ifndef RISCV_CSR_ENCODING_H
 #define RISCV_CSR_ENCODING_H
 
-#define SR_S     0x00000001
-#define SR_PS    0x00000002
-#define SR_EI    0x00000004
-#define SR_PEI   0x00000008
-#define SR_EF    0x00000010
-#define SR_U64   0x00000020
-#define SR_S64   0x00000040
-#define SR_VM    0x00000080
-#define SR_EA    0x00000100
-#define SR_IM    0x00FF0000
-#define SR_IP    0xFF000000
-#define SR_ZERO  ~(SR_S|SR_PS|SR_EI|SR_PEI|SR_EF|SR_U64|SR_S64|SR_VM|SR_EA|SR_IM|SR_IP)
-#define SR_IM_SHIFT 16
-#define SR_IP_SHIFT 24
+#define MSTATUS_SSIP        0x00000002
+#define MSTATUS_HSIP        0x00000004
+#define MSTATUS_MSIP        0x00000008
+#define MSTATUS_IE          0x00000010
+#define MSTATUS_PRV         0x00000060
+#define MSTATUS_IE1         0x00000080
+#define MSTATUS_PRV1        0x00000300
+#define MSTATUS_IE2         0x00000400
+#define MSTATUS_PRV2        0x00001800
+#define MSTATUS_IE3         0x00002000
+#define MSTATUS_PRV3        0x0000C000
+#define MSTATUS_MPRV        0x00030000
+#define MSTATUS_VM          0x00780000
+#define MSTATUS_STIE        0x01000000
+#define MSTATUS_HTIE        0x02000000
+#define MSTATUS_MTIE        0x04000000
+#define MSTATUS_FS          0x18000000
+#define MSTATUS_XS          0x60000000
+#define MSTATUS32_SD        0x80000000
+#define MSTATUS64_UA        0x0000000F00000000
+#define MSTATUS64_SA        0x000000F000000000
+#define MSTATUS64_HA        0x00000F0000000000
+#define MSTATUS64_SD        0x8000000000000000
 
-#define IRQ_COP   2
-#define IRQ_IPI   5
-#define IRQ_HOST  6
-#define IRQ_TIMER 7
+#define SSTATUS_SIP         0x00000002
+#define SSTATUS_IE          0x00000010
+#define SSTATUS_PIE         0x00000080
+#define SSTATUS_PS          0x00000100
+#define SSTATUS_UA          0x000F0000
+#define SSTATUS_TIE         0x01000000
+#define SSTATUS_TIP         0x04000000
+#define SSTATUS_FS          0x18000000
+#define SSTATUS_XS          0x60000000
+#define SSTATUS32_SD        0x80000000
+#define SSTATUS64_SD        0x8000000000000000
+
+#define PRV_U 0
+#define PRV_S 1
+#define PRV_H 2
+#define PRV_M 3
+
+#define VM_MBARE 0
+#define VM_MBB   1
+#define VM_MBBID 2
+#define VM_SV32  4
+#define VM_SV43  5
+
+#define UA_RV32  0
+#define UA_RV64  4
+#define UA_RV128 8
+
+#define IRQ_TIMER  0
+#define IRQ_IPI    1
+#define IRQ_HOST   2
+#define IRQ_COP    3
 
 #define IMPL_SPIKE  1
 #define IMPL_ROCKET 2
 #ifdef __riscv
 
 #ifdef __riscv64
+# define MSTATUS_UA MSTATUS64_UA
+# define MSTATUS_SA MSTATUS64_SA
+# define MSTATUS_HA MSTATUS64_HA
+# define MSTATUS_SD MSTATUS64_SD
+# define SSTATUS_SD SSTATUS64_SD
 # define RISCV_PGLEVELS 3
 # define RISCV_PGSHIFT 13
 #else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
 # define RISCV_PGLEVELS 2
 # define RISCV_PGSHIFT 12
 #endif
@@ -52,7 +95,9 @@
 
 #ifndef __ASSEMBLER__
 
-#define read_csr(reg) ({ long __tmp; \
+#ifdef __GNUC__
+
+#define read_csr(reg) ({ unsigned long __tmp; \
   asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
   __tmp; })
 
   asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
   __tmp; })
 
-#define set_csr(reg, bit) ({ long __tmp; \
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
   if (__builtin_constant_p(bit) && (bit) < 32) \
     asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
   else \
     asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
   __tmp; })
 
-#define clear_csr(reg, bit) ({ long __tmp; \
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
   if (__builtin_constant_p(bit) && (bit) < 32) \
     asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
   else \
     asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
   __tmp; })
 
-#define rdtime() ({ unsigned long __tmp; \
-  asm volatile ("rdtime %0" : "=r"(__tmp)); \
-  __tmp; })
-
-#define rdcycle() ({ unsigned long __tmp; \
-  asm volatile ("rdcycle %0" : "=r"(__tmp)); \
-  __tmp; })
+#define rdtime() read_csr(time)
+#define rdcycle() read_csr(cycle)
+#define rdinstret() read_csr(instret)
 
-#define rdinstret() ({ unsigned long __tmp; \
-  asm volatile ("rdinstret %0" : "=r"(__tmp)); \
-  __tmp; })
+#endif
 
 #endif
 
 #define MASK_FSGNJN_D  0xfe00707f
 #define MATCH_FMIN_S 0x28000053
 #define MASK_FMIN_S  0xfe00707f
+#define MATCH_MRET 0x30200073
+#define MASK_MRET  0xffffffff
 #define MATCH_CSRRW 0x1073
 #define MASK_CSRRW  0x707f
 #define MATCH_SLLIW 0x101b
 #define MASK_SCALL  0xffffffff
 #define MATCH_FCLASS_S 0xe0001053
 #define MASK_FCLASS_S  0xfff0707f
+#define MATCH_SFENCE_VM 0x10400073
+#define MASK_SFENCE_VM  0xfff07fff
 #define MATCH_SC_W 0x1800202f
 #define MASK_SC_W  0xf800707f
 #define MATCH_REM 0x2006033
 #define MASK_MULH  0xfe00707f
 #define MATCH_FMUL_S 0x10000053
 #define MASK_FMUL_S  0xfe00007f
+#define MATCH_MCALL 0x20000073
+#define MASK_MCALL  0xffffffff
 #define MATCH_CSRRSI 0x6073
 #define MASK_CSRRSI  0x707f
 #define MATCH_SRAI 0x40005013
 #define MASK_FSUB_D  0xfe00007f
 #define MATCH_FSGNJX_S 0x20002053
 #define MASK_FSGNJX_S  0xfe00707f
+#define MATCH_MRTS 0x30900073
+#define MASK_MRTS  0xffffffff
 #define MATCH_FEQ_D 0xa2002053
 #define MASK_FEQ_D  0xfe00707f
 #define MATCH_FCVT_D_WU 0xd2100053
 #define MASK_ANDI  0x707f
 #define MATCH_FMV_X_S 0xe0000053
 #define MASK_FMV_X_S  0xfff0707f
-#define MATCH_SRET 0x80000073
+#define MATCH_SRET 0x10200073
 #define MASK_SRET  0xffffffff
 #define MATCH_FNMADD_S 0x4f
 #define MASK_FNMADD_S  0x600007f
 #define CSR_FFLAGS 0x1
 #define CSR_FRM 0x2
 #define CSR_FCSR 0x3
-#define CSR_STATS 0xc0
-#define CSR_SUP0 0x500
-#define CSR_SUP1 0x501
-#define CSR_EPC 0x502
-#define CSR_BADVADDR 0x503
-#define CSR_PTBR 0x504
-#define CSR_ASID 0x505
-#define CSR_COUNT 0x506
-#define CSR_COMPARE 0x507
-#define CSR_EVEC 0x508
-#define CSR_CAUSE 0x509
-#define CSR_STATUS 0x50a
-#define CSR_HARTID 0x50b
-#define CSR_IMPL 0x50c
-#define CSR_FATC 0x50d
-#define CSR_SEND_IPI 0x50e
-#define CSR_CLEAR_IPI 0x50f
-#define CSR_RESET 0x51d
-#define CSR_TOHOST 0x51e
-#define CSR_FROMHOST 0x51f
 #define CSR_CYCLE 0xc00
 #define CSR_TIME 0xc01
 #define CSR_INSTRET 0xc02
+#define CSR_STATS 0xc0
 #define CSR_UARCH0 0xcc0
 #define CSR_UARCH1 0xcc1
 #define CSR_UARCH2 0xcc2
 #define CSR_UARCH13 0xccd
 #define CSR_UARCH14 0xcce
 #define CSR_UARCH15 0xccf
-#define CSR_COUNTH 0x586
+#define CSR_SSTATUS 0x100
+#define CSR_STVEC 0x101
+#define CSR_STIMECMP 0x121
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SPTBR 0x188
+#define CSR_SASID 0x189
+#define CSR_SCYCLE 0x900
+#define CSR_STIME 0x901
+#define CSR_SINSTRET 0x902
+#define CSR_SCAUSE 0xd40
+#define CSR_SBADADDR 0xd41
+#define CSR_MSTATUS 0x300
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MBADADDR 0x343
+#define CSR_RESET 0x780
+#define CSR_TOHOST 0x781
+#define CSR_FROMHOST 0x782
+#define CSR_SEND_IPI 0x783
+#define CSR_HARTID 0xfc0
 #define CSR_CYCLEH 0xc80
 #define CSR_TIMEH 0xc81
 #define CSR_INSTRETH 0xc82
+#define CSR_SCYCLEH 0x980
+#define CSR_STIMEH 0x981
+#define CSR_SINSTRETH 0x982
 #define CAUSE_MISALIGNED_FETCH 0x0
 #define CAUSE_FAULT_FETCH 0x1
 #define CAUSE_ILLEGAL_INSTRUCTION 0x2
-#define CAUSE_PRIVILEGED_INSTRUCTION 0x3
-#define CAUSE_FP_DISABLED 0x4
-#define CAUSE_SYSCALL 0x6
+#define CAUSE_SCALL 0x4
+#define CAUSE_HCALL 0x5
+#define CAUSE_MCALL 0x6
 #define CAUSE_BREAKPOINT 0x7
 #define CAUSE_MISALIGNED_LOAD 0x8
-#define CAUSE_MISALIGNED_STORE 0x9
-#define CAUSE_FAULT_LOAD 0xa
+#define CAUSE_FAULT_LOAD 0x9
+#define CAUSE_MISALIGNED_STORE 0xa
 #define CAUSE_FAULT_STORE 0xb
-#define CAUSE_ACCELERATOR_DISABLED 0xc
 #endif
 #ifdef DECLARE_INSN
 DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
@@ -479,6 +530,7 @@ DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
 DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
 DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
 DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
+DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
 DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
 DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
 DECLARE_INSN(lb, MATCH_LB, MASK_LB)
@@ -523,6 +575,7 @@ DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
 DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
 DECLARE_INSN(scall, MATCH_SCALL, MASK_SCALL)
 DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
+DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
 DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
 DECLARE_INSN(rem, MATCH_REM, MASK_REM)
 DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
@@ -531,6 +584,7 @@ DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
 DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
 DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
 DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
+DECLARE_INSN(mcall, MATCH_MCALL, MASK_MCALL)
 DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
 DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
 DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
@@ -551,6 +605,7 @@ DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
 DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
 DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
 DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
+DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS)
 DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
 DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
 DECLARE_INSN(or, MATCH_OR, MASK_OR)
@@ -633,29 +688,10 @@ DECLARE_INSN(sd, MATCH_SD, MASK_SD)
 DECLARE_CSR(fflags, CSR_FFLAGS)
 DECLARE_CSR(frm, CSR_FRM)
 DECLARE_CSR(fcsr, CSR_FCSR)
-DECLARE_CSR(stats, CSR_STATS)
-DECLARE_CSR(sup0, CSR_SUP0)
-DECLARE_CSR(sup1, CSR_SUP1)
-DECLARE_CSR(epc, CSR_EPC)
-DECLARE_CSR(badvaddr, CSR_BADVADDR)
-DECLARE_CSR(ptbr, CSR_PTBR)
-DECLARE_CSR(asid, CSR_ASID)
-DECLARE_CSR(count, CSR_COUNT)
-DECLARE_CSR(compare, CSR_COMPARE)
-DECLARE_CSR(evec, CSR_EVEC)
-DECLARE_CSR(cause, CSR_CAUSE)
-DECLARE_CSR(status, CSR_STATUS)
-DECLARE_CSR(hartid, CSR_HARTID)
-DECLARE_CSR(impl, CSR_IMPL)
-DECLARE_CSR(fatc, CSR_FATC)
-DECLARE_CSR(send_ipi, CSR_SEND_IPI)
-DECLARE_CSR(clear_ipi, CSR_CLEAR_IPI)
-DECLARE_CSR(reset, CSR_RESET)
-DECLARE_CSR(tohost, CSR_TOHOST)
-DECLARE_CSR(fromhost, CSR_FROMHOST)
 DECLARE_CSR(cycle, CSR_CYCLE)
 DECLARE_CSR(time, CSR_TIME)
 DECLARE_CSR(instret, CSR_INSTRET)
+DECLARE_CSR(stats, CSR_STATS)
 DECLARE_CSR(uarch0, CSR_UARCH0)
 DECLARE_CSR(uarch1, CSR_UARCH1)
 DECLARE_CSR(uarch2, CSR_UARCH2)
@@ -672,38 +708,43 @@ DECLARE_CSR(uarch12, CSR_UARCH12)
 DECLARE_CSR(uarch13, CSR_UARCH13)
 DECLARE_CSR(uarch14, CSR_UARCH14)
 DECLARE_CSR(uarch15, CSR_UARCH15)
-DECLARE_CSR(counth, CSR_COUNTH)
+DECLARE_CSR(sstatus, CSR_SSTATUS)
+DECLARE_CSR(stvec, CSR_STVEC)
+DECLARE_CSR(stimecmp, CSR_STIMECMP)
+DECLARE_CSR(sscratch, CSR_SSCRATCH)
+DECLARE_CSR(sepc, CSR_SEPC)
+DECLARE_CSR(sptbr, CSR_SPTBR)
+DECLARE_CSR(sasid, CSR_SASID)
+DECLARE_CSR(scycle, CSR_SCYCLE)
+DECLARE_CSR(stime, CSR_STIME)
+DECLARE_CSR(sinstret, CSR_SINSTRET)
+DECLARE_CSR(scause, CSR_SCAUSE)
+DECLARE_CSR(sbadaddr, CSR_SBADADDR)
+DECLARE_CSR(mstatus, CSR_MSTATUS)
+DECLARE_CSR(mscratch, CSR_MSCRATCH)
+DECLARE_CSR(mepc, CSR_MEPC)
+DECLARE_CSR(mcause, CSR_MCAUSE)
+DECLARE_CSR(mbadaddr, CSR_MBADADDR)
+DECLARE_CSR(reset, CSR_RESET)
+DECLARE_CSR(tohost, CSR_TOHOST)
+DECLARE_CSR(fromhost, CSR_FROMHOST)
+DECLARE_CSR(send_ipi, CSR_SEND_IPI)
+DECLARE_CSR(hartid, CSR_HARTID)
 DECLARE_CSR(cycleh, CSR_CYCLEH)
 DECLARE_CSR(timeh, CSR_TIMEH)
 DECLARE_CSR(instreth, CSR_INSTRETH)
+DECLARE_CSR(scycleh, CSR_SCYCLEH)
+DECLARE_CSR(stimeh, CSR_STIMEH)
+DECLARE_CSR(sinstreth, CSR_SINSTRETH)
 #endif
 #ifdef DECLARE_CAUSE
 DECLARE_CAUSE("fflags", CAUSE_FFLAGS)
 DECLARE_CAUSE("frm", CAUSE_FRM)
 DECLARE_CAUSE("fcsr", CAUSE_FCSR)
-DECLARE_CAUSE("stats", CAUSE_STATS)
-DECLARE_CAUSE("sup0", CAUSE_SUP0)
-DECLARE_CAUSE("sup1", CAUSE_SUP1)
-DECLARE_CAUSE("epc", CAUSE_EPC)
-DECLARE_CAUSE("badvaddr", CAUSE_BADVADDR)
-DECLARE_CAUSE("ptbr", CAUSE_PTBR)
-DECLARE_CAUSE("asid", CAUSE_ASID)
-DECLARE_CAUSE("count", CAUSE_COUNT)
-DECLARE_CAUSE("compare", CAUSE_COMPARE)
-DECLARE_CAUSE("evec", CAUSE_EVEC)
-DECLARE_CAUSE("cause", CAUSE_CAUSE)
-DECLARE_CAUSE("status", CAUSE_STATUS)
-DECLARE_CAUSE("hartid", CAUSE_HARTID)
-DECLARE_CAUSE("impl", CAUSE_IMPL)
-DECLARE_CAUSE("fatc", CAUSE_FATC)
-DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI)
-DECLARE_CAUSE("clear_ipi", CAUSE_CLEAR_IPI)
-DECLARE_CAUSE("reset", CAUSE_RESET)
-DECLARE_CAUSE("tohost", CAUSE_TOHOST)
-DECLARE_CAUSE("fromhost", CAUSE_FROMHOST)
 DECLARE_CAUSE("cycle", CAUSE_CYCLE)
 DECLARE_CAUSE("time", CAUSE_TIME)
 DECLARE_CAUSE("instret", CAUSE_INSTRET)
+DECLARE_CAUSE("stats", CAUSE_STATS)
 DECLARE_CAUSE("uarch0", CAUSE_UARCH0)
 DECLARE_CAUSE("uarch1", CAUSE_UARCH1)
 DECLARE_CAUSE("uarch2", CAUSE_UARCH2)
@@ -720,8 +761,32 @@ DECLARE_CAUSE("uarch12", CAUSE_UARCH12)
 DECLARE_CAUSE("uarch13", CAUSE_UARCH13)
 DECLARE_CAUSE("uarch14", CAUSE_UARCH14)
 DECLARE_CAUSE("uarch15", CAUSE_UARCH15)
-DECLARE_CAUSE("counth", CAUSE_COUNTH)
+DECLARE_CAUSE("sstatus", CAUSE_SSTATUS)
+DECLARE_CAUSE("stvec", CAUSE_STVEC)
+DECLARE_CAUSE("stimecmp", CAUSE_STIMECMP)
+DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH)
+DECLARE_CAUSE("sepc", CAUSE_SEPC)
+DECLARE_CAUSE("sptbr", CAUSE_SPTBR)
+DECLARE_CAUSE("sasid", CAUSE_SASID)
+DECLARE_CAUSE("scycle", CAUSE_SCYCLE)
+DECLARE_CAUSE("stime", CAUSE_STIME)
+DECLARE_CAUSE("sinstret", CAUSE_SINSTRET)
+DECLARE_CAUSE("scause", CAUSE_SCAUSE)
+DECLARE_CAUSE("sbadaddr", CAUSE_SBADADDR)
+DECLARE_CAUSE("mstatus", CAUSE_MSTATUS)
+DECLARE_CAUSE("mscratch", CAUSE_MSCRATCH)
+DECLARE_CAUSE("mepc", CAUSE_MEPC)
+DECLARE_CAUSE("mcause", CAUSE_MCAUSE)
+DECLARE_CAUSE("mbadaddr", CAUSE_MBADADDR)
+DECLARE_CAUSE("reset", CAUSE_RESET)
+DECLARE_CAUSE("tohost", CAUSE_TOHOST)
+DECLARE_CAUSE("fromhost", CAUSE_FROMHOST)
+DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI)
+DECLARE_CAUSE("hartid", CAUSE_HARTID)
 DECLARE_CAUSE("cycleh", CAUSE_CYCLEH)
 DECLARE_CAUSE("timeh", CAUSE_TIMEH)
 DECLARE_CAUSE("instreth", CAUSE_INSTRETH)
+DECLARE_CAUSE("scycleh", CAUSE_SCYCLEH)
+DECLARE_CAUSE("stimeh", CAUSE_STIMEH)
+DECLARE_CAUSE("sinstreth", CAUSE_SINSTRETH)
 #endif
index b758eef61cedd08ad218da8dbc4579a51c8c333f..c2bea2e648635f30ef513a57d2b97ddcc46172b3 100644 (file)
@@ -12,11 +12,9 @@ void extension_t::illegal_instruction()
 
 void extension_t::raise_interrupt()
 {
-  p->set_interrupt(IRQ_COP, true);
-  p->take_interrupt();
+  p->raise_interrupt(IRQ_COP);
 }
 
 void extension_t::clear_interrupt()
 {
-  p->set_interrupt(IRQ_COP, false);
 }
index 741a00f2401d6e2ae1f8784e767900cc857cdaeb..5234c7bb7d2317a0ba378a0abcce11657f009c9f 100644 (file)
@@ -84,23 +84,19 @@ void htif_isasim_t::tick_once()
       if (write)
         memcpy(&new_val, p.get_payload(), sizeof(new_val));
 
-      // TODO mapping HTIF regno to CSR[4:0] is arbitrary; consider alternative
       switch (regno)
       {
-        case CSR_HARTID & 0x1f:
-          old_val = coreid;
-          break;
-        case CSR_TOHOST & 0x1f:
+        case CSR_TOHOST:
           old_val = proc->get_state()->tohost;
           if (write)
             proc->get_state()->tohost = new_val;
           break;
-        case CSR_FROMHOST & 0x1f:
+        case CSR_FROMHOST:
           old_val = proc->get_state()->fromhost;
           if (write && old_val == 0)
-            proc->set_fromhost(new_val);
+            proc->get_state()->fromhost = new_val;
           break;
-        case CSR_RESET & 0x1f:
+        case CSR_RESET:
           old_val = !proc->running();
           if (write)
           {
index 71ab2923e7b5015a8aec2741c8516d5cf1c13652..4263eada244bb6f2f43f88df926600ece25a3dca 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(insn.i_imm() + RS1));
index f2d98d94c75ee89d26d249d29d88a3701efdbd96..706dc9c8f98b55be4bcc43d4bb7693d13bf738f5 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(RS1 + RS2));
index 532902ea94a2a2121ffc85e1fc23854cb3f8722f..c6bacaf57823908d3e13c0715ff78f6105a8e4a2 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, RS2 + v);
 WRITE_RD(v);
index 8a672ba56f52cf1770a378f1415989cf4b872102..d896ec1fc0056396c751333d57626f31670aa109 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, RS2 & v);
 WRITE_RD(v);
index 7b97e7b073e5e4296a3317d710b5c39128fed632..0a66214a4eade578c7c01f3dedcb568a76c2bc34 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 sreg_t v = MMU.load_int64(RS1);
 MMU.store_uint64(RS1, std::max(sreg_t(RS2),v));
 WRITE_RD(v);
index ef003c6e16f0f075b18dc245a92cf236d084a720..dbdb1d2f62a583191efd5b384852c8df2dd26473 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, std::max(RS2,v));
 WRITE_RD(v);
index 62915bb0df945b7c9cd42a8ba144b348b319201f..2ad8eef69e017d78c7a9cb4ae7ae4a6f26085275 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 sreg_t v = MMU.load_int64(RS1);
 MMU.store_uint64(RS1, std::min(sreg_t(RS2),v));
 WRITE_RD(v);
index 5543d5ed14b0245594190ed6597559e1c211e09a..88fe72461c019d1c5fc85d04adc9acaeac167a25 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, std::min(RS2,v));
 WRITE_RD(v);
index 500803f6876d590bbb7a2150a9e6f681464f9d96..58a64e082531a89bab89359a232d51af46904c42 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, RS2 | v);
 WRITE_RD(v);
index f03d2aabba95716c3d2bbde10d1a39dc3741e9ef..9f34eaa51e4245d54512caf04b115b2d35e0c329 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, RS2);
 WRITE_RD(v);
index c78e7e3939a1a169ee138e5e81f0800b820e0039..acd8b6140373839534a91a2a30e1f39e5d0ff7dc 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t v = MMU.load_uint64(RS1);
 MMU.store_uint64(RS1, RS2 ^ v);
 WRITE_RD(v);
index 4667fc889fc2e39e8adf30c261a0c7cd060335fe..74a687260cadd7a110810318996f2853ddb1aa7a 100644 (file)
@@ -1,4 +1,4 @@
 int csr = validate_csr(insn.csr(), true);
-reg_t old = p->get_pcr(csr);
-p->set_pcr(csr, old & ~RS1);
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, old & ~RS1);
 WRITE_RD(sext_xlen(old));
index 172aea0a05bcd07def93d544349ddfe9d13f899d..993f2d832ba8f6c0b2f42ea0698289ed2d764187 100644 (file)
@@ -1,4 +1,4 @@
 int csr = validate_csr(insn.csr(), true);
-reg_t old = p->get_pcr(csr);
-p->set_pcr(csr, old & ~(reg_t)insn.rs1());
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, old & ~(reg_t)insn.rs1());
 WRITE_RD(sext_xlen(old));
index 661685536f72627659fce52e536a1dcfd6eb044a..72b49bbe9d7d645e1c15f596c6fc0b79ff9531f1 100644 (file)
@@ -1,4 +1,4 @@
 int csr = validate_csr(insn.csr(), insn.rs1() != 0);
-reg_t old = p->get_pcr(csr);
-p->set_pcr(csr, old | RS1);
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, old | RS1);
 WRITE_RD(sext_xlen(old));
index 913c20a343ea317817eb32a220932e0c1029d1ea..90a44368b3344e67d13e36d1c3e8247cb204ea03 100644 (file)
@@ -1,4 +1,4 @@
 int csr = validate_csr(insn.csr(), true);
-reg_t old = p->get_pcr(csr);
-p->set_pcr(csr, old | insn.rs1());
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, old | insn.rs1());
 WRITE_RD(sext_xlen(old));
index b98166584b68decc869a9f7ed4ffbc624324b29a..9f2324ff6f3fc859ffb3ece63495af9e55ed914c 100644 (file)
@@ -1,4 +1,4 @@
 int csr = validate_csr(insn.csr(), true);
-reg_t old = p->get_pcr(csr);
-p->set_pcr(csr, RS1);
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, RS1);
 WRITE_RD(sext_xlen(old));
index cbee6b9de9e168d8d00602dc6d6b9aaf9377029b..cf0710f1d3742447cf3dc19e999da43075de2756 100644 (file)
@@ -1,4 +1,4 @@
 int csr = validate_csr(insn.csr(), true);
-reg_t old = p->get_pcr(csr);
-p->set_pcr(csr, insn.rs1());
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, insn.rs1());
 WRITE_RD(sext_xlen(old));
index a7176580ba5c90909f812bd15cbd5735a23f081e..a613d958fe190caded039fd6326cf468234e7834 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t lhs = zext32(RS1);
 reg_t rhs = zext32(RS2);
 if(rhs == 0)
index 24f22fdbebf191badc79f77af853414dd7f2e3bf..bd4e999f65dad1aa72dd91aa96b99e310991aed1 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 sreg_t lhs = sext32(RS1);
 sreg_t rhs = sext32(RS2);
 if(rhs == 0)
index eab849aceb51f4cb476dc79166195d5ace600c9d..e0e18245f3b62c2f30c09305d803d427c4e9fdc5 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_FRD(i64_to_f64(RS1));
index bef89ebd3ec4c2f96d3f6fda2763ee05af2352b3..ee338480d72bec372e1b070d19a527591b6959c4 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_FRD(ui64_to_f64(RS1));
index bf03b714b1883671458919bf7252edd6c88a0739..55dbe27d2b70e491585012098607e0a0d20cc82e 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_RD(f64_to_i64(FRS1, RM, true));
index 1259234ec4a48c15d48c6eae578aa6358ace6441..ea1e5a7084fdb2b0ba7618496f8979cc5feb0564 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_RD(f32_to_i64(FRS1, RM, true));
index d69b36b1e2e7f293b27c4a2686082c3ae289f9dd..7be12ed266f207f86e8fe446ba4819d3e8c5a204 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_RD(f64_to_ui64(FRS1, RM, true));
index e40605bd29c8b212c13ddff42b312a9f324eba7f..04501c196eff7999762af9ac1410644f1d3d55a4 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_RD(f32_to_ui64(FRS1, RM, true));
index 98570ab94ca8cc47ce31a59e67c5fddf86bedb79..723b9e42c5d1e50478457d606c5e966004435745 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_FRD(i64_to_f32(RS1));
index 921bfcfbb4ffb6c9698c1b066fb0ca65980bc721..b58b395757b79b580097b634b457969f63e9c341 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 require_fp;
 softfloat_roundingMode = RM;
 WRITE_FRD(ui64_to_f32(RS1));
index 35c1977c82610e38ef5a4184bbf76fda658c8ca9..f01811d3ab6f70d51f36da4ed6d0b447e7dcf4a0 100644 (file)
@@ -1,3 +1,3 @@
-require_xpr64;
+require_rv64;
 require_fp;
 WRITE_FRD(RS1);
index 5bcf2b5909ccf79795e89c7f16a97e980007a40b..d3c1d7aab83c1a18ce35a59cfa47f5e1eb8f6f95 100644 (file)
@@ -1,3 +1,3 @@
-require_xpr64;
+require_rv64;
 require_fp;
 WRITE_RD(FRS1);
index d36e172e758d3d167edb69f2019b6b26f5e7fd5e..1122b9807b3b273bb008972d35d87de087cad128 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(MMU.load_int64(RS1 + insn.i_imm()));
index 4e8ac181d7d17c9246a2244dc007b2c10469f2d5..94c4bf732bad3d86775bfd8ec3cc1d958c25e6ee 100644 (file)
@@ -1,3 +1,3 @@
-require_xpr64;
+require_rv64;
 p->get_state()->load_reservation = RS1;
 WRITE_RD(MMU.load_int64(RS1));
index 5535baf15b9a41ad0d5c1733191a8ca11b6e66bd..dcc4d75bab8b4d0815fdb8468fd0505d4153f309 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(MMU.load_uint32(RS1 + insn.i_imm()));
diff --git a/riscv/insns/mcall.h b/riscv/insns/mcall.h
new file mode 100644 (file)
index 0000000..97f55f8
--- /dev/null
@@ -0,0 +1,2 @@
+require_privilege(PRV_S); // or PRV_H if implemented
+throw trap_mcall();
diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h
new file mode 100644 (file)
index 0000000..7319a8f
--- /dev/null
@@ -0,0 +1,3 @@
+require_privilege(PRV_M);
+p->pop_privilege_stack();
+set_pc(p->get_state()->mepc);
diff --git a/riscv/insns/mrts.h b/riscv/insns/mrts.h
new file mode 100644 (file)
index 0000000..34675b7
--- /dev/null
@@ -0,0 +1,6 @@
+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 8ae75209f5c3ff84e2ab37321ea7b4cff002a1a3..567e213a42026897c114d3eb2c9e03601c961e8b 100644 (file)
@@ -1,4 +1,4 @@
-if (xpr64)
+if (xlen == 64)
   WRITE_RD(mulh(RS1, RS2));
 else
   WRITE_RD(sext32((sext32(RS1) * sext32(RS2)) >> 32));
index 3168ade2145f506b0ac7ad10d4ed07523e6ee6ec..5eeb89c7645c3e7dee3ed3c82f77042107952ef6 100644 (file)
@@ -1,4 +1,4 @@
-if (xpr64)
+if (xlen == 64)
   WRITE_RD(mulhsu(RS1, RS2));
 else
   WRITE_RD(sext32((sext32(RS1) * reg_t((uint32_t)RS2)) >> 32));
index b03b870accd5fb6fc4099987d26272c3a2215428..ce6a21ed34c8a0f13e512fd40221cccf7f396b00 100644 (file)
@@ -1,4 +1,4 @@
-if (xpr64)
+if (xlen == 64)
   WRITE_RD(mulhu(RS1, RS2));
 else
   WRITE_RD(sext32(((uint64_t)(uint32_t)RS1 * (uint64_t)(uint32_t)RS2) >> 32));
index 9f74fcfd57f8e9848f96c8067484dee7f91580a6..184dd4126081a42802619258b413031aefa68ba5 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(RS1 * RS2));
index bec7059c1ebea7196027a02b9da31f50e5edc399..e4875167e7478985d70c2ab014f69ad5571c4a65 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 reg_t lhs = zext32(RS1);
 reg_t rhs = zext32(RS2);
 if(rhs == 0)
index b8f4597c29055ba43a557c32d83a0954f0c19b82..2bae1a864683a96b1988caa80a49419c79dda5e4 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 sreg_t lhs = sext32(RS1);
 sreg_t rhs = sext32(RS2);
 if(rhs == 0)
index 3b4824445c77a6a148fde9a231ba5d52852e8b3c..2108079ad1e6d1bda8ecd977777010c04fa12d24 100644 (file)
@@ -1,4 +1,4 @@
-require_xpr64;
+require_rv64;
 if (RS1 == p->get_state()->load_reservation)
 {
   MMU.store_uint64(RS1, RS2);
index b31b7e6dae2e010ef168294174da8bae01e1fc3c..306a160957cf12aa43eac75ee0444a4af6fdd842 100644 (file)
@@ -1 +1 @@
-throw trap_syscall();
+throw trap_scall();
index 9364d875bded2d0e951f029efb8cf2cb3cb9d52a..664deb2c95ae5d0ec40a99f1b66d86ea8526c036 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 MMU.store_uint64(RS1 + insn.s_imm(), RS2);
diff --git a/riscv/insns/sfence_vm.h b/riscv/insns/sfence_vm.h
new file mode 100644 (file)
index 0000000..35ff5dd
--- /dev/null
@@ -0,0 +1,2 @@
+require_privilege(PRV_S);
+MMU.flush_tlb();
index ff9c8c39bf9d6d3521c11e55bdcd240d1f8e98ad..72912768da04afb9cbb6470fd7f8e66a07e9fa13 100644 (file)
@@ -1,4 +1,4 @@
-if(xpr64)
+if (xlen == 64)
   WRITE_RD(RS1 << SHAMT);
 else
 {
index fdb51be695fb267cf9a17e41a8116e82581e5a89..c1fda656c25093edc5ee67b430dcf9665545ba2d 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(RS1 << SHAMT));
index 25e717af502038056ab50919f13107bc9f70cef7..affe894441be2778b253a7f2ef33e764fd759468 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(RS1 << (RS2 & 0x1F)));
index 7fdbdf33c8cbcf579c5544aca3b48ed5a5cfd7ce..69066efb4d4fad0c4845eb56ff4a06c7c8f07161 100644 (file)
@@ -1,4 +1,4 @@
-if(xpr64)
+if (xlen == 64)
   WRITE_RD(sreg_t(RS1) >> SHAMT);
 else
 {
index 242c97eb45ee2be48020896017ed0de6821b55ba..b344459bf423c61a8e04e823ba5052a79e482102 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(int32_t(RS1) >> SHAMT));
index 29640bfb2a6865eff0aa98d50425f2453f7dc563..ca9c0c76ce8e855cb6fd2cdec9087c84b8b26daf 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(int32_t(RS1) >> (RS2 & 0x1F)));
index 442b00b3545090e89af3fcd1e870a49bf3252ab0..34fdb0d3a2a541fa19f2123e80f66e44c68a88a7 100644 (file)
@@ -1,5 +1,3 @@
-require_supervisor;
-p->set_pcr(CSR_STATUS, ((p->get_state()->sr & ~(SR_S | SR_EI)) |
-                       ((p->get_state()->sr & SR_PS) ? SR_S : 0)) |
-                       ((p->get_state()->sr & SR_PEI) ? SR_EI : 0));
-set_pc(p->get_state()->epc);
+require_privilege(PRV_S);
+p->pop_privilege_stack();
+set_pc(p->get_state()->sepc);
index 9b1eb2194baf3831b85c04555285917892b2c2f1..0eb948b7454e48962d4234304ccb7e17a4aea684 100644 (file)
@@ -1,4 +1,4 @@
-if(xpr64)
+if (xlen == 64)
   WRITE_RD(RS1 >> (RS2 & 0x3F));
 else
   WRITE_RD(sext32((uint32_t)RS1 >> (RS2 & 0x1F)));
index fee136c5698f8d7016fc70a884c0a63b970b6c82..0cdc853b0483f68021ef101f607a7e71da7288c7 100644 (file)
@@ -1,4 +1,4 @@
-if(xpr64)
+if (xlen == 64)
   WRITE_RD(RS1 >> SHAMT);
 else
 {
index 0b6f9b833fcc71c3480cd8106b7b4379727f5c37..c657d3da8bbeb078318900619b4eda189086ed1a 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32((uint32_t)RS1 >> SHAMT));
index 21ca5028aa01afcfda686c05d416ee071c703f38..a8eb4519859382c5b0b3a9f93bb34a48b1edceef 100644 (file)
@@ -1,2 +1,2 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32((uint32_t)RS1 >> (RS2 & 0x1F)));
index dce982f9d01866588454bc97b1d1a9f298dc2a50..b4168efe824f608ff0ab3b841db92bd50f378bde 100644 (file)
@@ -1,3 +1,3 @@
-require_xpr64;
+require_rv64;
 WRITE_RD(sext32(RS1 - RS2));
 
index 27e9ee0a5c93e14b6cf03d56c699bd007d012532..2dd1cada56578705b706a36424c527f83468efd0 100644 (file)
@@ -132,11 +132,24 @@ reg_t sim_t::get_reg(const std::vector<std::string>& args)
   if(args.size() != 2)
     throw trap_illegal_instruction();
 
-  int p = atoi(args[0].c_str());
-  int r = std::find(xpr_name, xpr_name + NXPR, args[1]) - xpr_name;
-  if (r == NXPR)
-    r = atoi(args[1].c_str());
-  if(p >= (int)num_cores() || r >= NXPR)
+  char* ptr;
+  unsigned long p = strtoul(args[0].c_str(), &ptr, 10);
+  if (*ptr || p >= num_cores())
+    throw trap_illegal_instruction();
+
+  unsigned long r = std::find(xpr_name, xpr_name + NXPR, args[1]) - xpr_name;
+  if (r == NXPR) {
+    r = strtoul(args[1].c_str(), &ptr, 10);
+    if (*ptr) {
+      #define DECLARE_CSR(name, number) if (args[1] == #name) return procs[p]->get_csr(number);
+      if (0) ;
+      #include "encoding.h"
+      else r = NXPR;
+      #undef DECLARE_CSR
+    }
+  }
+
+  if (r >= NXPR)
     throw trap_illegal_instruction();
 
   return procs[p]->state.XPR[r];
index 2e5de5b624186513e587bce374948e5500a7d511..779383db1bcbba1701a2d978eb4eefca901c9cda 100644 (file)
@@ -34,10 +34,29 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch)
   reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
   reg_t expected_tag = addr >> PGSHIFT;
 
-  reg_t pte = walk(addr);
+  reg_t pte = 0;
+  reg_t mstatus = proc ? proc->state.mstatus : 0;
+  
+  bool vm_disabled = get_field(mstatus, MSTATUS_VM) == VM_MBARE;
+  bool mode_m = get_field(mstatus, MSTATUS_PRV) == PRV_M;
+  bool mode_s = get_field(mstatus, MSTATUS_PRV) == PRV_S;
+  bool mprv_m = get_field(mstatus, MSTATUS_MPRV) == PRV_M;
+  bool mprv_s = get_field(mstatus, MSTATUS_MPRV) == PRV_S;
+
+  if (vm_disabled || (mode_m && (mprv_m || fetch))) {
+    // virtual memory is disabled.  merely check legality of physical address.
+    if (addr < memsz) {
+      // produce a fake PTE for the TLB's benefit.
+      pte = PTE_V | PTE_UX | PTE_SX | ((addr >> PGSHIFT) << PGSHIFT);
+      if (vm_disabled || !(mode_m && !mprv_m))
+        pte |= PTE_UR | PTE_SR | PTE_UW | PTE_SW;
+    }
+  } else {
+    pte = walk(addr);
+  }
 
   reg_t pte_perm = pte & PTE_PERM;
-  if (proc == NULL || (proc->state.sr & SR_S))
+  if (mode_s || (mode_m && mprv_s && !fetch))
     pte_perm = (pte_perm/(PTE_SX/PTE_UX)) & PTE_PERM;
   pte_perm |= pte & PTE_V;
 
@@ -70,53 +89,42 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch)
 
 pte_t mmu_t::walk(reg_t addr)
 {
-  pte_t pte = 0;
-
-  // the address must be a canonical sign-extended VA_BITS-bit number
-  int shift = 8*sizeof(reg_t) - VA_BITS;
-  if (((sreg_t)addr << shift >> shift) != (sreg_t)addr)
-    ;
-  else if (proc == NULL || !(proc->state.sr & SR_VM))
-  {
-    if(addr < memsz)
-      pte = PTE_V | PTE_PERM | ((addr >> PGSHIFT) << PGSHIFT);
-  }
-  else
-  {
-    reg_t base = proc->get_state()->ptbr;
-    reg_t ptd;
-
-    int ptshift = (LEVELS-1)*PTIDXBITS;
-    for(reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS)
-    {
-      reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1);
-
-      reg_t pte_addr = base + idx*sizeof(pte_t);
-      if(pte_addr >= memsz)
-        break;
-
-      ptd = *(pte_t*)(mem+pte_addr);
-
-      if (!(ptd & PTE_V)) // invalid mapping
-        break;
-      else if (ptd & PTE_T) // next level of page table
-        base = (ptd >> PGSHIFT) << PGSHIFT;
-      else // the actual PTE
-      {
-        // if this PTE is from a larger PT, fake a leaf
-        // PTE so the TLB will work right
-        reg_t vpn = addr >> PGSHIFT;
-        ptd |= (vpn & ((1<<(ptshift))-1)) << PGSHIFT;
-
-        // fault if physical addr is out of range
-        if (((ptd >> PGSHIFT) << PGSHIFT) < memsz)
-          pte = ptd;
-        break;
-      }
+  reg_t msb_mask = -(reg_t(1) << (VA_BITS-1));
+  if ((addr & msb_mask) != 0 && (addr & msb_mask) != msb_mask)
+    return 0; // address isn't properly sign-extended
+
+  reg_t base = proc->get_state()->sptbr;
+  reg_t ptd;
+
+  int ptshift = (LEVELS-1)*PTIDXBITS;
+  for (reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) {
+    reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1);
+
+    // check that physical address of PTE is legal
+    reg_t pte_addr = base + idx*sizeof(pte_t);
+    if (pte_addr >= memsz)
+      return 0;
+
+    ptd = *(pte_t*)(mem+pte_addr);
+
+    if (!(ptd & PTE_V)) { // invalid mapping
+      return 0;
+    } else if (ptd & PTE_T) { // next level of page table
+      base = (ptd >> PGSHIFT) << PGSHIFT;
+    } else {
+      // we've found the PTE.
+      // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
+      reg_t vpn = addr >> PGSHIFT;
+      ptd |= (vpn & ((1<<(ptshift))-1)) << PGSHIFT;
+
+      // check that physical address is legal
+      if (((ptd >> PGSHIFT) << PGSHIFT) >= memsz)
+        return 0;
+
+      return ptd;
     }
   }
-
-  return pte;
+  return 0;
 }
 
 void mmu_t::register_memtracer(memtracer_t* t)
index 0a344465df6b39ddf981e22b8c28f3ea4f67eeb2..335cbeab68f685b0bf2167a1be1a2ea639c7fa10 100644 (file)
@@ -49,31 +49,15 @@ processor_t::~processor_t()
 
 void state_t::reset()
 {
-  // the ISA guarantees on boot that the PC is 0x2000 and the the processor
-  // is in supervisor mode, and in 64-bit mode, if supported, with traps
-  // and virtual memory disabled.
-  sr = SR_S | SR_S64 | SR_U64;
-  pc = 0x2000;
-
-  // the following state is undefined upon boot-up,
-  // but we zero it for determinism
-  XPR.reset();
-  FPR.reset();
-
-  epc = 0;
-  badvaddr = 0;
-  evec = 0;
-  ptbr = 0;
-  pcr_k0 = 0;
-  pcr_k1 = 0;
-  cause = 0;
-  tohost = 0;
-  fromhost = 0;
-  count = 0;
-  compare = 0;
-  fflags = 0;
-  frm = 0;
-
+  memset(this, 0, sizeof(*this));
+  mstatus = set_field(mstatus, MSTATUS_PRV, PRV_M);
+  mstatus = set_field(mstatus, MSTATUS_PRV1, PRV_S);
+  mstatus = set_field(mstatus, MSTATUS_PRV2, PRV_S);
+#ifdef RISCV_ENABLE_64BIT
+  mstatus = set_field(mstatus, MSTATUS64_UA, UA_RV64);
+  mstatus = set_field(mstatus, MSTATUS64_SA, UA_RV64);
+#endif
+  pc = 0x100;
   load_reservation = -1;
 }
 
@@ -96,7 +80,7 @@ void processor_t::reset(bool value)
   run = !value;
 
   state.reset(); // reset the core
-  set_pcr(CSR_STATUS, state.sr);
+  set_csr(CSR_MSTATUS, state.mstatus);
 
   if (ext)
     ext->reset(); // reset the extension
@@ -112,21 +96,37 @@ void processor_t::serialize()
     serialized = true, throw serialize_t();
 }
 
+void processor_t::raise_interrupt(reg_t which)
+{
+  throw trap_t(((reg_t)1 << 63) | which);
+}
+
 void processor_t::take_interrupt()
 {
-  int irqs = ((state.sr & SR_IP) >> SR_IP_SHIFT) & (state.sr >> SR_IM_SHIFT);
-  if (likely(!irqs) || likely(!(state.sr & SR_EI)))
-    return;
+  int priv = get_field(state.mstatus, MSTATUS_PRV);
+  int ie = get_field(state.mstatus, MSTATUS_IE);
+
+  if (priv < PRV_M || (priv == PRV_M && ie)) {
+    if (get_field(state.mstatus, MSTATUS_MSIP))
+      raise_interrupt(IRQ_IPI);
+
+    if (state.fromhost != 0)
+      raise_interrupt(IRQ_HOST);
+  }
+
+  if (priv < PRV_S || (priv == PRV_S && ie)) {
+    if (get_field(state.mstatus, MSTATUS_SSIP))
+      raise_interrupt(IRQ_IPI);
 
-  for (int i = 0; ; i++)
-    if ((irqs >> i) & 1)
-      throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i);
+    if (state.stip && get_field(state.mstatus, MSTATUS_STIE))
+      raise_interrupt(IRQ_TIMER);
+  }
 }
 
 static void commit_log(state_t* state, reg_t pc, insn_t insn)
 {
 #ifdef RISCV_ENABLE_COMMITLOG
-  if (state->sr & SR_EI) {
+  if (get_field(state->mstatus, MSTATUS_IE)) {
     uint64_t mask = (insn.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn.length() * 8))) - 1;
     if (state->log_reg_write.addr) {
       fprintf(stderr, "0x%016" PRIx64 " (0x%08" PRIx64 ") %c%2" PRIu64 " 0x%016" PRIx64 "\n",
@@ -161,16 +161,16 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
 
 static void update_timer(state_t* state, size_t instret)
 {
-  uint64_t count0 = (uint64_t)(uint32_t)state->count;
-  state->count += instret;
-  uint64_t before = count0 - state->compare;
+  uint64_t count0 = (uint64_t)(uint32_t)state->scount;
+  state->scount += instret;
+  uint64_t before = count0 - state->stimecmp;
   if (int64_t(before ^ (before + instret)) < 0)
-    state->sr |= (1 << (IRQ_TIMER + SR_IP_SHIFT));
+    state->stip = true;
 }
 
 static size_t next_timer(state_t* state)
 {
-  return state->compare - (uint32_t)state->count;
+  return state->stimecmp - (uint32_t)state->scount;
 }
 
 void processor_t::step(size_t n)
@@ -225,28 +225,49 @@ void processor_t::step(size_t n)
   update_timer(&state, instret);
 }
 
+void processor_t::push_privilege_stack()
+{
+  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, PRV_M);
+  s = set_field(s, MSTATUS_IE, 0);
+  set_csr(CSR_MSTATUS, s);
+}
+
+void processor_t::pop_privilege_stack()
+{
+  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);
+}
+
 reg_t processor_t::take_trap(trap_t& t, reg_t epc)
 {
   if (debug)
     fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
             id, t.name(), epc);
 
-  // switch to supervisor, set previous supervisor bit, disable interrupts
-  set_pcr(CSR_STATUS, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
-                      ((state.sr & SR_S) ? SR_PS : 0) |
-                      ((state.sr & SR_EI) ? SR_PEI : 0));
-
+  reg_t tvec = 0x40 * get_field(state.mstatus, MSTATUS_PRV);
+  push_privilege_stack();
   yield_load_reservation();
-  state.cause = t.cause();
-  state.epc = epc;
+  state.mcause = t.cause();
+  state.mepc = epc;
   t.side_effects(&state); // might set badvaddr etc.
-  return state.evec;
+  return tvec;
 }
 
 void processor_t::deliver_ipi()
 {
-  if (run)
-    set_pcr(CSR_CLEAR_IPI, 1);
+  state.mstatus |= MSTATUS_MSIP;
 }
 
 void processor_t::disasm(insn_t insn)
@@ -256,83 +277,137 @@ void processor_t::disasm(insn_t insn)
           id, state.pc, bits, disassembler->disassemble(insn).c_str());
 }
 
-void processor_t::set_pcr(int which, reg_t val)
+static bool validate_priv(reg_t priv)
+{
+  return priv == PRV_U || priv == PRV_S || priv == PRV_M;
+}
+
+static bool validate_arch(reg_t arch)
+{
+#ifdef RISCV_ENABLE_64BIT
+  if (arch == UA_RV64) return true;
+#endif
+  return arch == UA_RV32;
+}
+
+static bool validate_vm(reg_t vm)
+{
+  // TODO: VM_SV32 support
+#ifdef RISCV_ENABLE_64BIT
+  if (vm == VM_SV43) return true;
+#endif
+  return vm == VM_MBARE;
+}
+
+void processor_t::set_csr(int which, reg_t val)
 {
   switch (which)
   {
     case CSR_FFLAGS:
+      dirty_fp_state;
       state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT);
       break;
     case CSR_FRM:
+      dirty_fp_state;
       state.frm = val & (FSR_RD >> FSR_RD_SHIFT);
       break;
     case CSR_FCSR:
+      dirty_fp_state;
       state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT;
       state.frm = (val & FSR_RD) >> FSR_RD_SHIFT;
       break;
-    case CSR_STATUS:
-      state.sr = (val & ~SR_IP) | (state.sr & SR_IP);
-#ifndef RISCV_ENABLE_64BIT
-      state.sr &= ~(SR_S64 | SR_U64);
+    case CSR_SCYCLE:
+    case CSR_STIME:
+    case CSR_SINSTRET:
+      state.scount = val; break;
+    case CSR_SCYCLEH:
+    case CSR_STIMEH:
+    case CSR_SINSTRETH:
+      state.scount = (val << 32) | (uint32_t)state.scount;
+      break;
+    case CSR_MSTATUS:
+    {
+      if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_MPRV))
+        mmu->flush_tlb();
+
+      reg_t mask = MSTATUS_SSIP | MSTATUS_MSIP | MSTATUS_IE | MSTATUS_IE1
+                   | MSTATUS_IE2 | MSTATUS_IE3 | MSTATUS_STIE;
+#ifdef RISCV_ENABLE_FPU
+      mask |= MSTATUS_FS;
 #endif
-#ifndef RISCV_ENABLE_FPU
-      state.sr &= ~SR_EF;
+      if (ext)
+        mask |= MSTATUS_XS;
+      state.mstatus = (state.mstatus & ~mask) | (val & mask);
+
+      if (validate_vm(get_field(val, MSTATUS_VM)))
+        state.mstatus = (state.mstatus & ~MSTATUS_VM) | (val & MSTATUS_VM);
+      if (validate_priv(get_field(val, MSTATUS_MPRV)))
+        state.mstatus = (state.mstatus & ~MSTATUS_MPRV) | (val & MSTATUS_MPRV);
+      if (validate_priv(get_field(val, MSTATUS_PRV)))
+        state.mstatus = (state.mstatus & ~MSTATUS_PRV) | (val & MSTATUS_PRV);
+      if (validate_priv(get_field(val, MSTATUS_PRV1)))
+        state.mstatus = (state.mstatus & ~MSTATUS_PRV1) | (val & MSTATUS_PRV1);
+      if (validate_priv(get_field(val, MSTATUS_PRV2)))
+        state.mstatus = (state.mstatus & ~MSTATUS_PRV2) | (val & MSTATUS_PRV2);
+      if (validate_priv(get_field(val, MSTATUS_PRV3)))
+        state.mstatus = (state.mstatus & ~MSTATUS_PRV3) | (val & MSTATUS_PRV3);
+      xlen = 32;
+
+      bool dirty = (state.mstatus & MSTATUS_FS) == MSTATUS_FS;
+      dirty |= (state.mstatus & MSTATUS_XS) == MSTATUS_XS;
+#ifndef RISCV_ENABLE_64BIT
+      state.mstatus = set_field(state.mstatus, MSTATUS32_SD, dirty);
+#else
+      state.mstatus = set_field(state.mstatus, MSTATUS64_SD, dirty);
+
+      if (validate_arch(get_field(val, MSTATUS64_UA)))
+        state.mstatus = (state.mstatus & ~MSTATUS64_UA) | (val & MSTATUS64_UA);
+      if (validate_arch(get_field(val, MSTATUS64_SA)))
+        state.mstatus = (state.mstatus & ~MSTATUS64_SA) | (val & MSTATUS64_SA);
+      switch (get_field(state.mstatus, MSTATUS_PRV)) {
+        case PRV_U: if (get_field(state.mstatus, MSTATUS64_UA)) xlen = 64; break;
+        case PRV_S: if (get_field(state.mstatus, MSTATUS64_SA)) xlen = 64; break;
+        case PRV_M: xlen = 64; break;
+        default: abort();
+      }
 #endif
-      if (!ext)
-        state.sr &= ~SR_EA;
-      state.sr &= ~SR_ZERO;
-      rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64);
-      mmu->flush_tlb();
-      break;
-    case CSR_EPC:
-      state.epc = val;
-      break;
-    case CSR_EVEC:
-      state.evec = val & ~3;
-      break;
-    case CSR_COUNT:
-      state.count = val;
-      break;
-    case CSR_COUNTH:
-      state.count = (val << 32) | (uint32_t)state.count;
       break;
-    case CSR_COMPARE:
+    }
+    case CSR_SSTATUS:
+    {
+      reg_t ms = state.mstatus;
+      ms = set_field(ms, MSTATUS_SSIP, get_field(val, SSTATUS_SIP));
+      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, MSTATUS64_UA, get_field(val, SSTATUS_UA));
+      ms = set_field(ms, MSTATUS_STIE, get_field(val, SSTATUS_TIE));
+      ms = set_field(ms, MSTATUS_FS, get_field(val, SSTATUS_FS));
+      ms = set_field(ms, MSTATUS_XS, get_field(val, SSTATUS_XS));
+      return set_csr(CSR_MSTATUS, ms);
+    }
+    case CSR_SEPC: state.sepc = val; break;
+    case CSR_STVEC: state.stvec = val & ~3; break;
+    case CSR_STIMECMP:
       serialize();
-      set_interrupt(IRQ_TIMER, false);
-      state.compare = val;
-      break;
-    case CSR_PTBR:
-      state.ptbr = val & ~(PGSIZE-1);
-      break;
-    case CSR_SEND_IPI:
-      sim->send_ipi(val);
-      break;
-    case CSR_CLEAR_IPI:
-      set_interrupt(IRQ_IPI, val & 1);
-      break;
-    case CSR_SUP0:
-      state.pcr_k0 = val;
-      break;
-    case CSR_SUP1:
-      state.pcr_k1 = val;
+      state.stip = false;
+      state.stimecmp = val;
       break;
+    case CSR_SPTBR: state.sptbr = val & ~(PGSIZE-1); break;
+    case CSR_SSCRATCH: state.sscratch = val; break;
+    case CSR_MEPC: state.mepc = val; break;
+    case CSR_MSCRATCH: state.mscratch = val; break;
+    case CSR_MCAUSE: state.mcause = val; break;
+    case CSR_SEND_IPI: sim->send_ipi(val); break;
     case CSR_TOHOST:
       if (state.tohost == 0)
         state.tohost = val;
       break;
-    case CSR_FROMHOST:
-      set_fromhost(val);
-      break;
+    case CSR_FROMHOST: state.fromhost = val; break;
   }
 }
 
-void processor_t::set_fromhost(reg_t val)
-{
-  set_interrupt(IRQ_HOST, val != 0);
-  state.fromhost = val;
-}
-
-reg_t processor_t::get_pcr(int which)
+reg_t processor_t::get_csr(int which)
 {
   switch (which)
   {
@@ -345,56 +420,64 @@ reg_t processor_t::get_pcr(int which)
     case CSR_FCSR:
       require_fp;
       return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
-    case CSR_STATUS:
-      return state.sr;
-    case CSR_EPC:
-      return state.epc;
-    case CSR_BADVADDR:
-      return state.badvaddr;
-    case CSR_EVEC:
-      return state.evec;
     case CSR_CYCLE:
     case CSR_TIME:
     case CSR_INSTRET:
-    case CSR_COUNT:
+    case CSR_SCYCLE:
+    case CSR_STIME:
+    case CSR_SINSTRET:
       serialize();
-      return state.count;
+      return state.scount;
     case CSR_CYCLEH:
     case CSR_TIMEH:
     case CSR_INSTRETH:
-    case CSR_COUNTH:
-      if (rv64)
+    case CSR_SCYCLEH:
+    case CSR_STIMEH:
+    case CSR_SINSTRETH:
+      if (xlen == 64)
         break;
       serialize();
-      return state.count >> 32;
-    case CSR_COMPARE:
-      return state.compare;
-    case CSR_CAUSE:
-      return state.cause;
-    case CSR_PTBR:
-      return state.ptbr;
-    case CSR_SEND_IPI:
-    case CSR_CLEAR_IPI:
-      return 0;
-    case CSR_ASID:
-      return 0;
-    case CSR_FATC:
-      mmu->flush_tlb();
-      return 0;
-    case CSR_HARTID:
-      return id;
-    case CSR_IMPL:
-      return 1;
-    case CSR_SUP0:
-      return state.pcr_k0;
-    case CSR_SUP1:
-      return state.pcr_k1;
+      return state.scount >> 32;
+    case CSR_SSTATUS:
+    {
+      reg_t ss = 0;
+      ss = set_field(ss, SSTATUS_SIP, get_field(state.mstatus, MSTATUS_SSIP));
+      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_UA, get_field(state.mstatus, MSTATUS64_UA));
+      ss = set_field(ss, SSTATUS_TIE, get_field(state.mstatus, MSTATUS_STIE));
+      ss = set_field(ss, SSTATUS_TIP, state.stip);
+      ss = set_field(ss, SSTATUS_FS, get_field(state.mstatus, MSTATUS_FS));
+      ss = set_field(ss, SSTATUS_XS, get_field(state.mstatus, MSTATUS_XS));
+      if (get_field(state.mstatus, MSTATUS64_SD))
+        ss = set_field(ss, (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD), 1);
+      return ss;
+    }
+    case CSR_SEPC: return state.sepc;
+    case CSR_SBADADDR: return state.sbadaddr;
+    case CSR_STVEC: return state.stvec;
+    case CSR_STIMECMP: return state.stimecmp;
+    case CSR_SCAUSE:
+      if (xlen == 32 && (state.scause >> 63) != 0)
+        return state.scause | ((reg_t)1 << 31);
+      return state.scause;
+    case CSR_SPTBR: return state.sptbr;
+    case CSR_SASID: return 0;
+    case CSR_SSCRATCH: return state.sscratch;
+    case CSR_MSTATUS: return state.mstatus;
+    case CSR_MEPC: return state.mepc;
+    case CSR_MSCRATCH: return state.mscratch;
+    case CSR_MCAUSE: return state.mcause;
+    case CSR_MBADADDR: return state.mbadaddr;
     case CSR_TOHOST:
       sim->get_htif()->tick(); // not necessary, but faster
       return state.tohost;
     case CSR_FROMHOST:
       sim->get_htif()->tick(); // not necessary, but faster
       return state.fromhost;
+    case CSR_SEND_IPI: return 0;
+    case CSR_HARTID: return id;
     case CSR_UARCH0:
     case CSR_UARCH1:
     case CSR_UARCH2:
@@ -416,15 +499,6 @@ reg_t processor_t::get_pcr(int which)
   throw trap_illegal_instruction();
 }
 
-void processor_t::set_interrupt(int which, bool on)
-{
-  uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
-  if (on)
-    state.sr |= mask;
-  else
-    state.sr &= ~mask;
-}
-
 reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
 {
   throw trap_illegal_instruction();
@@ -438,7 +512,7 @@ insn_func_t processor_t::decode_insn(insn_t insn)
   while ((insn.bits() & desc->mask) != desc->match)
     desc++;
 
-  return rv64 ? desc->rv64 : desc->rv32;
+  return xlen == 64 ? desc->rv64 : desc->rv32;
 }
 
 void processor_t::register_insn(insn_desc_t desc)
index 4e5b1444af9823a85b18d0a9ef7953db585a9438..4189fea8615f68271ff120b6c2b15791a79f002a 100644 (file)
@@ -40,18 +40,22 @@ struct state_t
   regfile_t<freg_t, NFPR, false> FPR;
 
   // control and status registers
-  reg_t epc;
-  reg_t badvaddr;
-  reg_t evec;
-  reg_t ptbr;
-  reg_t pcr_k0;
-  reg_t pcr_k1;
-  reg_t cause;
+  reg_t mstatus;
+  reg_t mepc;
+  reg_t mbadaddr;
+  reg_t mscratch;
+  reg_t mcause;
+  reg_t sepc;
+  reg_t sbadaddr;
+  reg_t sscratch;
+  reg_t stvec;
+  reg_t sptbr;
+  reg_t scause;
   reg_t tohost;
   reg_t fromhost;
-  reg_t count;
-  uint32_t compare;
-  uint32_t sr; // only modify the status register using set_pcr()
+  reg_t scount;
+  bool stip;
+  uint32_t stimecmp;
   uint32_t fflags;
   uint32_t frm;
 
@@ -75,13 +79,14 @@ public:
   void step(size_t n); // run for n cycles
   void deliver_ipi(); // register an interprocessor interrupt
   bool running() { return run; }
-  void set_pcr(int which, reg_t val);
-  void set_fromhost(reg_t val);
-  void set_interrupt(int which, bool on);
-  reg_t get_pcr(int which);
+  void set_csr(int which, reg_t val);
+  void raise_interrupt(reg_t which);
+  reg_t get_csr(int which);
   mmu_t* get_mmu() { return mmu; }
   state_t* get_state() { return &state; }
   extension_t* get_extension() { return ext; }
+  void push_privilege_stack();
+  void pop_privilege_stack();
   void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
   void update_histogram(size_t pc);
 
@@ -95,10 +100,10 @@ private:
   disassembler_t* disassembler;
   state_t state;
   uint32_t id;
+  int xlen;
   bool run; // !reset
   bool debug;
   bool histogram_enabled;
-  bool rv64;
   bool serialized;
 
   std::vector<insn_desc_t> instructions;
index e51aee57bf0a4f91f3afe962210eaab0f8e6eea7..7988c011e20ce9d1b1b27f0b53ba0c9d2bf2e972 100644 (file)
@@ -5,7 +5,6 @@
 #define customX(n) \
   static reg_t c##n(processor_t* p, insn_t insn, reg_t pc) \
   { \
-    require_accelerator; \
     rocc_t* rocc = static_cast<rocc_t*>(p->get_extension()); \
     rocc_insn_union_t u; \
     u.i = insn; \
index ead3a0047c6cdab0abe24121007da8791e3417f6..e1346e7c8d4fa1ea6c6966d5a9b03fca32e66e7b 100644 (file)
@@ -11,5 +11,5 @@ const char* trap_t::name()
 
 void mem_trap_t::side_effects(state_t* state)
 {
-  state->badvaddr = badvaddr;
+  state->mbadaddr = badvaddr;
 }
index 53df4f4033f0fc4e9d2efc17a404aea6e2760c12..711007371050113eefdfac7eeedd0538a6c028a8 100644 (file)
@@ -45,14 +45,12 @@ class mem_trap_t : public trap_t
 DECLARE_MEM_TRAP(CAUSE_MISALIGNED_FETCH, instruction_address_misaligned)
 DECLARE_MEM_TRAP(CAUSE_FAULT_FETCH, instruction_access_fault)
 DECLARE_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction)
-DECLARE_TRAP(CAUSE_PRIVILEGED_INSTRUCTION, privileged_instruction)
-DECLARE_TRAP(CAUSE_FP_DISABLED, fp_disabled)
-DECLARE_TRAP(CAUSE_SYSCALL, syscall)
+DECLARE_TRAP(CAUSE_SCALL, scall)
+DECLARE_TRAP(CAUSE_MCALL, mcall)
 DECLARE_TRAP(CAUSE_BREAKPOINT, breakpoint)
 DECLARE_MEM_TRAP(CAUSE_MISALIGNED_LOAD, load_address_misaligned)
 DECLARE_MEM_TRAP(CAUSE_MISALIGNED_STORE, store_address_misaligned)
 DECLARE_MEM_TRAP(CAUSE_FAULT_LOAD, load_access_fault)
 DECLARE_MEM_TRAP(CAUSE_FAULT_STORE, store_access_fault)
-DECLARE_TRAP(CAUSE_ACCELERATOR_DISABLED, accelerator_disabled)
 
 #endif