aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-04-03 21:53:22 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-04-03 21:53:22 -0700
commitc4350ef6ef6259e48509e125fd2d051969dc6efa (patch)
tree7f6b0900717eea640d687fc677d2cd39c97a9dd2 /riscv
parentd9d73d80c1b738b3b30eb40d192f61cbdb0e201f (diff)
downloadspike-c4350ef6ef6259e48509e125fd2d051969dc6efa.zip
spike-c4350ef6ef6259e48509e125fd2d051969dc6efa.tar.gz
spike-c4350ef6ef6259e48509e125fd2d051969dc6efa.tar.bz2
Support setting ISA/subsets with --isa flag
Default is RV64IMAFDC. Can do things like --isa=RV32 (which implies IMAFDC) --isa=IM (which implies RV64) --isa=RV64IMAFDXhwacha
Diffstat (limited to 'riscv')
-rw-r--r--riscv/decode.h17
-rw-r--r--riscv/encoding.h10
-rw-r--r--riscv/extensions.cc35
-rw-r--r--riscv/insns/amoadd_d.h1
-rw-r--r--riscv/insns/amoadd_w.h1
-rw-r--r--riscv/insns/amoand_d.h1
-rw-r--r--riscv/insns/amoand_w.h1
-rw-r--r--riscv/insns/amomax_d.h1
-rw-r--r--riscv/insns/amomax_w.h1
-rw-r--r--riscv/insns/amomaxu_d.h1
-rw-r--r--riscv/insns/amomaxu_w.h1
-rw-r--r--riscv/insns/amomin_d.h1
-rw-r--r--riscv/insns/amomin_w.h1
-rw-r--r--riscv/insns/amominu_d.h1
-rw-r--r--riscv/insns/amominu_w.h1
-rw-r--r--riscv/insns/amoor_d.h1
-rw-r--r--riscv/insns/amoor_w.h1
-rw-r--r--riscv/insns/amoswap_d.h1
-rw-r--r--riscv/insns/amoswap_w.h1
-rw-r--r--riscv/insns/amoxor_d.h1
-rw-r--r--riscv/insns/amoxor_w.h1
-rw-r--r--riscv/insns/c_add.h2
-rw-r--r--riscv/insns/c_addi.h2
-rw-r--r--riscv/insns/c_addi4.h2
-rw-r--r--riscv/insns/c_addiw.h2
-rw-r--r--riscv/insns/c_addw.h2
-rw-r--r--riscv/insns/c_beqz.h2
-rw-r--r--riscv/insns/c_bnez.h2
-rw-r--r--riscv/insns/c_j.h2
-rw-r--r--riscv/insns/c_jalr.h2
-rw-r--r--riscv/insns/c_ld.h2
-rw-r--r--riscv/insns/c_ldsp.h2
-rw-r--r--riscv/insns/c_li.h2
-rw-r--r--riscv/insns/c_lui.h2
-rw-r--r--riscv/insns/c_lw.h2
-rw-r--r--riscv/insns/c_lwsp.h2
-rw-r--r--riscv/insns/c_mv.h2
-rw-r--r--riscv/insns/c_sd.h2
-rw-r--r--riscv/insns/c_sdsp.h2
-rw-r--r--riscv/insns/c_slli.h2
-rw-r--r--riscv/insns/c_sw.h2
-rw-r--r--riscv/insns/c_swsp.h2
-rw-r--r--riscv/insns/div.h1
-rw-r--r--riscv/insns/divu.h1
-rw-r--r--riscv/insns/divuw.h1
-rw-r--r--riscv/insns/divw.h1
-rw-r--r--riscv/insns/fadd_d.h1
-rw-r--r--riscv/insns/fadd_h.h0
-rw-r--r--riscv/insns/fadd_s.h1
-rw-r--r--riscv/insns/fclass_d.h1
-rw-r--r--riscv/insns/fclass_s.h1
-rw-r--r--riscv/insns/fcvt_d_h.h0
-rw-r--r--riscv/insns/fcvt_d_l.h1
-rw-r--r--riscv/insns/fcvt_d_lu.h1
-rw-r--r--riscv/insns/fcvt_d_s.h1
-rw-r--r--riscv/insns/fcvt_d_w.h1
-rw-r--r--riscv/insns/fcvt_d_wu.h1
-rw-r--r--riscv/insns/fcvt_h_d.h0
-rw-r--r--riscv/insns/fcvt_h_l.h0
-rw-r--r--riscv/insns/fcvt_h_lu.h0
-rw-r--r--riscv/insns/fcvt_h_s.h0
-rw-r--r--riscv/insns/fcvt_h_w.h0
-rw-r--r--riscv/insns/fcvt_h_wu.h0
-rw-r--r--riscv/insns/fcvt_l_d.h1
-rw-r--r--riscv/insns/fcvt_l_h.h0
-rw-r--r--riscv/insns/fcvt_l_s.h1
-rw-r--r--riscv/insns/fcvt_lu_d.h1
-rw-r--r--riscv/insns/fcvt_lu_h.h0
-rw-r--r--riscv/insns/fcvt_lu_s.h1
-rw-r--r--riscv/insns/fcvt_s_d.h1
-rw-r--r--riscv/insns/fcvt_s_h.h0
-rw-r--r--riscv/insns/fcvt_s_l.h1
-rw-r--r--riscv/insns/fcvt_s_lu.h1
-rw-r--r--riscv/insns/fcvt_s_w.h1
-rw-r--r--riscv/insns/fcvt_s_wu.h1
-rw-r--r--riscv/insns/fcvt_w_d.h1
-rw-r--r--riscv/insns/fcvt_w_h.h0
-rw-r--r--riscv/insns/fcvt_w_s.h1
-rw-r--r--riscv/insns/fcvt_wu_d.h1
-rw-r--r--riscv/insns/fcvt_wu_h.h0
-rw-r--r--riscv/insns/fcvt_wu_s.h1
-rw-r--r--riscv/insns/fdiv_d.h1
-rw-r--r--riscv/insns/fdiv_h.h0
-rw-r--r--riscv/insns/fdiv_s.h1
-rw-r--r--riscv/insns/feq_d.h1
-rw-r--r--riscv/insns/feq_h.h0
-rw-r--r--riscv/insns/feq_s.h1
-rw-r--r--riscv/insns/fld.h1
-rw-r--r--riscv/insns/fle_d.h1
-rw-r--r--riscv/insns/fle_h.h0
-rw-r--r--riscv/insns/fle_s.h1
-rw-r--r--riscv/insns/flh.h0
-rw-r--r--riscv/insns/flt_d.h1
-rw-r--r--riscv/insns/flt_h.h0
-rw-r--r--riscv/insns/flt_s.h1
-rw-r--r--riscv/insns/flw.h1
-rw-r--r--riscv/insns/fmadd_d.h1
-rw-r--r--riscv/insns/fmadd_h.h0
-rw-r--r--riscv/insns/fmadd_s.h1
-rw-r--r--riscv/insns/fmax_d.h1
-rw-r--r--riscv/insns/fmax_h.h0
-rw-r--r--riscv/insns/fmax_s.h1
-rw-r--r--riscv/insns/fmin_d.h1
-rw-r--r--riscv/insns/fmin_h.h0
-rw-r--r--riscv/insns/fmin_s.h1
-rw-r--r--riscv/insns/fmsub_d.h1
-rw-r--r--riscv/insns/fmsub_h.h0
-rw-r--r--riscv/insns/fmsub_s.h1
-rw-r--r--riscv/insns/fmul_d.h1
-rw-r--r--riscv/insns/fmul_h.h0
-rw-r--r--riscv/insns/fmul_s.h1
-rw-r--r--riscv/insns/fmv_d_x.h1
-rw-r--r--riscv/insns/fmv_h_x.h0
-rw-r--r--riscv/insns/fmv_s_x.h1
-rw-r--r--riscv/insns/fmv_x_d.h1
-rw-r--r--riscv/insns/fmv_x_h.h0
-rw-r--r--riscv/insns/fmv_x_s.h1
-rw-r--r--riscv/insns/fnmadd_d.h1
-rw-r--r--riscv/insns/fnmadd_h.h0
-rw-r--r--riscv/insns/fnmadd_s.h1
-rw-r--r--riscv/insns/fnmsub_d.h1
-rw-r--r--riscv/insns/fnmsub_h.h0
-rw-r--r--riscv/insns/fnmsub_s.h1
-rw-r--r--riscv/insns/fsd.h1
-rw-r--r--riscv/insns/fsgnj_d.h1
-rw-r--r--riscv/insns/fsgnj_h.h0
-rw-r--r--riscv/insns/fsgnj_s.h1
-rw-r--r--riscv/insns/fsgnjn_d.h1
-rw-r--r--riscv/insns/fsgnjn_h.h0
-rw-r--r--riscv/insns/fsgnjn_s.h1
-rw-r--r--riscv/insns/fsgnjx_d.h1
-rw-r--r--riscv/insns/fsgnjx_h.h0
-rw-r--r--riscv/insns/fsgnjx_s.h1
-rw-r--r--riscv/insns/fsh.h0
-rw-r--r--riscv/insns/fsqrt_d.h1
-rw-r--r--riscv/insns/fsqrt_h.h0
-rw-r--r--riscv/insns/fsqrt_s.h1
-rw-r--r--riscv/insns/fsub_d.h1
-rw-r--r--riscv/insns/fsub_h.h0
-rw-r--r--riscv/insns/fsub_s.h1
-rw-r--r--riscv/insns/fsw.h1
-rw-r--r--riscv/insns/lr_d.h1
-rw-r--r--riscv/insns/lr_w.h1
-rw-r--r--riscv/insns/mul.h1
-rw-r--r--riscv/insns/mulh.h1
-rw-r--r--riscv/insns/mulhsu.h1
-rw-r--r--riscv/insns/mulhu.h1
-rw-r--r--riscv/insns/mulw.h1
-rw-r--r--riscv/insns/rem.h1
-rw-r--r--riscv/insns/remu.h1
-rw-r--r--riscv/insns/remuw.h1
-rw-r--r--riscv/insns/remw.h1
-rw-r--r--riscv/insns/sc_d.h1
-rw-r--r--riscv/insns/sc_w.h1
-rw-r--r--riscv/insns/sltiu.h2
-rw-r--r--riscv/mmu.cc23
-rw-r--r--riscv/mmu.h9
-rw-r--r--riscv/processor.cc122
-rw-r--r--riscv/processor.h6
-rw-r--r--riscv/riscv.ac19
-rw-r--r--riscv/riscv.mk.in3
-rw-r--r--riscv/sim.cc13
-rw-r--r--riscv/sim.h4
163 files changed, 282 insertions, 120 deletions
diff --git a/riscv/decode.h b/riscv/decode.h
index 55f03ff..4d4c447 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -45,14 +45,6 @@ const int NFPR = 32;
#define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT)
#define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
-#ifdef RISCV_ENABLE_RVC
-# define INSN_ALIGNMENT 2
-# define require_rvc
-#else
-# define INSN_ALIGNMENT 4
-# define require_rvc throw trap_illegal_instruction()
-#endif
-
#define insn_length(x) \
(((x) & 0x03) < 0x03 ? 2 : \
((x) & 0x1f) < 0x1f ? 4 : \
@@ -173,11 +165,8 @@ private:
#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()
-#ifdef RISCV_ENABLE_FPU
-# define require_fp if (unlikely((STATE.mstatus & MSTATUS_FS) == 0)) throw trap_illegal_instruction()
-#else
-# define require_fp throw trap_illegal_instruction()
-#endif
+#define require_extension(s) if (!p->supports_extension(s)) 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 set_fp_exceptions ({ STATE.fflags |= softfloat_exceptionFlags; \
@@ -189,7 +178,7 @@ private:
#define zext_xlen(x) (((reg_t)(x) << (64-xlen)) >> (64-xlen))
#define set_pc(x) \
- do { if ((x) & (INSN_ALIGNMENT-1)) \
+ do { if (unlikely(((x) & 2)) && !p->supports_extension('C')) \
throw trap_instruction_address_misaligned(x); \
npc = sext_xlen(x); \
} while(0)
diff --git a/riscv/encoding.h b/riscv/encoding.h
index 0c83ca2..8891ab3 100644
--- a/riscv/encoding.h
+++ b/riscv/encoding.h
@@ -48,7 +48,8 @@
#define VM_MBB 1
#define VM_MBBID 2
#define VM_SV32 4
-#define VM_SV43 5
+#define VM_SV39 5
+#define VM_SV48 6
#define UA_RV32 0
#define UA_RV64 4
@@ -69,7 +70,8 @@
#define PTE_R 0x040 // Referenced
#define PTE_D 0x080 // Dirty
#define PTE_SOFT 0x300 // Reserved for Software
-#define PTE_PPN_SHIFT 10
+#define RV64_PTE_PPN_SHIFT 26
+#define RV32_PTE_PPN_SHIFT 10
#define PTE_TYPE_INVALID 0
#define PTE_TYPE_TABLE 1
#define PTE_TYPE_U 2
@@ -105,13 +107,13 @@
# define MSTATUS_HA MSTATUS64_HA
# define MSTATUS_SD MSTATUS64_SD
# define SSTATUS_SD SSTATUS64_SD
-# define RISCV_PGLEVELS 3 /* Sv39 */
# define RISCV_PGLEVEL_BITS 9
+# define PTE_PPN_SHIFT RV64_PTE_PPN_SHIFT
#else
# define MSTATUS_SD MSTATUS32_SD
# define SSTATUS_SD SSTATUS32_SD
-# define RISCV_PGLEVELS 2 /* Sv32 */
# define RISCV_PGLEVEL_BITS 10
+# define PTE_PPN_SHIFT RV32_PTE_PPN_SHIFT
#endif
#define RISCV_PGSHIFT 12
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
diff --git a/riscv/extensions.cc b/riscv/extensions.cc
new file mode 100644
index 0000000..315621f
--- /dev/null
+++ b/riscv/extensions.cc
@@ -0,0 +1,35 @@
+#include "extension.h"
+#include <string>
+#include <map>
+#include <dlfcn.h>
+
+static std::map<std::string, std::function<extension_t*()>>& extensions()
+{
+ static std::map<std::string, std::function<extension_t*()>> v;
+ return v;
+}
+
+void register_extension(const char* name, std::function<extension_t*()> f)
+{
+ extensions()[name] = f;
+}
+
+std::function<extension_t*()> find_extension(const char* name)
+{
+ if (!extensions().count(name)) {
+ // try to find extension xyz by loading libxyz.so
+ std::string libname = std::string("lib") + name + ".so";
+ if (!dlopen(libname.c_str(), RTLD_LAZY)) {
+ fprintf(stderr, "couldn't find extension '%s' (or library '%s')\n",
+ name, libname.c_str());
+ exit(-1);
+ }
+ if (!extensions().count(name)) {
+ fprintf(stderr, "couldn't find extension '%s' in shared library '%s'\n",
+ name, libname.c_str());
+ exit(-1);
+ }
+ }
+
+ return extensions()[name];
+}
diff --git a/riscv/insns/amoadd_d.h b/riscv/insns/amoadd_d.h
index c6bacaf..9c7c124 100644
--- a/riscv/insns/amoadd_d.h
+++ b/riscv/insns/amoadd_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, RS2 + v);
diff --git a/riscv/insns/amoadd_w.h b/riscv/insns/amoadd_w.h
index 8eb9e2b..7ac59b0 100644
--- a/riscv/insns/amoadd_w.h
+++ b/riscv/insns/amoadd_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
reg_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, RS2 + v);
WRITE_RD(v);
diff --git a/riscv/insns/amoand_d.h b/riscv/insns/amoand_d.h
index d896ec1..7aa6386 100644
--- a/riscv/insns/amoand_d.h
+++ b/riscv/insns/amoand_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, RS2 & v);
diff --git a/riscv/insns/amoand_w.h b/riscv/insns/amoand_w.h
index 32ea7f7..7db2160 100644
--- a/riscv/insns/amoand_w.h
+++ b/riscv/insns/amoand_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
reg_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, RS2 & v);
WRITE_RD(v);
diff --git a/riscv/insns/amomax_d.h b/riscv/insns/amomax_d.h
index 0a66214..0f6da18 100644
--- a/riscv/insns/amomax_d.h
+++ b/riscv/insns/amomax_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
sreg_t v = MMU.load_int64(RS1);
MMU.store_uint64(RS1, std::max(sreg_t(RS2),v));
diff --git a/riscv/insns/amomax_w.h b/riscv/insns/amomax_w.h
index a255116..8c9222b 100644
--- a/riscv/insns/amomax_w.h
+++ b/riscv/insns/amomax_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
int32_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, std::max(int32_t(RS2),v));
WRITE_RD(v);
diff --git a/riscv/insns/amomaxu_d.h b/riscv/insns/amomaxu_d.h
index dbdb1d2..6760f91 100644
--- a/riscv/insns/amomaxu_d.h
+++ b/riscv/insns/amomaxu_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, std::max(RS2,v));
diff --git a/riscv/insns/amomaxu_w.h b/riscv/insns/amomaxu_w.h
index 448814b..fc83dc3 100644
--- a/riscv/insns/amomaxu_w.h
+++ b/riscv/insns/amomaxu_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
uint32_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, std::max(uint32_t(RS2),v));
WRITE_RD((int32_t)v);
diff --git a/riscv/insns/amomin_d.h b/riscv/insns/amomin_d.h
index 2ad8eef..8d08984 100644
--- a/riscv/insns/amomin_d.h
+++ b/riscv/insns/amomin_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
sreg_t v = MMU.load_int64(RS1);
MMU.store_uint64(RS1, std::min(sreg_t(RS2),v));
diff --git a/riscv/insns/amomin_w.h b/riscv/insns/amomin_w.h
index 28efa15..31a8df8 100644
--- a/riscv/insns/amomin_w.h
+++ b/riscv/insns/amomin_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
int32_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, std::min(int32_t(RS2),v));
WRITE_RD(v);
diff --git a/riscv/insns/amominu_d.h b/riscv/insns/amominu_d.h
index 88fe724..8a77edc 100644
--- a/riscv/insns/amominu_d.h
+++ b/riscv/insns/amominu_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, std::min(RS2,v));
diff --git a/riscv/insns/amominu_w.h b/riscv/insns/amominu_w.h
index 459b201..2b6aaa3 100644
--- a/riscv/insns/amominu_w.h
+++ b/riscv/insns/amominu_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
uint32_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, std::min(uint32_t(RS2),v));
WRITE_RD((int32_t)v);
diff --git a/riscv/insns/amoor_d.h b/riscv/insns/amoor_d.h
index 58a64e0..5a69717 100644
--- a/riscv/insns/amoor_d.h
+++ b/riscv/insns/amoor_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, RS2 | v);
diff --git a/riscv/insns/amoor_w.h b/riscv/insns/amoor_w.h
index c178f9a..f5b96b9 100644
--- a/riscv/insns/amoor_w.h
+++ b/riscv/insns/amoor_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
reg_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, RS2 | v);
WRITE_RD(v);
diff --git a/riscv/insns/amoswap_d.h b/riscv/insns/amoswap_d.h
index 9f34eaa..8cf1411 100644
--- a/riscv/insns/amoswap_d.h
+++ b/riscv/insns/amoswap_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, RS2);
diff --git a/riscv/insns/amoswap_w.h b/riscv/insns/amoswap_w.h
index 148b5bc..0764d59 100644
--- a/riscv/insns/amoswap_w.h
+++ b/riscv/insns/amoswap_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
reg_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, RS2);
WRITE_RD(v);
diff --git a/riscv/insns/amoxor_d.h b/riscv/insns/amoxor_d.h
index acd8b61..3970822 100644
--- a/riscv/insns/amoxor_d.h
+++ b/riscv/insns/amoxor_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
reg_t v = MMU.load_uint64(RS1);
MMU.store_uint64(RS1, RS2 ^ v);
diff --git a/riscv/insns/amoxor_w.h b/riscv/insns/amoxor_w.h
index 3a87b6e..9889b64 100644
--- a/riscv/insns/amoxor_w.h
+++ b/riscv/insns/amoxor_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
reg_t v = MMU.load_int32(RS1);
MMU.store_uint32(RS1, RS2 ^ v);
WRITE_RD(v);
diff --git a/riscv/insns/c_add.h b/riscv/insns/c_add.h
index b2ba34f..c349fc0 100644
--- a/riscv/insns/c_add.h
+++ b/riscv/insns/c_add.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RD(sext_xlen(RVC_RS1 + RVC_RS2));
diff --git a/riscv/insns/c_addi.h b/riscv/insns/c_addi.h
index 762f5c2..ad278f1 100644
--- a/riscv/insns/c_addi.h
+++ b/riscv/insns/c_addi.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RD(sext_xlen(RVC_RS2 + insn.rvc_imm()));
diff --git a/riscv/insns/c_addi4.h b/riscv/insns/c_addi4.h
index 90f3d81..3c9b7b2 100644
--- a/riscv/insns/c_addi4.h
+++ b/riscv/insns/c_addi4.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RD(sext_xlen(RVC_RS2 + insn.rvc_lwsp_imm()));
diff --git a/riscv/insns/c_addiw.h b/riscv/insns/c_addiw.h
index 33f970c..1b81834 100644
--- a/riscv/insns/c_addiw.h
+++ b/riscv/insns/c_addiw.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
require_rv64;
WRITE_RD(sext32(RVC_RS2 + insn.rvc_imm()));
diff --git a/riscv/insns/c_addw.h b/riscv/insns/c_addw.h
index c474cda..fef554d 100644
--- a/riscv/insns/c_addw.h
+++ b/riscv/insns/c_addw.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
require_rv64;
WRITE_RD(sext32(RVC_RS1 + RVC_RS2));
diff --git a/riscv/insns/c_beqz.h b/riscv/insns/c_beqz.h
index 8fee5bc..35c1196 100644
--- a/riscv/insns/c_beqz.h
+++ b/riscv/insns/c_beqz.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
if (RVC_RS1S == 0)
set_pc(pc + insn.rvc_b_imm());
diff --git a/riscv/insns/c_bnez.h b/riscv/insns/c_bnez.h
index a1a5666..1e40ea7 100644
--- a/riscv/insns/c_bnez.h
+++ b/riscv/insns/c_bnez.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
if (RVC_RS1S != 0)
set_pc(pc + insn.rvc_b_imm());
diff --git a/riscv/insns/c_j.h b/riscv/insns/c_j.h
index f57022d..6d8939c 100644
--- a/riscv/insns/c_j.h
+++ b/riscv/insns/c_j.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
set_pc(pc + insn.rvc_j_imm());
diff --git a/riscv/insns/c_jalr.h b/riscv/insns/c_jalr.h
index 9fd7f5d..ef6edfc 100644
--- a/riscv/insns/c_jalr.h
+++ b/riscv/insns/c_jalr.h
@@ -1,4 +1,4 @@
-require_rvc;
+require_extension('C');
reg_t tmp = npc;
set_pc(RVC_RS1 & ~reg_t(1));
WRITE_RD(tmp);
diff --git a/riscv/insns/c_ld.h b/riscv/insns/c_ld.h
index 37b0ee2..df0f5c3 100644
--- a/riscv/insns/c_ld.h
+++ b/riscv/insns/c_ld.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
require_rv64;
WRITE_RVC_RDS(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h
index 0b8bcbe..42665cf 100644
--- a/riscv/insns/c_ldsp.h
+++ b/riscv/insns/c_ldsp.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
require_rv64;
WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
diff --git a/riscv/insns/c_li.h b/riscv/insns/c_li.h
index b53c958..06d7bf2 100644
--- a/riscv/insns/c_li.h
+++ b/riscv/insns/c_li.h
@@ -1,4 +1,4 @@
-require_rvc;
+require_extension('C');
if (insn.rvc_rd() == 0) {
if (insn.rvc_imm() == -32) // c.sbreak
throw trap_breakpoint();
diff --git a/riscv/insns/c_lui.h b/riscv/insns/c_lui.h
index abdb78e..4bd4f87 100644
--- a/riscv/insns/c_lui.h
+++ b/riscv/insns/c_lui.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RD(insn.rvc_imm() << 12);
diff --git a/riscv/insns/c_lw.h b/riscv/insns/c_lw.h
index 9c6f470..f2fc299 100644
--- a/riscv/insns/c_lw.h
+++ b/riscv/insns/c_lw.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RVC_RDS(MMU.load_int32(RVC_RS1S + insn.rvc_lw_imm()));
diff --git a/riscv/insns/c_lwsp.h b/riscv/insns/c_lwsp.h
index 8d9b9e3..ed4dcf3 100644
--- a/riscv/insns/c_lwsp.h
+++ b/riscv/insns/c_lwsp.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RD(MMU.load_int32(RVC_SP + insn.rvc_lwsp_imm()));
diff --git a/riscv/insns/c_mv.h b/riscv/insns/c_mv.h
index 6de6584..bc05cfe 100644
--- a/riscv/insns/c_mv.h
+++ b/riscv/insns/c_mv.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
WRITE_RD(RVC_RS1);
diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h
index 13de934..9262d04 100644
--- a/riscv/insns/c_sd.h
+++ b/riscv/insns/c_sd.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
require_rv64;
MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h
index 6028b0f..e8b5170 100644
--- a/riscv/insns/c_sdsp.h
+++ b/riscv/insns/c_sdsp.h
@@ -1,3 +1,3 @@
-require_rvc;
+require_extension('C');
require_rv64;
MMU.store_uint64(RVC_SP + insn.rvc_ldsp_imm(), RVC_RS2);
diff --git a/riscv/insns/c_slli.h b/riscv/insns/c_slli.h
index fb6dffd..de3683b 100644
--- a/riscv/insns/c_slli.h
+++ b/riscv/insns/c_slli.h
@@ -1,4 +1,4 @@
-require_rvc;
+require_extension('C');
if (insn.rvc_imm() >= xlen)
throw trap_illegal_instruction();
WRITE_RD(sext_xlen(RVC_RS2 << insn.rvc_imm()));
diff --git a/riscv/insns/c_sw.h b/riscv/insns/c_sw.h
index 34deb9d..3073e9d 100644
--- a/riscv/insns/c_sw.h
+++ b/riscv/insns/c_sw.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_RS2S);
diff --git a/riscv/insns/c_swsp.h b/riscv/insns/c_swsp.h
index bbb5ad0..6f3fef0 100644
--- a/riscv/insns/c_swsp.h
+++ b/riscv/insns/c_swsp.h
@@ -1,2 +1,2 @@
-require_rvc;
+require_extension('C');
MMU.store_uint32(RVC_SP + insn.rvc_lwsp_imm(), RVC_RS2);
diff --git a/riscv/insns/div.h b/riscv/insns/div.h
index 3ad613a..9cbe8d6 100644
--- a/riscv/insns/div.h
+++ b/riscv/insns/div.h
@@ -1,3 +1,4 @@
+require_extension('M');
sreg_t lhs = sext_xlen(RS1);
sreg_t rhs = sext_xlen(RS2);
if(rhs == 0)
diff --git a/riscv/insns/divu.h b/riscv/insns/divu.h
index 4887ce0..31d7585 100644
--- a/riscv/insns/divu.h
+++ b/riscv/insns/divu.h
@@ -1,3 +1,4 @@
+require_extension('M');
reg_t lhs = zext_xlen(RS1);
reg_t rhs = zext_xlen(RS2);
if(rhs == 0)
diff --git a/riscv/insns/divuw.h b/riscv/insns/divuw.h
index a613d95..e127619 100644
--- a/riscv/insns/divuw.h
+++ b/riscv/insns/divuw.h
@@ -1,3 +1,4 @@
+require_extension('M');
require_rv64;
reg_t lhs = zext32(RS1);
reg_t rhs = zext32(RS2);
diff --git a/riscv/insns/divw.h b/riscv/insns/divw.h
index bd4e999..11be17e 100644
--- a/riscv/insns/divw.h
+++ b/riscv/insns/divw.h
@@ -1,3 +1,4 @@
+require_extension('M');
require_rv64;
sreg_t lhs = sext32(RS1);
sreg_t rhs = sext32(RS2);
diff --git a/riscv/insns/fadd_d.h b/riscv/insns/fadd_d.h
index e06efb8..3e5963d 100644
--- a/riscv/insns/fadd_d.h
+++ b/riscv/insns/fadd_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1, 0x3ff0000000000000ULL, FRS2));
diff --git a/riscv/insns/fadd_h.h b/riscv/insns/fadd_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fadd_h.h
+++ /dev/null
diff --git a/riscv/insns/fadd_s.h b/riscv/insns/fadd_s.h
index c43135d..a35a524 100644
--- a/riscv/insns/fadd_s.h
+++ b/riscv/insns/fadd_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1, 0x3f800000, FRS2));
diff --git a/riscv/insns/fclass_d.h b/riscv/insns/fclass_d.h
index bd42d45..f4883ef 100644
--- a/riscv/insns/fclass_d.h
+++ b/riscv/insns/fclass_d.h
@@ -1,2 +1,3 @@
+require_extension('D');
require_fp;
WRITE_RD(f64_classify(FRS1));
diff --git a/riscv/insns/fclass_s.h b/riscv/insns/fclass_s.h
index a010266..a2d5b63 100644
--- a/riscv/insns/fclass_s.h
+++ b/riscv/insns/fclass_s.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_RD(f32_classify(FRS1));
diff --git a/riscv/insns/fcvt_d_h.h b/riscv/insns/fcvt_d_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_d_h.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_d_l.h b/riscv/insns/fcvt_d_l.h
index e0e1824..08716cf 100644
--- a/riscv/insns/fcvt_d_l.h
+++ b/riscv/insns/fcvt_d_l.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_d_lu.h b/riscv/insns/fcvt_d_lu.h
index ee33848..306d7fe 100644
--- a/riscv/insns/fcvt_d_lu.h
+++ b/riscv/insns/fcvt_d_lu.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_d_s.h b/riscv/insns/fcvt_d_s.h
index 0024330..177e77c 100644
--- a/riscv/insns/fcvt_d_s.h
+++ b/riscv/insns/fcvt_d_s.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_to_f64(FRS1));
diff --git a/riscv/insns/fcvt_d_w.h b/riscv/insns/fcvt_d_w.h
index ce56974..4c4861c 100644
--- a/riscv/insns/fcvt_d_w.h
+++ b/riscv/insns/fcvt_d_w.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(i32_to_f64((int32_t)RS1));
diff --git a/riscv/insns/fcvt_d_wu.h b/riscv/insns/fcvt_d_wu.h
index 4c56248..1dbf218 100644
--- a/riscv/insns/fcvt_d_wu.h
+++ b/riscv/insns/fcvt_d_wu.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(ui32_to_f64((uint32_t)RS1));
diff --git a/riscv/insns/fcvt_h_d.h b/riscv/insns/fcvt_h_d.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_h_d.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_h_l.h b/riscv/insns/fcvt_h_l.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_h_l.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_h_lu.h b/riscv/insns/fcvt_h_lu.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_h_lu.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_h_s.h b/riscv/insns/fcvt_h_s.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_h_s.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_h_w.h b/riscv/insns/fcvt_h_w.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_h_w.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_h_wu.h b/riscv/insns/fcvt_h_wu.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_h_wu.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_l_d.h b/riscv/insns/fcvt_l_d.h
index 55dbe27..ee323f3 100644
--- a/riscv/insns/fcvt_l_d.h
+++ b/riscv/insns/fcvt_l_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_l_h.h b/riscv/insns/fcvt_l_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_l_h.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_l_s.h b/riscv/insns/fcvt_l_s.h
index ea1e5a7..6079a69 100644
--- a/riscv/insns/fcvt_l_s.h
+++ b/riscv/insns/fcvt_l_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_lu_d.h b/riscv/insns/fcvt_lu_d.h
index 7be12ed..b6004ea 100644
--- a/riscv/insns/fcvt_lu_d.h
+++ b/riscv/insns/fcvt_lu_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_lu_h.h b/riscv/insns/fcvt_lu_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_lu_h.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_lu_s.h b/riscv/insns/fcvt_lu_s.h
index 04501c1..af8e1ab 100644
--- a/riscv/insns/fcvt_lu_s.h
+++ b/riscv/insns/fcvt_lu_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_s_d.h b/riscv/insns/fcvt_s_d.h
index 28a1d69..c1c9f0c 100644
--- a/riscv/insns/fcvt_s_d.h
+++ b/riscv/insns/fcvt_s_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_to_f32(FRS1));
diff --git a/riscv/insns/fcvt_s_h.h b/riscv/insns/fcvt_s_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_s_h.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_s_l.h b/riscv/insns/fcvt_s_l.h
index 723b9e4..9abcc80 100644
--- a/riscv/insns/fcvt_s_l.h
+++ b/riscv/insns/fcvt_s_l.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_s_lu.h b/riscv/insns/fcvt_s_lu.h
index b58b395..70c676e 100644
--- a/riscv/insns/fcvt_s_lu.h
+++ b/riscv/insns/fcvt_s_lu.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_rv64;
require_fp;
softfloat_roundingMode = RM;
diff --git a/riscv/insns/fcvt_s_w.h b/riscv/insns/fcvt_s_w.h
index 05445fa..1ddabd8 100644
--- a/riscv/insns/fcvt_s_w.h
+++ b/riscv/insns/fcvt_s_w.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(i32_to_f32((int32_t)RS1));
diff --git a/riscv/insns/fcvt_s_wu.h b/riscv/insns/fcvt_s_wu.h
index ca8d2b6..c1394c3 100644
--- a/riscv/insns/fcvt_s_wu.h
+++ b/riscv/insns/fcvt_s_wu.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(ui32_to_f32((uint32_t)RS1));
diff --git a/riscv/insns/fcvt_w_d.h b/riscv/insns/fcvt_w_d.h
index a5186b5..bac8a9b 100644
--- a/riscv/insns/fcvt_w_d.h
+++ b/riscv/insns/fcvt_w_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_RD(sext32(f64_to_i32(FRS1, RM, true)));
diff --git a/riscv/insns/fcvt_w_h.h b/riscv/insns/fcvt_w_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_w_h.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_w_s.h b/riscv/insns/fcvt_w_s.h
index 1d82deb..81bc89f 100644
--- a/riscv/insns/fcvt_w_s.h
+++ b/riscv/insns/fcvt_w_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_RD(sext32(f32_to_i32(FRS1, RM, true)));
diff --git a/riscv/insns/fcvt_wu_d.h b/riscv/insns/fcvt_wu_d.h
index 5cf44d1..353ae6d 100644
--- a/riscv/insns/fcvt_wu_d.h
+++ b/riscv/insns/fcvt_wu_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_RD(sext32(f64_to_ui32(FRS1, RM, true)));
diff --git a/riscv/insns/fcvt_wu_h.h b/riscv/insns/fcvt_wu_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fcvt_wu_h.h
+++ /dev/null
diff --git a/riscv/insns/fcvt_wu_s.h b/riscv/insns/fcvt_wu_s.h
index 5b4c444..2c1ff00 100644
--- a/riscv/insns/fcvt_wu_s.h
+++ b/riscv/insns/fcvt_wu_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_RD(sext32(f32_to_ui32(FRS1, RM, true)));
diff --git a/riscv/insns/fdiv_d.h b/riscv/insns/fdiv_d.h
index e215702..d52ac66 100644
--- a/riscv/insns/fdiv_d.h
+++ b/riscv/insns/fdiv_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_div(FRS1, FRS2));
diff --git a/riscv/insns/fdiv_h.h b/riscv/insns/fdiv_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fdiv_h.h
+++ /dev/null
diff --git a/riscv/insns/fdiv_s.h b/riscv/insns/fdiv_s.h
index 2644d08..cf54c57 100644
--- a/riscv/insns/fdiv_s.h
+++ b/riscv/insns/fdiv_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_div(FRS1, FRS2));
diff --git a/riscv/insns/feq_d.h b/riscv/insns/feq_d.h
index 516fb59..43d9c1c 100644
--- a/riscv/insns/feq_d.h
+++ b/riscv/insns/feq_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
WRITE_RD(f64_eq(FRS1, FRS2));
set_fp_exceptions;
diff --git a/riscv/insns/feq_h.h b/riscv/insns/feq_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/feq_h.h
+++ /dev/null
diff --git a/riscv/insns/feq_s.h b/riscv/insns/feq_s.h
index b44da24..7d42634 100644
--- a/riscv/insns/feq_s.h
+++ b/riscv/insns/feq_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
WRITE_RD(f32_eq(FRS1, FRS2));
set_fp_exceptions;
diff --git a/riscv/insns/fld.h b/riscv/insns/fld.h
index 1bc83cf..0b50b8a 100644
--- a/riscv/insns/fld.h
+++ b/riscv/insns/fld.h
@@ -1,2 +1,3 @@
+require_extension('D');
require_fp;
WRITE_FRD(MMU.load_int64(RS1 + insn.i_imm()));
diff --git a/riscv/insns/fle_d.h b/riscv/insns/fle_d.h
index 72dcc7e..7f6a84d 100644
--- a/riscv/insns/fle_d.h
+++ b/riscv/insns/fle_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
WRITE_RD(f64_le(FRS1, FRS2));
set_fp_exceptions;
diff --git a/riscv/insns/fle_h.h b/riscv/insns/fle_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fle_h.h
+++ /dev/null
diff --git a/riscv/insns/fle_s.h b/riscv/insns/fle_s.h
index 9c85b4a..0884c51 100644
--- a/riscv/insns/fle_s.h
+++ b/riscv/insns/fle_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
WRITE_RD(f32_le(FRS1, FRS2));
set_fp_exceptions;
diff --git a/riscv/insns/flh.h b/riscv/insns/flh.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/flh.h
+++ /dev/null
diff --git a/riscv/insns/flt_d.h b/riscv/insns/flt_d.h
index 335e4a8..9fda98d 100644
--- a/riscv/insns/flt_d.h
+++ b/riscv/insns/flt_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
WRITE_RD(f64_lt(FRS1, FRS2));
set_fp_exceptions;
diff --git a/riscv/insns/flt_h.h b/riscv/insns/flt_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/flt_h.h
+++ /dev/null
diff --git a/riscv/insns/flt_s.h b/riscv/insns/flt_s.h
index 7a21785..830b0a0 100644
--- a/riscv/insns/flt_s.h
+++ b/riscv/insns/flt_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
WRITE_RD(f32_lt(FRS1, FRS2));
set_fp_exceptions;
diff --git a/riscv/insns/flw.h b/riscv/insns/flw.h
index a5f7d16..b94ba5d 100644
--- a/riscv/insns/flw.h
+++ b/riscv/insns/flw.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_FRD(MMU.load_int32(RS1 + insn.i_imm()));
diff --git a/riscv/insns/fmadd_d.h b/riscv/insns/fmadd_d.h
index 8640e7f..8605e0b 100644
--- a/riscv/insns/fmadd_d.h
+++ b/riscv/insns/fmadd_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1, FRS2, FRS3));
diff --git a/riscv/insns/fmadd_h.h b/riscv/insns/fmadd_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmadd_h.h
+++ /dev/null
diff --git a/riscv/insns/fmadd_s.h b/riscv/insns/fmadd_s.h
index f8b0a5f..95196b7 100644
--- a/riscv/insns/fmadd_s.h
+++ b/riscv/insns/fmadd_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1, FRS2, FRS3));
diff --git a/riscv/insns/fmax_d.h b/riscv/insns/fmax_d.h
index a26aeab..eb156de 100644
--- a/riscv/insns/fmax_d.h
+++ b/riscv/insns/fmax_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
WRITE_FRD(isNaNF64UI(FRS2) || f64_le_quiet(FRS2,FRS1) /* && FRS1 not NaN */
? FRS1 : FRS2);
diff --git a/riscv/insns/fmax_h.h b/riscv/insns/fmax_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmax_h.h
+++ /dev/null
diff --git a/riscv/insns/fmax_s.h b/riscv/insns/fmax_s.h
index b16134b..215a6d1 100644
--- a/riscv/insns/fmax_s.h
+++ b/riscv/insns/fmax_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
WRITE_FRD(isNaNF32UI(FRS2) || f32_le_quiet(FRS2,FRS1) /* && FRS1 not NaN */
? FRS1 : FRS2);
diff --git a/riscv/insns/fmin_d.h b/riscv/insns/fmin_d.h
index c095ade..02ea681 100644
--- a/riscv/insns/fmin_d.h
+++ b/riscv/insns/fmin_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
WRITE_FRD(isNaNF64UI(FRS2) || f64_lt_quiet(FRS1,FRS2) /* && FRS1 not NaN */
? FRS1 : FRS2);
diff --git a/riscv/insns/fmin_h.h b/riscv/insns/fmin_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmin_h.h
+++ /dev/null
diff --git a/riscv/insns/fmin_s.h b/riscv/insns/fmin_s.h
index e2fdc5c..cc673a0 100644
--- a/riscv/insns/fmin_s.h
+++ b/riscv/insns/fmin_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
WRITE_FRD(isNaNF32UI(FRS2) || f32_lt_quiet(FRS1,FRS2) /* && FRS1 not NaN */
? FRS1 : FRS2);
diff --git a/riscv/insns/fmsub_d.h b/riscv/insns/fmsub_d.h
index 13e9fcc..696f822 100644
--- a/riscv/insns/fmsub_d.h
+++ b/riscv/insns/fmsub_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1, FRS2, FRS3 ^ (uint64_t)INT64_MIN));
diff --git a/riscv/insns/fmsub_h.h b/riscv/insns/fmsub_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmsub_h.h
+++ /dev/null
diff --git a/riscv/insns/fmsub_s.h b/riscv/insns/fmsub_s.h
index c6aa418..9251277 100644
--- a/riscv/insns/fmsub_s.h
+++ b/riscv/insns/fmsub_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1, FRS2, FRS3 ^ (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fmul_d.h b/riscv/insns/fmul_d.h
index e2ca1c2..d74c316 100644
--- a/riscv/insns/fmul_d.h
+++ b/riscv/insns/fmul_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1, FRS2, (FRS1 ^ FRS2) & (uint64_t)INT64_MIN));
diff --git a/riscv/insns/fmul_h.h b/riscv/insns/fmul_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmul_h.h
+++ /dev/null
diff --git a/riscv/insns/fmul_s.h b/riscv/insns/fmul_s.h
index f564803..284aeb3 100644
--- a/riscv/insns/fmul_s.h
+++ b/riscv/insns/fmul_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1, FRS2, (FRS1 ^ FRS2) & (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fmv_d_x.h b/riscv/insns/fmv_d_x.h
index f01811d..c3f6049 100644
--- a/riscv/insns/fmv_d_x.h
+++ b/riscv/insns/fmv_d_x.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_rv64;
require_fp;
WRITE_FRD(RS1);
diff --git a/riscv/insns/fmv_h_x.h b/riscv/insns/fmv_h_x.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmv_h_x.h
+++ /dev/null
diff --git a/riscv/insns/fmv_s_x.h b/riscv/insns/fmv_s_x.h
index f3eac82..f0f95ac 100644
--- a/riscv/insns/fmv_s_x.h
+++ b/riscv/insns/fmv_s_x.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_FRD(RS1);
diff --git a/riscv/insns/fmv_x_d.h b/riscv/insns/fmv_x_d.h
index d3c1d7a..b97d7f5 100644
--- a/riscv/insns/fmv_x_d.h
+++ b/riscv/insns/fmv_x_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_rv64;
require_fp;
WRITE_RD(FRS1);
diff --git a/riscv/insns/fmv_x_h.h b/riscv/insns/fmv_x_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fmv_x_h.h
+++ /dev/null
diff --git a/riscv/insns/fmv_x_s.h b/riscv/insns/fmv_x_s.h
index 46a9488..1bee87f 100644
--- a/riscv/insns/fmv_x_s.h
+++ b/riscv/insns/fmv_x_s.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_RD(sext32(FRS1));
diff --git a/riscv/insns/fnmadd_d.h b/riscv/insns/fnmadd_d.h
index 705470b..bed6172 100644
--- a/riscv/insns/fnmadd_d.h
+++ b/riscv/insns/fnmadd_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1 ^ (uint64_t)INT64_MIN, FRS2, FRS3 ^ (uint64_t)INT64_MIN));
diff --git a/riscv/insns/fnmadd_h.h b/riscv/insns/fnmadd_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fnmadd_h.h
+++ /dev/null
diff --git a/riscv/insns/fnmadd_s.h b/riscv/insns/fnmadd_s.h
index 2df321b..1378ae3 100644
--- a/riscv/insns/fnmadd_s.h
+++ b/riscv/insns/fnmadd_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1 ^ (uint32_t)INT32_MIN, FRS2, FRS3 ^ (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fnmsub_d.h b/riscv/insns/fnmsub_d.h
index c38d2bf..340090a 100644
--- a/riscv/insns/fnmsub_d.h
+++ b/riscv/insns/fnmsub_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1 ^ (uint64_t)INT64_MIN, FRS2, FRS3));
diff --git a/riscv/insns/fnmsub_h.h b/riscv/insns/fnmsub_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fnmsub_h.h
+++ /dev/null
diff --git a/riscv/insns/fnmsub_s.h b/riscv/insns/fnmsub_s.h
index c3fa995..3be27d0 100644
--- a/riscv/insns/fnmsub_s.h
+++ b/riscv/insns/fnmsub_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1 ^ (uint32_t)INT32_MIN, FRS2, FRS3));
diff --git a/riscv/insns/fsd.h b/riscv/insns/fsd.h
index fe90a6b..63cc8e5 100644
--- a/riscv/insns/fsd.h
+++ b/riscv/insns/fsd.h
@@ -1,2 +1,3 @@
+require_extension('D');
require_fp;
MMU.store_uint64(RS1 + insn.s_imm(), FRS2);
diff --git a/riscv/insns/fsgnj_d.h b/riscv/insns/fsgnj_d.h
index 74ef3f6..52648a1 100644
--- a/riscv/insns/fsgnj_d.h
+++ b/riscv/insns/fsgnj_d.h
@@ -1,2 +1,3 @@
+require_extension('D');
require_fp;
WRITE_FRD((FRS1 &~ INT64_MIN) | (FRS2 & INT64_MIN));
diff --git a/riscv/insns/fsgnj_h.h b/riscv/insns/fsgnj_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fsgnj_h.h
+++ /dev/null
diff --git a/riscv/insns/fsgnj_s.h b/riscv/insns/fsgnj_s.h
index 4f852b4..4c91ff3 100644
--- a/riscv/insns/fsgnj_s.h
+++ b/riscv/insns/fsgnj_s.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_FRD((FRS1 &~ (uint32_t)INT32_MIN) | (FRS2 & (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fsgnjn_d.h b/riscv/insns/fsgnjn_d.h
index e214f1d..cdec924 100644
--- a/riscv/insns/fsgnjn_d.h
+++ b/riscv/insns/fsgnjn_d.h
@@ -1,2 +1,3 @@
+require_extension('D');
require_fp;
WRITE_FRD((FRS1 &~ INT64_MIN) | ((~FRS2) & INT64_MIN));
diff --git a/riscv/insns/fsgnjn_h.h b/riscv/insns/fsgnjn_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fsgnjn_h.h
+++ /dev/null
diff --git a/riscv/insns/fsgnjn_s.h b/riscv/insns/fsgnjn_s.h
index b098150..f91a7b0 100644
--- a/riscv/insns/fsgnjn_s.h
+++ b/riscv/insns/fsgnjn_s.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_FRD((FRS1 &~ (uint32_t)INT32_MIN) | ((~FRS2) & (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fsgnjx_d.h b/riscv/insns/fsgnjx_d.h
index 2bcef6f..b09d24c 100644
--- a/riscv/insns/fsgnjx_d.h
+++ b/riscv/insns/fsgnjx_d.h
@@ -1,2 +1,3 @@
+require_extension('D');
require_fp;
WRITE_FRD(FRS1 ^ (FRS2 & INT64_MIN));
diff --git a/riscv/insns/fsgnjx_h.h b/riscv/insns/fsgnjx_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fsgnjx_h.h
+++ /dev/null
diff --git a/riscv/insns/fsgnjx_s.h b/riscv/insns/fsgnjx_s.h
index 69b2d98..1fd2de6 100644
--- a/riscv/insns/fsgnjx_s.h
+++ b/riscv/insns/fsgnjx_s.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
WRITE_FRD(FRS1 ^ (FRS2 & (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fsh.h b/riscv/insns/fsh.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fsh.h
+++ /dev/null
diff --git a/riscv/insns/fsqrt_d.h b/riscv/insns/fsqrt_d.h
index 0ff5daa..812438c 100644
--- a/riscv/insns/fsqrt_d.h
+++ b/riscv/insns/fsqrt_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_sqrt(FRS1));
diff --git a/riscv/insns/fsqrt_h.h b/riscv/insns/fsqrt_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fsqrt_h.h
+++ /dev/null
diff --git a/riscv/insns/fsqrt_s.h b/riscv/insns/fsqrt_s.h
index ea1f31a..d77acab 100644
--- a/riscv/insns/fsqrt_s.h
+++ b/riscv/insns/fsqrt_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_sqrt(FRS1));
diff --git a/riscv/insns/fsub_d.h b/riscv/insns/fsub_d.h
index 238ee9e..6ffc6b3 100644
--- a/riscv/insns/fsub_d.h
+++ b/riscv/insns/fsub_d.h
@@ -1,3 +1,4 @@
+require_extension('D');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f64_mulAdd(FRS1, 0x3ff0000000000000ULL, FRS2 ^ (uint64_t)INT64_MIN));
diff --git a/riscv/insns/fsub_h.h b/riscv/insns/fsub_h.h
deleted file mode 100644
index e69de29..0000000
--- a/riscv/insns/fsub_h.h
+++ /dev/null
diff --git a/riscv/insns/fsub_s.h b/riscv/insns/fsub_s.h
index a30b4f9..6a0f853 100644
--- a/riscv/insns/fsub_s.h
+++ b/riscv/insns/fsub_s.h
@@ -1,3 +1,4 @@
+require_extension('F');
require_fp;
softfloat_roundingMode = RM;
WRITE_FRD(f32_mulAdd(FRS1, 0x3f800000, FRS2 ^ (uint32_t)INT32_MIN));
diff --git a/riscv/insns/fsw.h b/riscv/insns/fsw.h
index 85c8091..3135e9b 100644
--- a/riscv/insns/fsw.h
+++ b/riscv/insns/fsw.h
@@ -1,2 +1,3 @@
+require_extension('F');
require_fp;
MMU.store_uint32(RS1 + insn.s_imm(), FRS2);
diff --git a/riscv/insns/lr_d.h b/riscv/insns/lr_d.h
index 94c4bf7..077590f 100644
--- a/riscv/insns/lr_d.h
+++ b/riscv/insns/lr_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
p->get_state()->load_reservation = RS1;
WRITE_RD(MMU.load_int64(RS1));
diff --git a/riscv/insns/lr_w.h b/riscv/insns/lr_w.h
index 2b95419..767251f 100644
--- a/riscv/insns/lr_w.h
+++ b/riscv/insns/lr_w.h
@@ -1,2 +1,3 @@
+require_extension('A');
p->get_state()->load_reservation = RS1;
WRITE_RD(MMU.load_int32(RS1));
diff --git a/riscv/insns/mul.h b/riscv/insns/mul.h
index c6b5331..0102d36 100644
--- a/riscv/insns/mul.h
+++ b/riscv/insns/mul.h
@@ -1 +1,2 @@
+require_extension('M');
WRITE_RD(sext_xlen(RS1 * RS2));
diff --git a/riscv/insns/mulh.h b/riscv/insns/mulh.h
index 567e213..051382a 100644
--- a/riscv/insns/mulh.h
+++ b/riscv/insns/mulh.h
@@ -1,3 +1,4 @@
+require_extension('M');
if (xlen == 64)
WRITE_RD(mulh(RS1, RS2));
else
diff --git a/riscv/insns/mulhsu.h b/riscv/insns/mulhsu.h
index 5eeb89c..c53f90b 100644
--- a/riscv/insns/mulhsu.h
+++ b/riscv/insns/mulhsu.h
@@ -1,3 +1,4 @@
+require_extension('M');
if (xlen == 64)
WRITE_RD(mulhsu(RS1, RS2));
else
diff --git a/riscv/insns/mulhu.h b/riscv/insns/mulhu.h
index ce6a21e..1ae3650 100644
--- a/riscv/insns/mulhu.h
+++ b/riscv/insns/mulhu.h
@@ -1,3 +1,4 @@
+require_extension('M');
if (xlen == 64)
WRITE_RD(mulhu(RS1, RS2));
else
diff --git a/riscv/insns/mulw.h b/riscv/insns/mulw.h
index 184dd41..ed55545 100644
--- a/riscv/insns/mulw.h
+++ b/riscv/insns/mulw.h
@@ -1,2 +1,3 @@
+require_extension('M');
require_rv64;
WRITE_RD(sext32(RS1 * RS2));
diff --git a/riscv/insns/rem.h b/riscv/insns/rem.h
index d074f26..8587995 100644
--- a/riscv/insns/rem.h
+++ b/riscv/insns/rem.h
@@ -1,3 +1,4 @@
+require_extension('M');
sreg_t lhs = sext_xlen(RS1);
sreg_t rhs = sext_xlen(RS2);
if(rhs == 0)
diff --git a/riscv/insns/remu.h b/riscv/insns/remu.h
index c291947..e74774c 100644
--- a/riscv/insns/remu.h
+++ b/riscv/insns/remu.h
@@ -1,3 +1,4 @@
+require_extension('M');
reg_t lhs = zext_xlen(RS1);
reg_t rhs = zext_xlen(RS2);
if(rhs == 0)
diff --git a/riscv/insns/remuw.h b/riscv/insns/remuw.h
index e487516..b239c8f 100644
--- a/riscv/insns/remuw.h
+++ b/riscv/insns/remuw.h
@@ -1,3 +1,4 @@
+require_extension('M');
require_rv64;
reg_t lhs = zext32(RS1);
reg_t rhs = zext32(RS2);
diff --git a/riscv/insns/remw.h b/riscv/insns/remw.h
index 2bae1a8..56221cc 100644
--- a/riscv/insns/remw.h
+++ b/riscv/insns/remw.h
@@ -1,3 +1,4 @@
+require_extension('M');
require_rv64;
sreg_t lhs = sext32(RS1);
sreg_t rhs = sext32(RS2);
diff --git a/riscv/insns/sc_d.h b/riscv/insns/sc_d.h
index 2108079..01a45ce 100644
--- a/riscv/insns/sc_d.h
+++ b/riscv/insns/sc_d.h
@@ -1,3 +1,4 @@
+require_extension('A');
require_rv64;
if (RS1 == p->get_state()->load_reservation)
{
diff --git a/riscv/insns/sc_w.h b/riscv/insns/sc_w.h
index 729973d..68ec577 100644
--- a/riscv/insns/sc_w.h
+++ b/riscv/insns/sc_w.h
@@ -1,3 +1,4 @@
+require_extension('A');
if (RS1 == p->get_state()->load_reservation)
{
MMU.store_uint32(RS1, RS2);
diff --git a/riscv/insns/sltiu.h b/riscv/insns/sltiu.h
index c4478fd..f398457 100644
--- a/riscv/insns/sltiu.h
+++ b/riscv/insns/sltiu.h
@@ -1 +1 @@
-WRITE_RD(RS1 < insn.i_imm());
+WRITE_RD(RS1 < reg_t(insn.i_imm()));
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
index 2519f84..e6bbbd4 100644
--- a/riscv/mmu.cc
+++ b/riscv/mmu.cc
@@ -4,6 +4,12 @@
#include "sim.h"
#include "processor.h"
+#define LEVELS(xlen) ((xlen) == 32 ? 2 : 3)
+#define PPN_SHIFT(xlen) ((xlen) == 32 ? 10 : 26)
+#define PTIDXBITS(xlen) ((xlen) == 32 ? 10 : 9)
+#define VPN_BITS(xlen) (PTIDXBITS(xlen) * LEVELS(xlen))
+#define VA_BITS(xlen) (VPN_BITS(xlen) + PGSHIFT)
+
mmu_t::mmu_t(char* _mem, size_t _memsz)
: mem(_mem), memsz(_memsz), proc(NULL)
{
@@ -79,25 +85,26 @@ void* mmu_t::refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch)
return mem + paddr;
}
-pte_t mmu_t::walk(reg_t addr, bool supervisor, bool store, bool fetch)
+reg_t mmu_t::walk(reg_t addr, bool supervisor, bool store, bool fetch)
{
- reg_t msb_mask = -(reg_t(1) << (VA_BITS-1));
+ reg_t msb_mask = -(reg_t(1) << (VA_BITS(proc->xlen) - 1));
if ((addr & msb_mask) != 0 && (addr & msb_mask) != msb_mask)
return -1; // address isn't properly sign-extended
reg_t base = proc->get_state()->sptbr;
- int ptshift = (LEVELS-1)*PTIDXBITS;
- for (reg_t i = 0; i < LEVELS; i++, ptshift -= PTIDXBITS) {
- reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS)-1);
+ int xlen = proc->max_xlen;
+ int ptshift = (LEVELS(xlen) - 1) * PTIDXBITS(xlen);
+ for (reg_t i = 0; i < LEVELS(xlen); i++, ptshift -= PTIDXBITS(xlen)) {
+ reg_t idx = (addr >> (PGSHIFT+ptshift)) & ((1<<PTIDXBITS(xlen))-1);
// check that physical address of PTE is legal
- reg_t pte_addr = base + idx*sizeof(pte_t);
+ reg_t pte_addr = base + idx*sizeof(reg_t);
if (pte_addr >= memsz)
return -1;
- pte_t* ppte = (pte_t*)(mem+pte_addr);
- reg_t ppn = *ppte >> PTE_PPN_SHIFT;
+ reg_t* ppte = (reg_t*)(mem+pte_addr);
+ reg_t ppn = *ppte >> PPN_SHIFT(xlen);
if ((*ppte & PTE_TYPE) == PTE_TYPE_TABLE) { // next level of page table
base = ppn << PGSHIFT;
diff --git a/riscv/mmu.h b/riscv/mmu.h
index d6f446b..a8853d3 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -12,13 +12,8 @@
#include <vector>
// virtual memory configuration
-typedef reg_t pte_t;
-const reg_t LEVELS = sizeof(pte_t) == 8 ? 3 : 2;
-const reg_t PGSHIFT = 12;
-const reg_t PTIDXBITS = PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2);
+#define PGSHIFT 12
const reg_t PGSIZE = 1 << PGSHIFT;
-const reg_t VPN_BITS = PTIDXBITS * LEVELS;
-const reg_t VA_BITS = VPN_BITS + PGSHIFT;
struct insn_fetch_t
{
@@ -153,7 +148,7 @@ private:
void* refill_tlb(reg_t addr, reg_t bytes, bool store, bool fetch);
// perform a page table walk for a given VA; set referenced/dirty bits
- pte_t walk(reg_t addr, bool supervisor, bool store, bool fetch);
+ reg_t walk(reg_t addr, bool supervisor, bool store, bool fetch);
// translate a virtual address to a physical address
void* translate(reg_t addr, reg_t bytes, bool store, bool fetch)
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 51e56b1..1187265 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -19,13 +19,17 @@
#undef STATE
#define STATE state
-processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
- : sim(_sim), mmu(_mmu), ext(NULL), disassembler(new disassembler_t),
- id(_id), run(false), debug(false)
+processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id)
+ : sim(sim), ext(NULL), disassembler(new disassembler_t),
+ id(id), run(false), debug(false)
{
- reset(true);
+ parse_isa_string(isa);
+
+ mmu = new mmu_t(sim->mem, sim->memsz);
mmu->set_processor(this);
+ reset(true);
+
#define DECLARE_INSN(name, match, mask) REGISTER_INSN(this, name, match, mask)
#include "encoding.h"
#undef DECLARE_INSN
@@ -44,19 +48,62 @@ processor_t::~processor_t()
}
#endif
+ delete mmu;
delete disassembler;
}
+static void bad_isa_string(const char* isa)
+{
+ fprintf(stderr, "error: bad --isa option %s\n", isa);
+ abort();
+}
+
+void processor_t::parse_isa_string(const char* isa)
+{
+ const char* p = isa;
+ const char* all_subsets = "IMAFDC";
+
+ max_xlen = 64;
+ if (strncmp(p, "RV32", 4) == 0)
+ max_xlen = 32, p += 4;
+ else if (strncmp(p, "RV64", 4) == 0)
+ p += 4;
+ else if (strncmp(p, "RV", 2) == 0)
+ p += 2;
+
+ if (!*p)
+ p = all_subsets;
+ else if (*p != 'I')
+ bad_isa_string(isa);
+
+ memset(subsets, 0, sizeof(subsets));
+
+ while (*p) {
+ if (auto next = strchr(all_subsets, *p)) {
+ subsets[(int)*p] = true;
+ all_subsets = next + 1;
+ p++;
+ } else if (*p == 'X') {
+ const char* ext = p+1, *end = ext;
+ while (islower(*end))
+ end++;
+ register_extension(find_extension(std::string(ext, end - ext).c_str())());
+ p = end;
+ } else {
+ bad_isa_string(isa);
+ }
+ }
+
+ if (supports_extension('D') && !supports_extension('F'))
+ bad_isa_string(isa);
+}
+
void state_t::reset()
{
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;
}
@@ -79,7 +126,7 @@ void processor_t::reset(bool value)
return;
run = !value;
- state.reset(); // reset the core
+ state.reset();
set_csr(CSR_MSTATUS, state.mstatus);
if (ext)
@@ -88,7 +135,7 @@ void processor_t::reset(bool value)
void processor_t::raise_interrupt(reg_t which)
{
- throw trap_t(((reg_t)1 << 63) | which);
+ throw trap_t(((reg_t)1 << (max_xlen-1)) | which);
}
void processor_t::take_interrupt()
@@ -286,20 +333,19 @@ static bool validate_priv(reg_t priv)
return priv == PRV_U || priv == PRV_S || priv == PRV_M;
}
-static bool validate_arch(reg_t arch)
+static bool validate_arch(int max_xlen, reg_t arch)
{
-#ifdef RISCV_ENABLE_64BIT
- if (arch == UA_RV64) return true;
-#endif
+ if (max_xlen == 64 && arch == UA_RV64)
+ return true;
return arch == UA_RV32;
}
-static bool validate_vm(reg_t vm)
+static bool validate_vm(int max_xlen, reg_t vm)
{
- // TODO: VM_SV32 support
-#ifdef RISCV_ENABLE_64BIT
- if (vm == VM_SV43) return true;
-#endif
+ if (max_xlen == 64 && vm == VM_SV39)
+ return true;
+ if (max_xlen == 32 && vm == VM_SV32)
+ return true;
return vm == VM_MBARE;
}
@@ -340,7 +386,7 @@ void processor_t::set_csr(int which, reg_t val)
mask |= MSTATUS_XS;
state.mstatus = (state.mstatus & ~mask) | (val & mask);
- if (validate_vm(get_field(val, MSTATUS_VM)))
+ if (validate_vm(max_xlen, 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);
@@ -352,26 +398,26 @@ void processor_t::set_csr(int which, reg_t val)
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();
+ xlen = 32;
+ if (max_xlen == 32) {
+ state.mstatus = set_field(state.mstatus, MSTATUS32_SD, dirty);
+ } else {
+ state.mstatus = set_field(state.mstatus, MSTATUS64_SD, dirty);
+
+ if (validate_arch(max_xlen, get_field(val, MSTATUS64_UA)))
+ state.mstatus = (state.mstatus & ~MSTATUS64_UA) | (val & MSTATUS64_UA);
+ if (validate_arch(max_xlen, 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
break;
}
case CSR_SSTATUS:
@@ -458,8 +504,8 @@ reg_t processor_t::get_csr(int which)
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);
+ if (max_xlen > xlen)
+ return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1));
return state.scause;
case CSR_SPTBR: return state.sptbr;
case CSR_SASID: return 0;
diff --git a/riscv/processor.h b/riscv/processor.h
index e9d9c4f..c0acad9 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -71,7 +71,7 @@ struct state_t
class processor_t
{
public:
- processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id);
+ processor_t(const char* isa, sim_t* sim, uint32_t id);
~processor_t();
void set_debug(bool value);
@@ -86,6 +86,7 @@ public:
mmu_t* get_mmu() { return mmu; }
state_t* get_state() { return &state; }
extension_t* get_extension() { return ext; }
+ bool supports_extension(unsigned char ext) { return subsets[ext]; }
void push_privilege_stack();
void pop_privilege_stack();
void yield_load_reservation() { state.load_reservation = (reg_t)-1; }
@@ -100,7 +101,9 @@ private:
extension_t* ext;
disassembler_t* disassembler;
state_t state;
+ bool subsets[256];
uint32_t id;
+ int max_xlen;
int xlen;
bool run; // !reset
bool debug;
@@ -119,6 +122,7 @@ private:
friend class mmu_t;
friend class extension_t;
+ void parse_isa_string(const char* isa);
void build_opcode_map();
insn_func_t decode_insn(insn_t insn);
};
diff --git a/riscv/riscv.ac b/riscv/riscv.ac
index 0b095e8..2a8ee53 100644
--- a/riscv/riscv.ac
+++ b/riscv/riscv.ac
@@ -1,5 +1,9 @@
AC_LANG_CPLUSPLUS
+AC_SEARCH_LIBS([dlopen], [dl dld], [], [
+ AC_MSG_ERROR([unable to find the dlopen() function])
+])
+
AC_ARG_WITH([fesvr],
[AS_HELP_STRING([--with-fesvr],
[path to your fesvr installation if not in a standard location])],
@@ -13,21 +17,6 @@ AC_CHECK_LIB(fesvr, libfesvr_is_present, [], [AC_MSG_ERROR([libfesvr is required
AC_CHECK_LIB(pthread, pthread_create, [], [AC_MSG_ERROR([libpthread is required])])
-AC_ARG_ENABLE([fpu], AS_HELP_STRING([--disable-fpu], [Disable floating-point]))
-AS_IF([test "x$enable_fpu" != "xno"], [
- AC_DEFINE([RISCV_ENABLE_FPU],,[Define if floating-point instructions are supported])
-])
-
-AC_ARG_ENABLE([rvc], AS_HELP_STRING([--disable-rvc], [Disable RISC-V Compressed]))
-AS_IF([test "x$enable_rvc" != "xno"], [
- AC_DEFINE([RISCV_ENABLE_RVC],,[Define if RISC-V Compressed is supported])
-])
-
-AC_ARG_ENABLE([64bit], AS_HELP_STRING([--disable-64bit], [Disable 64-bit mode]))
-AS_IF([test "x$enable_64bit" != "xno"], [
- AC_DEFINE([RISCV_ENABLE_64BIT],,[Define if 64-bit mode is supported])
-])
-
AC_ARG_ENABLE([commitlog], AS_HELP_STRING([--enable-commitlog], [Enable commit log generation]))
AS_IF([test "x$enable_commitlog" = "xyes"], [
AC_DEFINE([RISCV_ENABLE_COMMITLOG],,[Enable commit log generation])
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index 9e5aa9f..d307259 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -35,6 +35,7 @@ riscv_srcs = \
mmu.cc \
disasm.cc \
extension.cc \
+ extensions.cc \
rocc.cc \
regnames.cc \
$(riscv_gen_srcs) \
@@ -42,7 +43,7 @@ riscv_srcs = \
riscv_test_srcs =
riscv_gen_hdrs = \
- icache.h \
+ icache.h \
riscv_gen_srcs = \
$(addsuffix .cc, $(call get_insn_list,$(src_dir)/riscv/encoding.h))
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 9490af3..0fdd829 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -18,7 +18,8 @@ static void handle_signal(int sig)
signal(sig, &handle_signal);
}
-sim_t::sim_t(size_t nprocs, size_t mem_mb, const std::vector<std::string>& args)
+sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb,
+ const std::vector<std::string>& args)
: htif(new htif_isasim_t(this, args)), procs(std::max(nprocs, size_t(1))),
current_step(0), current_proc(0), debug(false)
{
@@ -40,20 +41,14 @@ sim_t::sim_t(size_t nprocs, size_t mem_mb, const std::vector<std::string>& args)
debug_mmu = new mmu_t(mem, memsz);
- for (size_t i = 0; i < procs.size(); i++) {
- procs[i] = new processor_t(this, new mmu_t(mem, memsz), i);
- }
-
+ for (size_t i = 0; i < procs.size(); i++)
+ procs[i] = new processor_t(isa, this, i);
}
sim_t::~sim_t()
{
for (size_t i = 0; i < procs.size(); i++)
- {
- mmu_t* pmmu = procs[i]->get_mmu();
delete procs[i];
- delete pmmu;
- }
delete debug_mmu;
free(mem);
}
diff --git a/riscv/sim.h b/riscv/sim.h
index 9e1362e..ca1ad6f 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -15,7 +15,8 @@ class htif_isasim_t;
class sim_t
{
public:
- sim_t(size_t _nprocs, size_t mem_mb, const std::vector<std::string>& htif_args);
+ sim_t(const char* isa, size_t _nprocs, size_t mem_mb,
+ const std::vector<std::string>& htif_args);
~sim_t();
// run the simulation to completion
@@ -72,6 +73,7 @@ private:
reg_t get_tohost(const std::vector<std::string>& args);
friend class htif_isasim_t;
+ friend class processor_t;
};
extern volatile bool ctrlc_pressed;