aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-06-19 20:47:29 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-06-19 20:47:29 -0700
commit77452a26e7d95d29dbaa797595ae683f03a3345b (patch)
treee7aaae682f73a20ceb4d3366528b0cd38378f49d /riscv
parent740f981cfd55604d46598144dccac26dd53f643c (diff)
downloadspike-77452a26e7d95d29dbaa797595ae683f03a3345b.zip
spike-77452a26e7d95d29dbaa797595ae683f03a3345b.tar.gz
spike-77452a26e7d95d29dbaa797595ae683f03a3345b.tar.bz2
temporary undoing of renaming
Diffstat (limited to 'riscv')
-rw-r--r--riscv/common.h9
-rw-r--r--riscv/decode.h301
-rwxr-xr-xriscv/dispatch77
-rw-r--r--riscv/dispatch.h254
-rw-r--r--riscv/htif.cc143
-rw-r--r--riscv/htif.h35
-rw-r--r--riscv/icsim.cc100
-rw-r--r--riscv/icsim.h55
-rw-r--r--riscv/insn_header.h7
-rw-r--r--riscv/insns/add.h1
-rw-r--r--riscv/insns/addi.h1
-rw-r--r--riscv/insns/addiw.h2
-rw-r--r--riscv/insns/addw.h2
-rw-r--r--riscv/insns/amoadd_d.h4
-rw-r--r--riscv/insns/amoadd_w.h3
-rw-r--r--riscv/insns/amoand_d.h4
-rw-r--r--riscv/insns/amoand_w.h3
-rw-r--r--riscv/insns/amomax_d.h4
-rw-r--r--riscv/insns/amomax_w.h3
-rw-r--r--riscv/insns/amomaxu_d.h4
-rw-r--r--riscv/insns/amomaxu_w.h3
-rw-r--r--riscv/insns/amomin_d.h4
-rw-r--r--riscv/insns/amomin_w.h3
-rw-r--r--riscv/insns/amominu_d.h4
-rw-r--r--riscv/insns/amominu_w.h3
-rw-r--r--riscv/insns/amoor_d.h4
-rw-r--r--riscv/insns/amoor_w.h3
-rw-r--r--riscv/insns/amoswap_d.h4
-rw-r--r--riscv/insns/amoswap_w.h3
-rw-r--r--riscv/insns/and.h1
-rw-r--r--riscv/insns/andi.h1
-rw-r--r--riscv/insns/beq.h2
-rw-r--r--riscv/insns/bge.h2
-rw-r--r--riscv/insns/bgeu.h2
-rw-r--r--riscv/insns/blt.h2
-rw-r--r--riscv/insns/bltu.h2
-rw-r--r--riscv/insns/bne.h2
-rw-r--r--riscv/insns/break.h1
-rw-r--r--riscv/insns/c_add.h2
-rw-r--r--riscv/insns/c_add3.h2
-rw-r--r--riscv/insns/c_addi.h10
-rw-r--r--riscv/insns/c_addiw.h3
-rw-r--r--riscv/insns/c_and3.h2
-rw-r--r--riscv/insns/c_beq.h3
-rw-r--r--riscv/insns/c_bne.h3
-rw-r--r--riscv/insns/c_fld.h3
-rw-r--r--riscv/insns/c_flw.h3
-rw-r--r--riscv/insns/c_fsd.h3
-rw-r--r--riscv/insns/c_fsw.h3
-rw-r--r--riscv/insns/c_j.h2
-rw-r--r--riscv/insns/c_ld.h3
-rw-r--r--riscv/insns/c_ld0.h3
-rw-r--r--riscv/insns/c_ldsp.h3
-rw-r--r--riscv/insns/c_li.h2
-rw-r--r--riscv/insns/c_lw.h2
-rw-r--r--riscv/insns/c_lw0.h2
-rw-r--r--riscv/insns/c_lwsp.h2
-rw-r--r--riscv/insns/c_move.h2
-rw-r--r--riscv/insns/c_or3.h2
-rw-r--r--riscv/insns/c_sd.h3
-rw-r--r--riscv/insns/c_sdsp.h3
-rw-r--r--riscv/insns/c_slli.h5
-rw-r--r--riscv/insns/c_slli32.h3
-rw-r--r--riscv/insns/c_slliw.h3
-rw-r--r--riscv/insns/c_srai.h5
-rw-r--r--riscv/insns/c_srai32.h3
-rw-r--r--riscv/insns/c_srli.h5
-rw-r--r--riscv/insns/c_srli32.h3
-rw-r--r--riscv/insns/c_sub.h2
-rw-r--r--riscv/insns/c_sub3.h2
-rw-r--r--riscv/insns/c_sw.h2
-rw-r--r--riscv/insns/c_swsp.h2
-rw-r--r--riscv/insns/cflush.h1
-rw-r--r--riscv/insns/di.h4
-rw-r--r--riscv/insns/div.h6
-rw-r--r--riscv/insns/divu.h4
-rw-r--r--riscv/insns/divuw.h5
-rw-r--r--riscv/insns/divw.h7
-rw-r--r--riscv/insns/ei.h4
-rw-r--r--riscv/insns/eret.h5
-rw-r--r--riscv/insns/fadd_d.h4
-rw-r--r--riscv/insns/fadd_s.h4
-rw-r--r--riscv/insns/fcvt_d_l.h5
-rw-r--r--riscv/insns/fcvt_d_lu.h5
-rw-r--r--riscv/insns/fcvt_d_s.h4
-rw-r--r--riscv/insns/fcvt_d_w.h4
-rw-r--r--riscv/insns/fcvt_d_wu.h4
-rw-r--r--riscv/insns/fcvt_l_d.h5
-rw-r--r--riscv/insns/fcvt_l_s.h5
-rw-r--r--riscv/insns/fcvt_lu_d.h5
-rw-r--r--riscv/insns/fcvt_lu_s.h5
-rw-r--r--riscv/insns/fcvt_s_d.h4
-rw-r--r--riscv/insns/fcvt_s_l.h5
-rw-r--r--riscv/insns/fcvt_s_lu.h5
-rw-r--r--riscv/insns/fcvt_s_w.h4
-rw-r--r--riscv/insns/fcvt_s_wu.h4
-rw-r--r--riscv/insns/fcvt_w_d.h4
-rw-r--r--riscv/insns/fcvt_w_s.h4
-rw-r--r--riscv/insns/fcvt_wu_d.h4
-rw-r--r--riscv/insns/fcvt_wu_s.h4
-rw-r--r--riscv/insns/fdiv_d.h4
-rw-r--r--riscv/insns/fdiv_s.h4
-rw-r--r--riscv/insns/fence.h0
-rw-r--r--riscv/insns/fence_g_cv.h0
-rw-r--r--riscv/insns/fence_g_v.h0
-rw-r--r--riscv/insns/fence_i.h1
-rw-r--r--riscv/insns/fence_l_cv.h0
-rw-r--r--riscv/insns/fence_l_v.h0
-rw-r--r--riscv/insns/feq_d.h3
-rw-r--r--riscv/insns/feq_s.h3
-rw-r--r--riscv/insns/fld.h2
-rw-r--r--riscv/insns/fle_d.h3
-rw-r--r--riscv/insns/fle_s.h3
-rw-r--r--riscv/insns/flt_d.h3
-rw-r--r--riscv/insns/flt_s.h3
-rw-r--r--riscv/insns/flw.h2
-rw-r--r--riscv/insns/fmadd_d.h4
-rw-r--r--riscv/insns/fmadd_s.h4
-rw-r--r--riscv/insns/fmax_d.h4
-rw-r--r--riscv/insns/fmax_s.h4
-rw-r--r--riscv/insns/fmin_d.h4
-rw-r--r--riscv/insns/fmin_s.h4
-rw-r--r--riscv/insns/fmovn.h2
-rw-r--r--riscv/insns/fmovz.h2
-rw-r--r--riscv/insns/fmsub_d.h4
-rw-r--r--riscv/insns/fmsub_s.h4
-rw-r--r--riscv/insns/fmul_d.h4
-rw-r--r--riscv/insns/fmul_s.h4
-rw-r--r--riscv/insns/fnmadd_d.h4
-rw-r--r--riscv/insns/fnmadd_s.h4
-rw-r--r--riscv/insns/fnmsub_d.h4
-rw-r--r--riscv/insns/fnmsub_s.h4
-rw-r--r--riscv/insns/fsd.h2
-rw-r--r--riscv/insns/fsgnj_d.h2
-rw-r--r--riscv/insns/fsgnj_s.h2
-rw-r--r--riscv/insns/fsgnjn_d.h2
-rw-r--r--riscv/insns/fsgnjn_s.h2
-rw-r--r--riscv/insns/fsgnjx_d.h2
-rw-r--r--riscv/insns/fsgnjx_s.h2
-rw-r--r--riscv/insns/fsqrt_d.h4
-rw-r--r--riscv/insns/fsqrt_s.h4
-rw-r--r--riscv/insns/fsub_d.h4
-rw-r--r--riscv/insns/fsub_s.h4
-rw-r--r--riscv/insns/fsw.h2
-rw-r--r--riscv/insns/j.h1
-rw-r--r--riscv/insns/jal.h2
-rw-r--r--riscv/insns/jalr_c.h3
-rw-r--r--riscv/insns/jalr_j.h1
-rw-r--r--riscv/insns/jalr_r.h1
-rw-r--r--riscv/insns/lb.h1
-rw-r--r--riscv/insns/lbu.h1
-rw-r--r--riscv/insns/ld.h2
-rw-r--r--riscv/insns/lh.h1
-rw-r--r--riscv/insns/lhu.h1
-rw-r--r--riscv/insns/lui.h1
-rw-r--r--riscv/insns/lw.h1
-rw-r--r--riscv/insns/lwu.h2
-rw-r--r--riscv/insns/mffsr.h2
-rw-r--r--riscv/insns/mfpcr.h68
-rw-r--r--riscv/insns/mftx_d.h3
-rw-r--r--riscv/insns/mftx_s.h2
-rw-r--r--riscv/insns/movn.h2
-rw-r--r--riscv/insns/movz.h2
-rw-r--r--riscv/insns/mtfsr.h4
-rw-r--r--riscv/insns/mtpcr.h45
-rw-r--r--riscv/insns/mul.h1
-rw-r--r--riscv/insns/mulh.h8
-rw-r--r--riscv/insns/mulhsu.h8
-rw-r--r--riscv/insns/mulhu.h4
-rw-r--r--riscv/insns/mulw.h2
-rw-r--r--riscv/insns/mxtf_d.h3
-rw-r--r--riscv/insns/mxtf_s.h2
-rw-r--r--riscv/insns/or.h1
-rw-r--r--riscv/insns/ori.h1
-rw-r--r--riscv/insns/rdcycle.h1
-rw-r--r--riscv/insns/rdinstret.h1
-rw-r--r--riscv/insns/rdnpc.h1
-rw-r--r--riscv/insns/rdtime.h1
-rw-r--r--riscv/insns/rem.h6
-rw-r--r--riscv/insns/remu.h4
-rw-r--r--riscv/insns/remuw.h5
-rw-r--r--riscv/insns/remw.h7
-rw-r--r--riscv/insns/sb.h1
-rw-r--r--riscv/insns/sd.h2
-rw-r--r--riscv/insns/sh.h1
-rw-r--r--riscv/insns/sll.h1
-rw-r--r--riscv/insns/slli.h8
-rw-r--r--riscv/insns/slliw.h2
-rw-r--r--riscv/insns/sllw.h2
-rw-r--r--riscv/insns/slt.h1
-rw-r--r--riscv/insns/slti.h1
-rw-r--r--riscv/insns/sltiu.h1
-rw-r--r--riscv/insns/sltu.h1
-rw-r--r--riscv/insns/sra.h1
-rw-r--r--riscv/insns/srai.h8
-rw-r--r--riscv/insns/sraiw.h2
-rw-r--r--riscv/insns/sraw.h2
-rw-r--r--riscv/insns/srl.h4
-rw-r--r--riscv/insns/srli.h8
-rw-r--r--riscv/insns/srliw.h2
-rw-r--r--riscv/insns/srlw.h2
-rw-r--r--riscv/insns/stop.h3
-rw-r--r--riscv/insns/sub.h1
-rw-r--r--riscv/insns/subw.h3
-rw-r--r--riscv/insns/sw.h1
-rw-r--r--riscv/insns/syscall.h1
-rw-r--r--riscv/insns/utidx.h2
-rw-r--r--riscv/insns/vf.h8
-rw-r--r--riscv/insns/vfld.h3
-rw-r--r--riscv/insns/vflsegd.h0
-rw-r--r--riscv/insns/vflsegstd.h0
-rw-r--r--riscv/insns/vflsegstw.h0
-rw-r--r--riscv/insns/vflsegw.h0
-rw-r--r--riscv/insns/vflstd.h3
-rw-r--r--riscv/insns/vflstw.h3
-rw-r--r--riscv/insns/vflw.h3
-rw-r--r--riscv/insns/vfmst.h4
-rw-r--r--riscv/insns/vfmsv.h5
-rw-r--r--riscv/insns/vfmts.h4
-rw-r--r--riscv/insns/vfmvv.h5
-rw-r--r--riscv/insns/vfsd.h3
-rw-r--r--riscv/insns/vfssegd.h0
-rw-r--r--riscv/insns/vfssegstd.h0
-rw-r--r--riscv/insns/vfssegstw.h0
-rw-r--r--riscv/insns/vfssegw.h0
-rw-r--r--riscv/insns/vfsstd.h3
-rw-r--r--riscv/insns/vfsstw.h3
-rw-r--r--riscv/insns/vfsw.h3
-rw-r--r--riscv/insns/vlb.h2
-rw-r--r--riscv/insns/vlbu.h2
-rw-r--r--riscv/insns/vld.h3
-rw-r--r--riscv/insns/vlh.h2
-rw-r--r--riscv/insns/vlhu.h2
-rw-r--r--riscv/insns/vlsegb.h0
-rw-r--r--riscv/insns/vlsegbu.h0
-rw-r--r--riscv/insns/vlsegd.h0
-rw-r--r--riscv/insns/vlsegh.h0
-rw-r--r--riscv/insns/vlseghu.h0
-rw-r--r--riscv/insns/vlsegstb.h0
-rw-r--r--riscv/insns/vlsegstbu.h0
-rw-r--r--riscv/insns/vlsegstd.h0
-rw-r--r--riscv/insns/vlsegsth.h0
-rw-r--r--riscv/insns/vlsegsthu.h0
-rw-r--r--riscv/insns/vlsegstw.h0
-rw-r--r--riscv/insns/vlsegstwu.h0
-rw-r--r--riscv/insns/vlsegw.h0
-rw-r--r--riscv/insns/vlsegwu.h0
-rw-r--r--riscv/insns/vlstb.h2
-rw-r--r--riscv/insns/vlstbu.h2
-rw-r--r--riscv/insns/vlstd.h3
-rw-r--r--riscv/insns/vlsth.h2
-rw-r--r--riscv/insns/vlsthu.h2
-rw-r--r--riscv/insns/vlstw.h2
-rw-r--r--riscv/insns/vlstwu.h2
-rw-r--r--riscv/insns/vlw.h2
-rw-r--r--riscv/insns/vlwu.h2
-rw-r--r--riscv/insns/vmst.h3
-rw-r--r--riscv/insns/vmsv.h4
-rw-r--r--riscv/insns/vmts.h3
-rw-r--r--riscv/insns/vmvv.h4
-rw-r--r--riscv/insns/vsb.h2
-rw-r--r--riscv/insns/vsd.h3
-rw-r--r--riscv/insns/vsetvl.h3
-rw-r--r--riscv/insns/vsh.h2
-rw-r--r--riscv/insns/vssegb.h0
-rw-r--r--riscv/insns/vssegd.h0
-rw-r--r--riscv/insns/vssegh.h0
-rw-r--r--riscv/insns/vssegstb.h0
-rw-r--r--riscv/insns/vssegstd.h0
-rw-r--r--riscv/insns/vssegsth.h0
-rw-r--r--riscv/insns/vssegstw.h0
-rw-r--r--riscv/insns/vssegw.h0
-rw-r--r--riscv/insns/vsstb.h2
-rw-r--r--riscv/insns/vsstd.h3
-rw-r--r--riscv/insns/vssth.h2
-rw-r--r--riscv/insns/vsstw.h2
-rw-r--r--riscv/insns/vsw.h2
-rw-r--r--riscv/insns/vtcfgivl.h0
-rw-r--r--riscv/insns/vvcfgivl.h6
-rw-r--r--riscv/insns/xor.h1
-rw-r--r--riscv/insns/xori.h1
-rw-r--r--riscv/interactive.cc256
-rw-r--r--riscv/mmu.cc104
-rw-r--r--riscv/mmu.h191
-rw-r--r--riscv/opcodes.h272
-rw-r--r--riscv/processor.cc240
-rw-r--r--riscv/processor.h89
-rw-r--r--riscv/riscv-isa-run.cc56
-rw-r--r--riscv/riscv.ac32
-rw-r--r--riscv/riscv.mk.in50
-rw-r--r--riscv/sim.cc92
-rw-r--r--riscv/sim.h82
-rw-r--r--riscv/trap.cc10
-rw-r--r--riscv/trap.h44
294 files changed, 3310 insertions, 0 deletions
diff --git a/riscv/common.h b/riscv/common.h
new file mode 100644
index 0000000..801baf8
--- /dev/null
+++ b/riscv/common.h
@@ -0,0 +1,9 @@
+#ifndef _RISCV_COMMON_H
+#define _RISCV_COMMON_H
+
+#define static_assert(x) switch (x) case 0: case (x):
+
+#define likely(x) __builtin_expect(x, 1)
+#define unlikely(x) __builtin_expect(x, 0)
+
+#endif
diff --git a/riscv/decode.h b/riscv/decode.h
new file mode 100644
index 0000000..f78c8f4
--- /dev/null
+++ b/riscv/decode.h
@@ -0,0 +1,301 @@
+#ifndef _RISCV_DECODE_H
+#define _RISCV_DECODE_H
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+#include "common.h"
+#include "config.h"
+
+typedef int int128_t __attribute__((mode(TI)));
+typedef unsigned int uint128_t __attribute__((mode(TI)));
+
+typedef int64_t sreg_t;
+typedef uint64_t reg_t;
+typedef uint64_t freg_t;
+
+const int OPCODE_BITS = 7;
+
+const int XPRID_BITS = 5;
+const int NXPR = 1 << XPRID_BITS;
+
+const int FPR_BITS = 64;
+const int FPRID_BITS = 5;
+const int NFPR = 1 << FPRID_BITS;
+
+const int IMM_BITS = 12;
+const int IMMLO_BITS = 7;
+const int TARGET_BITS = 25;
+const int FUNCT_BITS = 3;
+const int FUNCTR_BITS = 7;
+const int FFUNCT_BITS = 2;
+const int RM_BITS = 3;
+const int BIGIMM_BITS = 20;
+const int BRANCH_ALIGN_BITS = 1;
+const int JUMP_ALIGN_BITS = 1;
+
+#define SR_ET 0x0000000000000001ULL
+#define SR_EF 0x0000000000000002ULL
+#define SR_EV 0x0000000000000004ULL
+#define SR_EC 0x0000000000000008ULL
+#define SR_PS 0x0000000000000010ULL
+#define SR_S 0x0000000000000020ULL
+#define SR_UX 0x0000000000000040ULL
+#define SR_SX 0x0000000000000080ULL
+#define SR_IM 0x000000000000FF00ULL
+#define SR_VM 0x0000000000010000ULL
+#define SR_ZERO ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_UX|SR_SX|SR_IM|SR_VM)
+#define SR_IM_SHIFT 8
+#define IPI_IRQ 5
+#define TIMER_IRQ 7
+
+#define CAUSE_EXCCODE 0x000000FF
+#define CAUSE_IP 0x0000FF00
+#define CAUSE_EXCCODE_SHIFT 0
+#define CAUSE_IP_SHIFT 8
+
+#define FP_RD_NE 0
+#define FP_RD_0 1
+#define FP_RD_DN 2
+#define FP_RD_UP 3
+#define FP_RD_NMM 4
+
+#define FSR_RD_SHIFT 5
+#define FSR_RD (0x7 << FSR_RD_SHIFT)
+
+#define FPEXC_NX 0x01
+#define FPEXC_UF 0x02
+#define FPEXC_OF 0x04
+#define FPEXC_DZ 0x08
+#define FPEXC_NV 0x10
+
+#define FSR_AEXC_SHIFT 0
+#define FSR_NVA (FPEXC_NV << FSR_AEXC_SHIFT)
+#define FSR_OFA (FPEXC_OF << FSR_AEXC_SHIFT)
+#define FSR_UFA (FPEXC_UF << FSR_AEXC_SHIFT)
+#define FSR_DZA (FPEXC_DZ << FSR_AEXC_SHIFT)
+#define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT)
+#define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
+
+#define FSR_ZERO ~(FSR_RD | FSR_AEXC)
+
+// note: bit fields are in little-endian order
+struct itype_t
+{
+ unsigned opcode : OPCODE_BITS;
+ unsigned funct : FUNCT_BITS;
+ signed imm12 : IMM_BITS;
+ unsigned rs1 : XPRID_BITS;
+ unsigned rd : XPRID_BITS;
+};
+
+struct btype_t
+{
+ unsigned opcode : OPCODE_BITS;
+ unsigned funct : FUNCT_BITS;
+ unsigned immlo : IMMLO_BITS;
+ unsigned rs2 : XPRID_BITS;
+ unsigned rs1 : XPRID_BITS;
+ signed immhi : IMM_BITS-IMMLO_BITS;
+};
+
+struct jtype_t
+{
+ unsigned jump_opcode : OPCODE_BITS;
+ signed target : TARGET_BITS;
+};
+
+struct rtype_t
+{
+ unsigned opcode : OPCODE_BITS;
+ unsigned funct : FUNCT_BITS;
+ unsigned functr : FUNCTR_BITS;
+ unsigned rs2 : XPRID_BITS;
+ unsigned rs1 : XPRID_BITS;
+ unsigned rd : XPRID_BITS;
+};
+
+struct ltype_t
+{
+ unsigned opcode : OPCODE_BITS;
+ unsigned bigimm : BIGIMM_BITS;
+ unsigned rd : XPRID_BITS;
+};
+
+struct ftype_t
+{
+ unsigned opcode : OPCODE_BITS;
+ unsigned ffunct : FFUNCT_BITS;
+ unsigned rm : RM_BITS;
+ unsigned rs3 : FPRID_BITS;
+ unsigned rs2 : FPRID_BITS;
+ unsigned rs1 : FPRID_BITS;
+ unsigned rd : FPRID_BITS;
+};
+
+union insn_t
+{
+ itype_t itype;
+ jtype_t jtype;
+ rtype_t rtype;
+ btype_t btype;
+ ltype_t ltype;
+ ftype_t ftype;
+ uint32_t bits;
+};
+
+#include <stdio.h>
+class do_writeback
+{
+public:
+ do_writeback(reg_t* _rf, int _rd) : rf(_rf), rd(_rd) {}
+
+ const do_writeback& operator = (reg_t rhs)
+ {
+#if 0
+ printf("R[%x] <= %llx\n",rd,(long long)rhs);
+#endif
+ rf[rd] = rhs;
+ rf[0] = 0;
+ return *this;
+ }
+
+ operator reg_t() { return rf[rd]; }
+
+private:
+ reg_t* rf;
+ int rd;
+};
+
+#define throw_illegal_instruction \
+ ({ if (utmode) throw trap_vector_illegal_instruction; \
+ else throw trap_illegal_instruction; })
+
+// helpful macros, etc
+#define RS1 XPR[insn.rtype.rs1]
+#define RS2 XPR[insn.rtype.rs2]
+#define RD do_writeback(XPR,insn.rtype.rd)
+#define RA do_writeback(XPR,1)
+#define FRS1 FPR[insn.ftype.rs1]
+#define FRS2 FPR[insn.ftype.rs2]
+#define FRS3 FPR[insn.ftype.rs3]
+#define FRD FPR[insn.ftype.rd]
+#define BIGIMM insn.ltype.bigimm
+#define SIMM insn.itype.imm12
+#define BIMM ((signed)insn.btype.immlo | (insn.btype.immhi << IMMLO_BITS))
+#define SHAMT (insn.itype.imm12 & 0x3F)
+#define SHAMTW (insn.itype.imm12 & 0x1F)
+#define TARGET insn.jtype.target
+#define BRANCH_TARGET (pc + (BIMM << BRANCH_ALIGN_BITS))
+#define JUMP_TARGET (pc + (TARGET << JUMP_ALIGN_BITS))
+#define RM ({ int rm = insn.ftype.rm; \
+ if(rm == 7) rm = (fsr & FSR_RD) >> FSR_RD_SHIFT; \
+ if(rm > 4) throw_illegal_instruction; \
+ rm; })
+
+#define require_supervisor if(unlikely(!(sr & SR_S))) throw trap_privileged_instruction
+#define xpr64 (xprlen == 64)
+#define require_xpr64 if(unlikely(!xpr64)) throw_illegal_instruction
+#define require_xpr32 if(unlikely(xpr64)) throw_illegal_instruction
+#define require_fp if(unlikely(!(sr & SR_EF))) throw trap_fp_disabled
+#define require_vector \
+ ({ if(!(sr & SR_EV)) throw trap_vector_disabled; \
+ else if (!utmode && (vecbanks_count < 3)) throw trap_vector_bank; \
+ })
+#define cmp_trunc(reg) (reg_t(reg) << (64-xprlen))
+#define set_fp_exceptions ({ set_fsr(fsr | \
+ (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \
+ softfloat_exceptionFlags = 0; })
+
+#define sext32(x) ((sreg_t)(int32_t)(x))
+#define zext32(x) ((reg_t)(uint32_t)(x))
+#define sext_xprlen(x) ((sreg_t(x) << (64-xprlen)) >> (64-xprlen))
+#define zext_xprlen(x) ((reg_t(x) << (64-xprlen)) >> (64-xprlen))
+
+#ifndef RISCV_ENABLE_RVC
+# define set_pc(x) \
+ do { if((x) & (sizeof(insn_t)-1)) \
+ { badvaddr = (x); throw trap_instruction_address_misaligned; } \
+ npc = (x); \
+ } while(0)
+#else
+# define set_pc(x) \
+ do { if((x) & ((sr & SR_EC) ? 1 : 3)) \
+ { badvaddr = (x); throw trap_instruction_address_misaligned; } \
+ npc = (x); \
+ } while(0)
+#endif
+
+// RVC stuff
+
+#define INSN_IS_RVC(x) (((x) & 0x3) < 0x3)
+#define insn_length(x) (INSN_IS_RVC(x) ? 2 : 4)
+#define require_rvc if(!(sr & SR_EC)) throw_illegal_instruction
+
+#define CRD_REGNUM ((insn.bits >> 5) & 0x1f)
+#define CRD do_writeback(XPR, CRD_REGNUM)
+#define CRS1 XPR[(insn.bits >> 10) & 0x1f]
+#define CRS2 XPR[(insn.bits >> 5) & 0x1f]
+#define CIMM6 ((int32_t)((insn.bits >> 10) & 0x3f) << 26 >> 26)
+#define CIMM5U ((insn.bits >> 5) & 0x1f)
+#define CIMM5 ((int32_t)CIMM5U << 27 >> 27)
+#define CIMM10 ((int32_t)((insn.bits >> 5) & 0x3ff) << 22 >> 22)
+#define CBRANCH_TARGET (pc + (CIMM5 << BRANCH_ALIGN_BITS))
+#define CJUMP_TARGET (pc + (CIMM10 << JUMP_ALIGN_BITS))
+
+static const int rvc_rs1_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 7 };
+#define rvc_rd_regmap rvc_rs1_regmap
+#define rvc_rs2b_regmap rvc_rs1_regmap
+static const int rvc_rs2_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 0 };
+#define CRDS XPR[rvc_rd_regmap[(insn.bits >> 13) & 0x7]]
+#define FCRDS FPR[rvc_rd_regmap[(insn.bits >> 13) & 0x7]]
+#define CRS1S XPR[rvc_rs1_regmap[(insn.bits >> 10) & 0x7]]
+#define CRS2S XPR[rvc_rs2_regmap[(insn.bits >> 13) & 0x7]]
+#define CRS2BS XPR[rvc_rs2b_regmap[(insn.bits >> 5) & 0x7]]
+#define FCRS2S FPR[rvc_rs2_regmap[(insn.bits >> 13) & 0x7]]
+
+// vector stuff
+#define VL vl
+
+#define UT_RS1(idx) uts[idx]->XPR[insn.rtype.rs1]
+#define UT_RS2(idx) uts[idx]->XPR[insn.rtype.rs2]
+#define UT_RD(idx) do_writeback(uts[idx]->XPR,insn.rtype.rd)
+#define UT_RA(idx) do_writeback(uts[idx]->XPR,1)
+#define UT_FRS1(idx) uts[idx]->FPR[insn.ftype.rs1]
+#define UT_FRS2(idx) uts[idx]->FPR[insn.ftype.rs2]
+#define UT_FRS3(idx) uts[idx]->FPR[insn.ftype.rs3]
+#define UT_FRD(idx) uts[idx]->FPR[insn.ftype.rd]
+#define UT_RM(idx) ((insn.ftype.rm != 7) ? insn.ftype.rm : \
+ ((uts[idx]->fsr & FSR_RD) >> FSR_RD_SHIFT))
+
+#define UT_LOOP_START for (int i=0;i<VL; i++) {
+#define UT_LOOP_END }
+#define UT_LOOP_RS1 UT_RS1(i)
+#define UT_LOOP_RS2 UT_RS2(i)
+#define UT_LOOP_RD UT_RD(i)
+#define UT_LOOP_RA UT_RA(i)
+#define UT_LOOP_FRS1 UT_FRS1(i)
+#define UT_LOOP_FRS2 UT_FRS2(i)
+#define UT_LOOP_FRS3 UT_FRS3(i)
+#define UT_LOOP_FRD UT_FRD(i)
+#define UT_LOOP_RM UT_RM(i)
+
+#define VEC_LOAD(dst, func, inc) \
+ reg_t addr = RS1; \
+ UT_LOOP_START \
+ UT_LOOP_##dst = mmu.func(addr); \
+ addr += inc; \
+ UT_LOOP_END
+
+#define VEC_STORE(src, func, inc) \
+ reg_t addr = RS1; \
+ UT_LOOP_START \
+ mmu.func(addr, UT_LOOP_##src); \
+ addr += inc; \
+ UT_LOOP_END
+
+enum vt_command_t
+{
+ vt_command_stop,
+};
+
+#endif
diff --git a/riscv/dispatch b/riscv/dispatch
new file mode 100755
index 0000000..b96b364
--- /dev/null
+++ b/riscv/dispatch
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+import sys
+
+if len(sys.argv) == 3:
+ numfiles = int(sys.argv[1])
+ tablesz = int(sys.argv[2])
+ filenum = numfiles+1
+else:
+ filenum = int(sys.argv[1])
+ numfiles = int(sys.argv[2])
+ tablesz = int(sys.argv[3])
+
+match = {}
+mask = {}
+seen = {}
+for line in sys.stdin:
+ (name, mtch, msk) = line.split('(')[1].split(')')[0].split(',')
+ match[name] = int(mtch,16)
+ mask[name] = int(msk,16)
+
+redundant = {}
+for name in match.iterkeys():
+ if (mask[name] & (tablesz-1)) == mask[name]:
+ for i in range(match[name]+1, tablesz):
+ if (i & mask[name]) == match[name]:
+ redundant[i] = match[name]
+
+illegal = -1
+for i in range(0, tablesz):
+ used = 0
+ for name in match.iterkeys():
+ if match[name] % tablesz == (i & mask[name]):
+ used = 1
+ if not used and illegal == -1:
+ illegal = i
+ elif not used:
+ redundant[i] = illegal
+
+if filenum == numfiles:
+ print '#include "processor.h"'
+ print 'const insn_func_t processor_t::dispatch_table[DISPATCH_TABLE_SIZE] = {'
+ for i in range(0, tablesz):
+ func = i
+ if i in redundant:
+ func = redundant[i]
+ print ' &processor_t::insn_func_%d,' % func
+ print '};'
+
+if filenum == numfiles+1:
+ print 'static const size_t DISPATCH_TABLE_SIZE = %d;' % tablesz
+ print 'static const insn_func_t dispatch_table[DISPATCH_TABLE_SIZE];'
+ for i in range(0, tablesz):
+ if i not in redundant:
+ print 'reg_t insn_func_%d(insn_t insn, reg_t reg);' % i
+ sys.exit(0)
+
+print '#include "insn_header.h"'
+
+for i in range(0, tablesz):
+ if i % numfiles != filenum or i in redundant:
+ continue
+
+ print 'reg_t processor_t::insn_func_%d(insn_t insn, reg_t pc)' % i
+ print '{'
+ for name in match.iterkeys():
+ if match[name] % tablesz == (i & mask[name]):
+ print ' if((insn.bits & 0x%x) == 0x%x)' % (mask[name] & ~(tablesz-1), \
+ match[name] & ~(tablesz-1))
+ print ' {'
+ print ' reg_t npc = pc + insn_length(0x%x);' % match[name]
+ print ' #include "insns/%s.h"' % name
+ print ' return npc;'
+ print ' }'
+ print ' else',
+
+ print ' throw trap_illegal_instruction;'
+ print '}\n'
diff --git a/riscv/dispatch.h b/riscv/dispatch.h
new file mode 100644
index 0000000..7091899
--- /dev/null
+++ b/riscv/dispatch.h
@@ -0,0 +1,254 @@
+static const size_t DISPATCH_TABLE_SIZE = 1024;
+static const insn_func_t dispatch_table[DISPATCH_TABLE_SIZE];
+reg_t insn_func_0(insn_t insn, reg_t reg);
+reg_t insn_func_1(insn_t insn, reg_t reg);
+reg_t insn_func_2(insn_t insn, reg_t reg);
+reg_t insn_func_3(insn_t insn, reg_t reg);
+reg_t insn_func_4(insn_t insn, reg_t reg);
+reg_t insn_func_5(insn_t insn, reg_t reg);
+reg_t insn_func_6(insn_t insn, reg_t reg);
+reg_t insn_func_7(insn_t insn, reg_t reg);
+reg_t insn_func_8(insn_t insn, reg_t reg);
+reg_t insn_func_9(insn_t insn, reg_t reg);
+reg_t insn_func_10(insn_t insn, reg_t reg);
+reg_t insn_func_11(insn_t insn, reg_t reg);
+reg_t insn_func_12(insn_t insn, reg_t reg);
+reg_t insn_func_13(insn_t insn, reg_t reg);
+reg_t insn_func_15(insn_t insn, reg_t reg);
+reg_t insn_func_16(insn_t insn, reg_t reg);
+reg_t insn_func_17(insn_t insn, reg_t reg);
+reg_t insn_func_18(insn_t insn, reg_t reg);
+reg_t insn_func_19(insn_t insn, reg_t reg);
+reg_t insn_func_20(insn_t insn, reg_t reg);
+reg_t insn_func_21(insn_t insn, reg_t reg);
+reg_t insn_func_22(insn_t insn, reg_t reg);
+reg_t insn_func_24(insn_t insn, reg_t reg);
+reg_t insn_func_25(insn_t insn, reg_t reg);
+reg_t insn_func_26(insn_t insn, reg_t reg);
+reg_t insn_func_27(insn_t insn, reg_t reg);
+reg_t insn_func_28(insn_t insn, reg_t reg);
+reg_t insn_func_29(insn_t insn, reg_t reg);
+reg_t insn_func_34(insn_t insn, reg_t reg);
+reg_t insn_func_35(insn_t insn, reg_t reg);
+reg_t insn_func_50(insn_t insn, reg_t reg);
+reg_t insn_func_51(insn_t insn, reg_t reg);
+reg_t insn_func_55(insn_t insn, reg_t reg);
+reg_t insn_func_57(insn_t insn, reg_t reg);
+reg_t insn_func_58(insn_t insn, reg_t reg);
+reg_t insn_func_59(insn_t insn, reg_t reg);
+reg_t insn_func_66(insn_t insn, reg_t reg);
+reg_t insn_func_67(insn_t insn, reg_t reg);
+reg_t insn_func_71(insn_t insn, reg_t reg);
+reg_t insn_func_75(insn_t insn, reg_t reg);
+reg_t insn_func_79(insn_t insn, reg_t reg);
+reg_t insn_func_82(insn_t insn, reg_t reg);
+reg_t insn_func_83(insn_t insn, reg_t reg);
+reg_t insn_func_89(insn_t insn, reg_t reg);
+reg_t insn_func_90(insn_t insn, reg_t reg);
+reg_t insn_func_98(insn_t insn, reg_t reg);
+reg_t insn_func_99(insn_t insn, reg_t reg);
+reg_t insn_func_103(insn_t insn, reg_t reg);
+reg_t insn_func_107(insn_t insn, reg_t reg);
+reg_t insn_func_111(insn_t insn, reg_t reg);
+reg_t insn_func_114(insn_t insn, reg_t reg);
+reg_t insn_func_115(insn_t insn, reg_t reg);
+reg_t insn_func_119(insn_t insn, reg_t reg);
+reg_t insn_func_121(insn_t insn, reg_t reg);
+reg_t insn_func_122(insn_t insn, reg_t reg);
+reg_t insn_func_123(insn_t insn, reg_t reg);
+reg_t insn_func_130(insn_t insn, reg_t reg);
+reg_t insn_func_131(insn_t insn, reg_t reg);
+reg_t insn_func_139(insn_t insn, reg_t reg);
+reg_t insn_func_143(insn_t insn, reg_t reg);
+reg_t insn_func_146(insn_t insn, reg_t reg);
+reg_t insn_func_147(insn_t insn, reg_t reg);
+reg_t insn_func_153(insn_t insn, reg_t reg);
+reg_t insn_func_154(insn_t insn, reg_t reg);
+reg_t insn_func_155(insn_t insn, reg_t reg);
+reg_t insn_func_162(insn_t insn, reg_t reg);
+reg_t insn_func_163(insn_t insn, reg_t reg);
+reg_t insn_func_175(insn_t insn, reg_t reg);
+reg_t insn_func_178(insn_t insn, reg_t reg);
+reg_t insn_func_179(insn_t insn, reg_t reg);
+reg_t insn_func_185(insn_t insn, reg_t reg);
+reg_t insn_func_186(insn_t insn, reg_t reg);
+reg_t insn_func_187(insn_t insn, reg_t reg);
+reg_t insn_func_194(insn_t insn, reg_t reg);
+reg_t insn_func_195(insn_t insn, reg_t reg);
+reg_t insn_func_199(insn_t insn, reg_t reg);
+reg_t insn_func_203(insn_t insn, reg_t reg);
+reg_t insn_func_207(insn_t insn, reg_t reg);
+reg_t insn_func_210(insn_t insn, reg_t reg);
+reg_t insn_func_211(insn_t insn, reg_t reg);
+reg_t insn_func_217(insn_t insn, reg_t reg);
+reg_t insn_func_218(insn_t insn, reg_t reg);
+reg_t insn_func_226(insn_t insn, reg_t reg);
+reg_t insn_func_227(insn_t insn, reg_t reg);
+reg_t insn_func_235(insn_t insn, reg_t reg);
+reg_t insn_func_242(insn_t insn, reg_t reg);
+reg_t insn_func_243(insn_t insn, reg_t reg);
+reg_t insn_func_247(insn_t insn, reg_t reg);
+reg_t insn_func_249(insn_t insn, reg_t reg);
+reg_t insn_func_250(insn_t insn, reg_t reg);
+reg_t insn_func_251(insn_t insn, reg_t reg);
+reg_t insn_func_258(insn_t insn, reg_t reg);
+reg_t insn_func_259(insn_t insn, reg_t reg);
+reg_t insn_func_263(insn_t insn, reg_t reg);
+reg_t insn_func_267(insn_t insn, reg_t reg);
+reg_t insn_func_271(insn_t insn, reg_t reg);
+reg_t insn_func_274(insn_t insn, reg_t reg);
+reg_t insn_func_275(insn_t insn, reg_t reg);
+reg_t insn_func_281(insn_t insn, reg_t reg);
+reg_t insn_func_282(insn_t insn, reg_t reg);
+reg_t insn_func_284(insn_t insn, reg_t reg);
+reg_t insn_func_290(insn_t insn, reg_t reg);
+reg_t insn_func_291(insn_t insn, reg_t reg);
+reg_t insn_func_295(insn_t insn, reg_t reg);
+reg_t insn_func_299(insn_t insn, reg_t reg);
+reg_t insn_func_303(insn_t insn, reg_t reg);
+reg_t insn_func_306(insn_t insn, reg_t reg);
+reg_t insn_func_307(insn_t insn, reg_t reg);
+reg_t insn_func_313(insn_t insn, reg_t reg);
+reg_t insn_func_314(insn_t insn, reg_t reg);
+reg_t insn_func_322(insn_t insn, reg_t reg);
+reg_t insn_func_338(insn_t insn, reg_t reg);
+reg_t insn_func_345(insn_t insn, reg_t reg);
+reg_t insn_func_346(insn_t insn, reg_t reg);
+reg_t insn_func_354(insn_t insn, reg_t reg);
+reg_t insn_func_363(insn_t insn, reg_t reg);
+reg_t insn_func_370(insn_t insn, reg_t reg);
+reg_t insn_func_371(insn_t insn, reg_t reg);
+reg_t insn_func_375(insn_t insn, reg_t reg);
+reg_t insn_func_377(insn_t insn, reg_t reg);
+reg_t insn_func_378(insn_t insn, reg_t reg);
+reg_t insn_func_379(insn_t insn, reg_t reg);
+reg_t insn_func_386(insn_t insn, reg_t reg);
+reg_t insn_func_387(insn_t insn, reg_t reg);
+reg_t insn_func_391(insn_t insn, reg_t reg);
+reg_t insn_func_395(insn_t insn, reg_t reg);
+reg_t insn_func_399(insn_t insn, reg_t reg);
+reg_t insn_func_402(insn_t insn, reg_t reg);
+reg_t insn_func_403(insn_t insn, reg_t reg);
+reg_t insn_func_409(insn_t insn, reg_t reg);
+reg_t insn_func_410(insn_t insn, reg_t reg);
+reg_t insn_func_418(insn_t insn, reg_t reg);
+reg_t insn_func_419(insn_t insn, reg_t reg);
+reg_t insn_func_423(insn_t insn, reg_t reg);
+reg_t insn_func_427(insn_t insn, reg_t reg);
+reg_t insn_func_434(insn_t insn, reg_t reg);
+reg_t insn_func_435(insn_t insn, reg_t reg);
+reg_t insn_func_441(insn_t insn, reg_t reg);
+reg_t insn_func_442(insn_t insn, reg_t reg);
+reg_t insn_func_450(insn_t insn, reg_t reg);
+reg_t insn_func_466(insn_t insn, reg_t reg);
+reg_t insn_func_473(insn_t insn, reg_t reg);
+reg_t insn_func_474(insn_t insn, reg_t reg);
+reg_t insn_func_482(insn_t insn, reg_t reg);
+reg_t insn_func_498(insn_t insn, reg_t reg);
+reg_t insn_func_499(insn_t insn, reg_t reg);
+reg_t insn_func_503(insn_t insn, reg_t reg);
+reg_t insn_func_505(insn_t insn, reg_t reg);
+reg_t insn_func_506(insn_t insn, reg_t reg);
+reg_t insn_func_507(insn_t insn, reg_t reg);
+reg_t insn_func_514(insn_t insn, reg_t reg);
+reg_t insn_func_515(insn_t insn, reg_t reg);
+reg_t insn_func_523(insn_t insn, reg_t reg);
+reg_t insn_func_530(insn_t insn, reg_t reg);
+reg_t insn_func_531(insn_t insn, reg_t reg);
+reg_t insn_func_537(insn_t insn, reg_t reg);
+reg_t insn_func_538(insn_t insn, reg_t reg);
+reg_t insn_func_540(insn_t insn, reg_t reg);
+reg_t insn_func_546(insn_t insn, reg_t reg);
+reg_t insn_func_559(insn_t insn, reg_t reg);
+reg_t insn_func_562(insn_t insn, reg_t reg);
+reg_t insn_func_563(insn_t insn, reg_t reg);
+reg_t insn_func_569(insn_t insn, reg_t reg);
+reg_t insn_func_570(insn_t insn, reg_t reg);
+reg_t insn_func_571(insn_t insn, reg_t reg);
+reg_t insn_func_578(insn_t insn, reg_t reg);
+reg_t insn_func_594(insn_t insn, reg_t reg);
+reg_t insn_func_595(insn_t insn, reg_t reg);
+reg_t insn_func_601(insn_t insn, reg_t reg);
+reg_t insn_func_602(insn_t insn, reg_t reg);
+reg_t insn_func_610(insn_t insn, reg_t reg);
+reg_t insn_func_611(insn_t insn, reg_t reg);
+reg_t insn_func_619(insn_t insn, reg_t reg);
+reg_t insn_func_626(insn_t insn, reg_t reg);
+reg_t insn_func_631(insn_t insn, reg_t reg);
+reg_t insn_func_633(insn_t insn, reg_t reg);
+reg_t insn_func_634(insn_t insn, reg_t reg);
+reg_t insn_func_635(insn_t insn, reg_t reg);
+reg_t insn_func_642(insn_t insn, reg_t reg);
+reg_t insn_func_643(insn_t insn, reg_t reg);
+reg_t insn_func_651(insn_t insn, reg_t reg);
+reg_t insn_func_658(insn_t insn, reg_t reg);
+reg_t insn_func_659(insn_t insn, reg_t reg);
+reg_t insn_func_665(insn_t insn, reg_t reg);
+reg_t insn_func_666(insn_t insn, reg_t reg);
+reg_t insn_func_667(insn_t insn, reg_t reg);
+reg_t insn_func_674(insn_t insn, reg_t reg);
+reg_t insn_func_687(insn_t insn, reg_t reg);
+reg_t insn_func_690(insn_t insn, reg_t reg);
+reg_t insn_func_691(insn_t insn, reg_t reg);
+reg_t insn_func_697(insn_t insn, reg_t reg);
+reg_t insn_func_698(insn_t insn, reg_t reg);
+reg_t insn_func_699(insn_t insn, reg_t reg);
+reg_t insn_func_706(insn_t insn, reg_t reg);
+reg_t insn_func_722(insn_t insn, reg_t reg);
+reg_t insn_func_723(insn_t insn, reg_t reg);
+reg_t insn_func_729(insn_t insn, reg_t reg);
+reg_t insn_func_730(insn_t insn, reg_t reg);
+reg_t insn_func_738(insn_t insn, reg_t reg);
+reg_t insn_func_739(insn_t insn, reg_t reg);
+reg_t insn_func_754(insn_t insn, reg_t reg);
+reg_t insn_func_755(insn_t insn, reg_t reg);
+reg_t insn_func_759(insn_t insn, reg_t reg);
+reg_t insn_func_761(insn_t insn, reg_t reg);
+reg_t insn_func_762(insn_t insn, reg_t reg);
+reg_t insn_func_763(insn_t insn, reg_t reg);
+reg_t insn_func_770(insn_t insn, reg_t reg);
+reg_t insn_func_771(insn_t insn, reg_t reg);
+reg_t insn_func_779(insn_t insn, reg_t reg);
+reg_t insn_func_786(insn_t insn, reg_t reg);
+reg_t insn_func_787(insn_t insn, reg_t reg);
+reg_t insn_func_793(insn_t insn, reg_t reg);
+reg_t insn_func_794(insn_t insn, reg_t reg);
+reg_t insn_func_796(insn_t insn, reg_t reg);
+reg_t insn_func_802(insn_t insn, reg_t reg);
+reg_t insn_func_815(insn_t insn, reg_t reg);
+reg_t insn_func_818(insn_t insn, reg_t reg);
+reg_t insn_func_819(insn_t insn, reg_t reg);
+reg_t insn_func_825(insn_t insn, reg_t reg);
+reg_t insn_func_826(insn_t insn, reg_t reg);
+reg_t insn_func_827(insn_t insn, reg_t reg);
+reg_t insn_func_834(insn_t insn, reg_t reg);
+reg_t insn_func_850(insn_t insn, reg_t reg);
+reg_t insn_func_857(insn_t insn, reg_t reg);
+reg_t insn_func_858(insn_t insn, reg_t reg);
+reg_t insn_func_866(insn_t insn, reg_t reg);
+reg_t insn_func_867(insn_t insn, reg_t reg);
+reg_t insn_func_882(insn_t insn, reg_t reg);
+reg_t insn_func_889(insn_t insn, reg_t reg);
+reg_t insn_func_890(insn_t insn, reg_t reg);
+reg_t insn_func_898(insn_t insn, reg_t reg);
+reg_t insn_func_914(insn_t insn, reg_t reg);
+reg_t insn_func_915(insn_t insn, reg_t reg);
+reg_t insn_func_921(insn_t insn, reg_t reg);
+reg_t insn_func_922(insn_t insn, reg_t reg);
+reg_t insn_func_930(insn_t insn, reg_t reg);
+reg_t insn_func_943(insn_t insn, reg_t reg);
+reg_t insn_func_946(insn_t insn, reg_t reg);
+reg_t insn_func_947(insn_t insn, reg_t reg);
+reg_t insn_func_953(insn_t insn, reg_t reg);
+reg_t insn_func_954(insn_t insn, reg_t reg);
+reg_t insn_func_955(insn_t insn, reg_t reg);
+reg_t insn_func_962(insn_t insn, reg_t reg);
+reg_t insn_func_978(insn_t insn, reg_t reg);
+reg_t insn_func_985(insn_t insn, reg_t reg);
+reg_t insn_func_986(insn_t insn, reg_t reg);
+reg_t insn_func_994(insn_t insn, reg_t reg);
+reg_t insn_func_995(insn_t insn, reg_t reg);
+reg_t insn_func_1010(insn_t insn, reg_t reg);
+reg_t insn_func_1011(insn_t insn, reg_t reg);
+reg_t insn_func_1017(insn_t insn, reg_t reg);
+reg_t insn_func_1018(insn_t insn, reg_t reg);
diff --git a/riscv/htif.cc b/riscv/htif.cc
new file mode 100644
index 0000000..02809d0
--- /dev/null
+++ b/riscv/htif.cc
@@ -0,0 +1,143 @@
+#include "htif.h"
+#include "common.h"
+#include "sim.h"
+#include <unistd.h>
+#include <stdexcept>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+enum
+{
+ APP_CMD_READ_MEM,
+ APP_CMD_WRITE_MEM,
+ APP_CMD_READ_CONTROL_REG,
+ APP_CMD_WRITE_CONTROL_REG,
+ APP_CMD_START,
+ APP_CMD_STOP,
+ APP_CMD_ACK,
+ APP_CMD_NACK
+};
+
+#define APP_DATA_ALIGN 8
+#define APP_MAX_DATA_SIZE 1024
+struct packet
+{
+ uint16_t cmd;
+ uint16_t seqno;
+ uint32_t data_size;
+ uint64_t addr;
+ uint8_t data[APP_MAX_DATA_SIZE];
+};
+
+htif_t::htif_t(int _tohost_fd, int _fromhost_fd)
+ : sim(NULL), tohost_fd(_tohost_fd), fromhost_fd(_fromhost_fd), seqno(1)
+{
+}
+
+htif_t::~htif_t()
+{
+ close(tohost_fd);
+ close(fromhost_fd);
+}
+
+void htif_t::init(sim_t* _sim)
+{
+ sim = _sim;
+}
+
+void htif_t::wait_for_start()
+{
+ while(wait_for_packet() != APP_CMD_START);
+}
+
+void htif_t::wait_for_fromhost_write()
+{
+ while(wait_for_packet() != APP_CMD_WRITE_CONTROL_REG);
+}
+
+void htif_t::send_packet(packet* p)
+{
+ int bytes = write(tohost_fd,p,offsetof(packet,data)+p->data_size);
+ if((size_t)bytes != offsetof(packet,data) + p->data_size)
+ {
+ const char* error = bytes == -1 ? strerror(errno) : "not all bytes sent";
+ fprintf(stderr,"HTIF error: %s\n", error);
+ exit(-1);
+ }
+}
+
+void htif_t::nack(uint16_t nack_seqno)
+{
+ packet p = {APP_CMD_NACK,nack_seqno,0,0};
+ send_packet(&p);
+}
+
+int htif_t::wait_for_packet()
+{
+ while(1)
+ {
+ packet p;
+ int bytes = read(fromhost_fd,&p,sizeof(p));
+ if(bytes < (int)offsetof(packet,data))
+ {
+ const char* error = bytes == -1 ? strerror(errno) : "too few bytes read";
+ fprintf(stderr,"HTIF error: %s\n", error);
+ exit(-1);
+ }
+
+ if(p.seqno != seqno)
+ {
+ nack(p.seqno);
+ continue;
+ }
+
+ packet ackpacket = {APP_CMD_ACK,seqno,0,0};
+
+ switch(p.cmd)
+ {
+ case APP_CMD_START:
+ break;
+ case APP_CMD_STOP:
+ sim->stop();
+ break;
+ case APP_CMD_READ_MEM:
+ assert(p.addr % APP_DATA_ALIGN == 0);
+ assert(p.data_size % APP_DATA_ALIGN == 0);
+ assert(p.data_size <= APP_MAX_DATA_SIZE);
+ assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz);
+ ackpacket.data_size = p.data_size;
+
+ static_assert(APP_DATA_ALIGN >= sizeof(uint64_t))
+ for(size_t i = 0; i < p.data_size/8; i++)
+ ((uint64_t*)ackpacket.data)[i] = sim->mmu->load_uint64(p.addr+i*8);
+ break;
+ case APP_CMD_WRITE_MEM:
+ assert(p.addr % APP_DATA_ALIGN == 0);
+ assert(p.data_size % APP_DATA_ALIGN == 0);
+ assert(p.data_size <= bytes - offsetof(packet,data));
+ assert(p.addr <= sim->memsz && p.addr+p.data_size <= sim->memsz);
+
+ for(size_t i = 0; i < p.data_size/8; i++)
+ sim->mmu->store_uint64(p.addr+i*8, ((uint64_t*)p.data)[i]);
+ break;
+ case APP_CMD_READ_CONTROL_REG:
+ assert(p.addr == 16);
+ assert(p.data_size == sizeof(reg_t));
+ ackpacket.data_size = sizeof(reg_t);
+ memcpy(ackpacket.data,&sim->tohost,sizeof(reg_t));
+ break;
+ case APP_CMD_WRITE_CONTROL_REG:
+ assert(p.addr == 17);
+ assert(p.data_size == sizeof(reg_t));
+ sim->tohost = 0;
+ memcpy(&sim->fromhost,p.data,sizeof(reg_t));
+ break;
+ }
+
+ send_packet(&ackpacket);
+ seqno++;
+ return p.cmd;
+ }
+}
+
diff --git a/riscv/htif.h b/riscv/htif.h
new file mode 100644
index 0000000..0106695
--- /dev/null
+++ b/riscv/htif.h
@@ -0,0 +1,35 @@
+#ifndef _HTIF_H
+#define _HTIF_H
+
+#include <stdint.h>
+
+class sim_t;
+struct packet;
+
+// this class implements the host-target interface for program loading, etc.
+class htif_t
+{
+public:
+ htif_t(int _tohost_fd, int _fromhost_fd);
+ ~htif_t();
+ void init(sim_t* _sim);
+
+ // wait for host to send start command
+ void wait_for_start();
+
+ // we block on the host if the target machine reads the fromhost register,
+ // which provides determinism in tohost/fromhost communication.
+ void wait_for_fromhost_write();
+
+private:
+ sim_t* sim;
+ int tohost_fd;
+ int fromhost_fd;
+ uint16_t seqno;
+
+ void nack(uint16_t seqno);
+ void send_packet(packet* p);
+ int wait_for_packet();
+};
+
+#endif
diff --git a/riscv/icsim.cc b/riscv/icsim.cc
new file mode 100644
index 0000000..308e7ed
--- /dev/null
+++ b/riscv/icsim.cc
@@ -0,0 +1,100 @@
+#include "icsim.h"
+#include <stdexcept>
+#include <iostream>
+#include <iomanip>
+
+icsim_t::icsim_t(size_t _sets, size_t _ways, size_t _linesz, const char* _name)
+ : sets(_sets), ways(_ways), linesz(_linesz), idx_mask(_sets-1), name(_name)
+{
+ if(sets == 0 || (sets & (sets-1)))
+ throw std::logic_error("sets not a power of 2");
+ if(linesz == 0 || (linesz & (linesz-1)))
+ throw std::logic_error("linesz not a power of 2");
+
+ idx_shift = 0;
+ while(_linesz >>= 1)
+ idx_shift++;
+
+ tags = new uint64_t[sets*ways];
+ memset(tags, 0, sets*ways*sizeof(uint64_t));
+
+ read_accesses = 0;
+ read_misses = 0;
+ bytes_read = 0;
+ write_accesses = 0;
+ write_misses = 0;
+ bytes_written = 0;
+ writebacks = 0;
+}
+
+icsim_t::icsim_t(const icsim_t& rhs)
+ : sets(rhs.sets), ways(rhs.ways), linesz(rhs.linesz),
+ idx_shift(rhs.idx_shift), idx_mask(rhs.idx_mask), name(rhs.name)
+{
+ tags = new uint64_t[sets*ways];
+ memcpy(tags, rhs.tags, sets*ways*sizeof(uint64_t));
+}
+
+icsim_t::~icsim_t()
+{
+ delete [] tags;
+}
+
+void icsim_t::print_stats()
+{
+ if(read_accesses + write_accesses == 0)
+ return;
+
+ float mr = 100.0f*(read_misses+write_misses)/(read_accesses+write_accesses);
+
+ std::cout << std::setprecision(3) << std::fixed;
+ std::cout << name << " ";
+ std::cout << "Bytes Read: " << bytes_read << std::endl;
+ std::cout << name << " ";
+ std::cout << "Bytes Written: " << bytes_written << std::endl;
+ std::cout << name << " ";
+ std::cout << "Read Accesses: " << read_accesses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Write Accesses: " << write_accesses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Read Misses: " << read_misses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Write Misses: " << write_misses << std::endl;
+ std::cout << name << " ";
+ std::cout << "Writebacks: " << writebacks << std::endl;
+ std::cout << name << " ";
+ std::cout << "Miss Rate: " << mr << '%' << std::endl;
+
+ float cr = read_accesses == 0 ? 0.0f : 100.0f*bytes_read/(4*read_accesses);
+ if(name == "I$")
+ {
+ std::cout << name << " ";
+ std::cout << "RVC compression ratio: " << cr << '%' << std::endl;
+ }
+}
+
+void icsim_t::tick(uint64_t pc, int insnlen, bool store)
+{
+ store ? write_accesses++ : read_accesses++;
+ (store ? bytes_written : bytes_read) += insnlen;
+
+ size_t idx = (pc >> idx_shift) & idx_mask;
+ size_t tag = (pc >> idx_shift) | VALID;
+
+ for(size_t i = 0; i < ways; i++)
+ {
+ if(tag == (tags[idx + i*sets] & ~DIRTY)) // hit
+ {
+ if(store)
+ tags[idx + i*sets] |= DIRTY;
+ return;
+ }
+ }
+
+ store ? write_misses++ : read_misses++;
+
+ size_t way = lfsr.next() % ways;
+ if((tags[idx + way*sets] & (VALID | DIRTY)) == (VALID | DIRTY))
+ writebacks++;
+ tags[idx + way*sets] = tag;
+}
diff --git a/riscv/icsim.h b/riscv/icsim.h
new file mode 100644
index 0000000..ec6eae4
--- /dev/null
+++ b/riscv/icsim.h
@@ -0,0 +1,55 @@
+#ifndef _RISCV_ICSIM_H
+#define _RISCV_ICSIM_H
+
+// this file models a simple cache to estimate hit/miss rates.
+// it is currently unused.
+
+#include <cstring>
+#include <string>
+#include <stdint.h>
+
+class lfsr_t
+{
+public:
+ lfsr_t() : reg(1) {}
+ lfsr_t(const lfsr_t& lfsr) : reg(lfsr.reg) {}
+ uint32_t next() { return reg = (reg>>1)^(-(reg&1) & 0xd0000001); }
+private:
+ uint32_t reg;
+};
+
+class icsim_t
+{
+public:
+ icsim_t(size_t sets, size_t ways, size_t linesz, const char* name);
+ icsim_t(const icsim_t& rhs);
+ ~icsim_t();
+
+ void tick(uint64_t pc, int insnlen, bool store);
+ void print_stats();
+private:
+ lfsr_t lfsr;
+
+ size_t sets;
+ size_t ways;
+ size_t linesz;
+ size_t idx_shift;
+ size_t idx_mask;
+
+ uint64_t* tags;
+
+ uint64_t read_accesses;
+ uint64_t read_misses;
+ uint64_t bytes_read;
+ uint64_t write_accesses;
+ uint64_t write_misses;
+ uint64_t bytes_written;
+ uint64_t writebacks;
+
+ std::string name;
+
+ static const uint64_t VALID = 1ULL << 63;
+ static const uint64_t DIRTY = 1ULL << 62;
+};
+
+#endif
diff --git a/riscv/insn_header.h b/riscv/insn_header.h
new file mode 100644
index 0000000..9ea3586
--- /dev/null
+++ b/riscv/insn_header.h
@@ -0,0 +1,7 @@
+#include "processor.h"
+#include "config.h"
+#include "sim.h"
+#include "softfloat.h"
+#include "platform.h" // softfloat isNaNF32UI, etc.
+#include "internals.h" // ditto
+#include <assert.h>
diff --git a/riscv/insns/add.h b/riscv/insns/add.h
new file mode 100644
index 0000000..34d49ff
--- /dev/null
+++ b/riscv/insns/add.h
@@ -0,0 +1 @@
+RD = sext_xprlen(RS1 + RS2);
diff --git a/riscv/insns/addi.h b/riscv/insns/addi.h
new file mode 100644
index 0000000..88881e5
--- /dev/null
+++ b/riscv/insns/addi.h
@@ -0,0 +1 @@
+RD = sext_xprlen(RS1 + SIMM);
diff --git a/riscv/insns/addiw.h b/riscv/insns/addiw.h
new file mode 100644
index 0000000..23ae278
--- /dev/null
+++ b/riscv/insns/addiw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(SIMM + RS1);
diff --git a/riscv/insns/addw.h b/riscv/insns/addw.h
new file mode 100644
index 0000000..4e2ed56
--- /dev/null
+++ b/riscv/insns/addw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(RS1 + RS2);
diff --git a/riscv/insns/amoadd_d.h b/riscv/insns/amoadd_d.h
new file mode 100644
index 0000000..b8450bf
--- /dev/null
+++ b/riscv/insns/amoadd_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+reg_t v = mmu.load_uint64(RS1);
+mmu.store_uint64(RS1, RS2 + v);
+RD = v;
diff --git a/riscv/insns/amoadd_w.h b/riscv/insns/amoadd_w.h
new file mode 100644
index 0000000..033b3c8
--- /dev/null
+++ b/riscv/insns/amoadd_w.h
@@ -0,0 +1,3 @@
+reg_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, RS2 + v);
+RD = v;
diff --git a/riscv/insns/amoand_d.h b/riscv/insns/amoand_d.h
new file mode 100644
index 0000000..586eb7f
--- /dev/null
+++ b/riscv/insns/amoand_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+reg_t v = mmu.load_uint64(RS1);
+mmu.store_uint64(RS1, RS2 & v);
+RD = v;
diff --git a/riscv/insns/amoand_w.h b/riscv/insns/amoand_w.h
new file mode 100644
index 0000000..18a9249
--- /dev/null
+++ b/riscv/insns/amoand_w.h
@@ -0,0 +1,3 @@
+reg_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, RS2 & v);
+RD = v;
diff --git a/riscv/insns/amomax_d.h b/riscv/insns/amomax_d.h
new file mode 100644
index 0000000..1a0bc8a
--- /dev/null
+++ b/riscv/insns/amomax_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+sreg_t v = mmu.load_int64(RS1);
+mmu.store_uint64(RS1, std::max(sreg_t(RS2),v));
+RD = v;
diff --git a/riscv/insns/amomax_w.h b/riscv/insns/amomax_w.h
new file mode 100644
index 0000000..ff9c2da
--- /dev/null
+++ b/riscv/insns/amomax_w.h
@@ -0,0 +1,3 @@
+int32_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, std::max(int32_t(RS2),v));
+RD = v;
diff --git a/riscv/insns/amomaxu_d.h b/riscv/insns/amomaxu_d.h
new file mode 100644
index 0000000..ccfaf1d
--- /dev/null
+++ b/riscv/insns/amomaxu_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+reg_t v = mmu.load_uint64(RS1);
+mmu.store_uint64(RS1, std::max(RS2,v));
+RD = v;
diff --git a/riscv/insns/amomaxu_w.h b/riscv/insns/amomaxu_w.h
new file mode 100644
index 0000000..075847d
--- /dev/null
+++ b/riscv/insns/amomaxu_w.h
@@ -0,0 +1,3 @@
+uint32_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, std::max(uint32_t(RS2),v));
+RD = (int32_t)v;
diff --git a/riscv/insns/amomin_d.h b/riscv/insns/amomin_d.h
new file mode 100644
index 0000000..4f3b6d6
--- /dev/null
+++ b/riscv/insns/amomin_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+sreg_t v = mmu.load_int64(RS1);
+mmu.store_uint64(RS1, std::min(sreg_t(RS2),v));
+RD = v;
diff --git a/riscv/insns/amomin_w.h b/riscv/insns/amomin_w.h
new file mode 100644
index 0000000..529ad50
--- /dev/null
+++ b/riscv/insns/amomin_w.h
@@ -0,0 +1,3 @@
+int32_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, std::min(int32_t(RS2),v));
+RD = v;
diff --git a/riscv/insns/amominu_d.h b/riscv/insns/amominu_d.h
new file mode 100644
index 0000000..c09c51a
--- /dev/null
+++ b/riscv/insns/amominu_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+reg_t v = mmu.load_uint64(RS1);
+mmu.store_uint64(RS1, std::min(RS2,v));
+RD = v;
diff --git a/riscv/insns/amominu_w.h b/riscv/insns/amominu_w.h
new file mode 100644
index 0000000..d8d6377
--- /dev/null
+++ b/riscv/insns/amominu_w.h
@@ -0,0 +1,3 @@
+uint32_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, std::min(uint32_t(RS2),v));
+RD = (int32_t)v;
diff --git a/riscv/insns/amoor_d.h b/riscv/insns/amoor_d.h
new file mode 100644
index 0000000..76a4508
--- /dev/null
+++ b/riscv/insns/amoor_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+reg_t v = mmu.load_uint64(RS1);
+mmu.store_uint64(RS1, RS2 | v);
+RD = v;
diff --git a/riscv/insns/amoor_w.h b/riscv/insns/amoor_w.h
new file mode 100644
index 0000000..741fbef
--- /dev/null
+++ b/riscv/insns/amoor_w.h
@@ -0,0 +1,3 @@
+reg_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, RS2 | v);
+RD = v;
diff --git a/riscv/insns/amoswap_d.h b/riscv/insns/amoswap_d.h
new file mode 100644
index 0000000..43e3538
--- /dev/null
+++ b/riscv/insns/amoswap_d.h
@@ -0,0 +1,4 @@
+require_xpr64;
+reg_t v = mmu.load_uint64(RS1);
+mmu.store_uint64(RS1, RS2);
+RD = v;
diff --git a/riscv/insns/amoswap_w.h b/riscv/insns/amoswap_w.h
new file mode 100644
index 0000000..30e6102
--- /dev/null
+++ b/riscv/insns/amoswap_w.h
@@ -0,0 +1,3 @@
+reg_t v = mmu.load_int32(RS1);
+mmu.store_uint32(RS1, RS2);
+RD = v;
diff --git a/riscv/insns/and.h b/riscv/insns/and.h
new file mode 100644
index 0000000..88ac1d8
--- /dev/null
+++ b/riscv/insns/and.h
@@ -0,0 +1 @@
+RD = RS1 & RS2;
diff --git a/riscv/insns/andi.h b/riscv/insns/andi.h
new file mode 100644
index 0000000..5caea16
--- /dev/null
+++ b/riscv/insns/andi.h
@@ -0,0 +1 @@
+RD = SIMM & RS1;
diff --git a/riscv/insns/beq.h b/riscv/insns/beq.h
new file mode 100644
index 0000000..7b26488
--- /dev/null
+++ b/riscv/insns/beq.h
@@ -0,0 +1,2 @@
+if(cmp_trunc(RS1) == cmp_trunc(RS2))
+ set_pc(BRANCH_TARGET);
diff --git a/riscv/insns/bge.h b/riscv/insns/bge.h
new file mode 100644
index 0000000..dca544b
--- /dev/null
+++ b/riscv/insns/bge.h
@@ -0,0 +1,2 @@
+if(sreg_t(cmp_trunc(RS1)) >= sreg_t(cmp_trunc(RS2)))
+ set_pc(BRANCH_TARGET);
diff --git a/riscv/insns/bgeu.h b/riscv/insns/bgeu.h
new file mode 100644
index 0000000..6325466
--- /dev/null
+++ b/riscv/insns/bgeu.h
@@ -0,0 +1,2 @@
+if(cmp_trunc(RS1) >= cmp_trunc(RS2))
+ set_pc(BRANCH_TARGET);
diff --git a/riscv/insns/blt.h b/riscv/insns/blt.h
new file mode 100644
index 0000000..d84fd7a
--- /dev/null
+++ b/riscv/insns/blt.h
@@ -0,0 +1,2 @@
+if(sreg_t(cmp_trunc(RS1)) < sreg_t(cmp_trunc(RS2)))
+ set_pc(BRANCH_TARGET);
diff --git a/riscv/insns/bltu.h b/riscv/insns/bltu.h
new file mode 100644
index 0000000..250fd4f
--- /dev/null
+++ b/riscv/insns/bltu.h
@@ -0,0 +1,2 @@
+if(cmp_trunc(RS1) < cmp_trunc(RS2))
+ set_pc(BRANCH_TARGET);
diff --git a/riscv/insns/bne.h b/riscv/insns/bne.h
new file mode 100644
index 0000000..f775721
--- /dev/null
+++ b/riscv/insns/bne.h
@@ -0,0 +1,2 @@
+if(cmp_trunc(RS1) != cmp_trunc(RS2))
+ set_pc(BRANCH_TARGET);
diff --git a/riscv/insns/break.h b/riscv/insns/break.h
new file mode 100644
index 0000000..7fd3d66
--- /dev/null
+++ b/riscv/insns/break.h
@@ -0,0 +1 @@
+throw trap_breakpoint;
diff --git a/riscv/insns/c_add.h b/riscv/insns/c_add.h
new file mode 100644
index 0000000..2170d69
--- /dev/null
+++ b/riscv/insns/c_add.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRD = CRS1 + CRS2;
diff --git a/riscv/insns/c_add3.h b/riscv/insns/c_add3.h
new file mode 100644
index 0000000..914c85d
--- /dev/null
+++ b/riscv/insns/c_add3.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRDS = CRS1S + CRS2BS;
diff --git a/riscv/insns/c_addi.h b/riscv/insns/c_addi.h
new file mode 100644
index 0000000..448e31a
--- /dev/null
+++ b/riscv/insns/c_addi.h
@@ -0,0 +1,10 @@
+require_rvc;
+if(CRD_REGNUM == 0)
+{
+ reg_t temp = CRS1;
+ if(CIMM6 & 0x20)
+ RA = npc;
+ set_pc(temp);
+}
+else
+ CRD = sext_xprlen(CRS2 + CIMM6);
diff --git a/riscv/insns/c_addiw.h b/riscv/insns/c_addiw.h
new file mode 100644
index 0000000..6a1e0a3
--- /dev/null
+++ b/riscv/insns/c_addiw.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRD = sext32(CRS2 + CIMM6);
diff --git a/riscv/insns/c_and3.h b/riscv/insns/c_and3.h
new file mode 100644
index 0000000..b506d6a
--- /dev/null
+++ b/riscv/insns/c_and3.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRDS = CRS1S & CRS2BS;
diff --git a/riscv/insns/c_beq.h b/riscv/insns/c_beq.h
new file mode 100644
index 0000000..031d96d
--- /dev/null
+++ b/riscv/insns/c_beq.h
@@ -0,0 +1,3 @@
+require_rvc;
+if(cmp_trunc(CRS1S) == cmp_trunc(CRS2S))
+ set_pc(CBRANCH_TARGET);
diff --git a/riscv/insns/c_bne.h b/riscv/insns/c_bne.h
new file mode 100644
index 0000000..caf9229
--- /dev/null
+++ b/riscv/insns/c_bne.h
@@ -0,0 +1,3 @@
+require_rvc;
+if(cmp_trunc(CRS1S) != cmp_trunc(CRS2S))
+ set_pc(CBRANCH_TARGET);
diff --git a/riscv/insns/c_fld.h b/riscv/insns/c_fld.h
new file mode 100644
index 0000000..a726039
--- /dev/null
+++ b/riscv/insns/c_fld.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_fp;
+FCRDS = mmu.load_int64(CRS1S+CIMM5*8);
diff --git a/riscv/insns/c_flw.h b/riscv/insns/c_flw.h
new file mode 100644
index 0000000..cdb7221
--- /dev/null
+++ b/riscv/insns/c_flw.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_fp;
+FCRDS = mmu.load_int32(CRS1S+CIMM5*4);
diff --git a/riscv/insns/c_fsd.h b/riscv/insns/c_fsd.h
new file mode 100644
index 0000000..20814fd
--- /dev/null
+++ b/riscv/insns/c_fsd.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_fp;
+mmu.store_uint64(CRS1S+CIMM5*8, FCRS2S);
diff --git a/riscv/insns/c_fsw.h b/riscv/insns/c_fsw.h
new file mode 100644
index 0000000..1d21629
--- /dev/null
+++ b/riscv/insns/c_fsw.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_fp;
+mmu.store_uint32(CRS1S+CIMM5*4, FCRS2S);
diff --git a/riscv/insns/c_j.h b/riscv/insns/c_j.h
new file mode 100644
index 0000000..5ba9c73
--- /dev/null
+++ b/riscv/insns/c_j.h
@@ -0,0 +1,2 @@
+require_rvc;
+set_pc(CJUMP_TARGET);
diff --git a/riscv/insns/c_ld.h b/riscv/insns/c_ld.h
new file mode 100644
index 0000000..f9c07af
--- /dev/null
+++ b/riscv/insns/c_ld.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRDS = mmu.load_int64(CRS1S+CIMM5*8);
diff --git a/riscv/insns/c_ld0.h b/riscv/insns/c_ld0.h
new file mode 100644
index 0000000..f51a966
--- /dev/null
+++ b/riscv/insns/c_ld0.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRD = mmu.load_int64(CRS1);
diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h
new file mode 100644
index 0000000..1fbd9bd
--- /dev/null
+++ b/riscv/insns/c_ldsp.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRD = mmu.load_int64(XPR[30]+CIMM6*8);
diff --git a/riscv/insns/c_li.h b/riscv/insns/c_li.h
new file mode 100644
index 0000000..e65614e
--- /dev/null
+++ b/riscv/insns/c_li.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRD = CIMM6;
diff --git a/riscv/insns/c_lw.h b/riscv/insns/c_lw.h
new file mode 100644
index 0000000..4796ab8
--- /dev/null
+++ b/riscv/insns/c_lw.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRDS = mmu.load_int32(CRS1S+CIMM5*4);
diff --git a/riscv/insns/c_lw0.h b/riscv/insns/c_lw0.h
new file mode 100644
index 0000000..d263a80
--- /dev/null
+++ b/riscv/insns/c_lw0.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRD = mmu.load_int32(CRS1);
diff --git a/riscv/insns/c_lwsp.h b/riscv/insns/c_lwsp.h
new file mode 100644
index 0000000..318342a
--- /dev/null
+++ b/riscv/insns/c_lwsp.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRD = mmu.load_int32(XPR[30]+CIMM6*4);
diff --git a/riscv/insns/c_move.h b/riscv/insns/c_move.h
new file mode 100644
index 0000000..b0aef33
--- /dev/null
+++ b/riscv/insns/c_move.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRD = CRS1;
diff --git a/riscv/insns/c_or3.h b/riscv/insns/c_or3.h
new file mode 100644
index 0000000..143e2ae
--- /dev/null
+++ b/riscv/insns/c_or3.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRDS = CRS1S | CRS2BS;
diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h
new file mode 100644
index 0000000..b2eb456
--- /dev/null
+++ b/riscv/insns/c_sd.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+mmu.store_uint64(CRS1S+CIMM5*8, CRS2S);
diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h
new file mode 100644
index 0000000..ca97d51
--- /dev/null
+++ b/riscv/insns/c_sdsp.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+mmu.store_uint64(XPR[30]+CIMM6*8, CRS2);
diff --git a/riscv/insns/c_slli.h b/riscv/insns/c_slli.h
new file mode 100644
index 0000000..5026767
--- /dev/null
+++ b/riscv/insns/c_slli.h
@@ -0,0 +1,5 @@
+require_rvc;
+if(xpr64)
+ CRDS = CRDS << CIMM5U;
+else
+ CRDS = sext32(CRDS << CIMM5U);
diff --git a/riscv/insns/c_slli32.h b/riscv/insns/c_slli32.h
new file mode 100644
index 0000000..1e3e958
--- /dev/null
+++ b/riscv/insns/c_slli32.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRDS = CRDS << (32+CIMM5U);
diff --git a/riscv/insns/c_slliw.h b/riscv/insns/c_slliw.h
new file mode 100644
index 0000000..9e428f5
--- /dev/null
+++ b/riscv/insns/c_slliw.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRDS = sext32(CRDS << CIMM5U);
diff --git a/riscv/insns/c_srai.h b/riscv/insns/c_srai.h
new file mode 100644
index 0000000..aa33424
--- /dev/null
+++ b/riscv/insns/c_srai.h
@@ -0,0 +1,5 @@
+require_rvc;
+if(xpr64)
+ CRDS = sreg_t(CRDS) >> CIMM5U;
+else
+ CRDS = sext32(int32_t(CRDS) >> CIMM5U);
diff --git a/riscv/insns/c_srai32.h b/riscv/insns/c_srai32.h
new file mode 100644
index 0000000..ca7b024
--- /dev/null
+++ b/riscv/insns/c_srai32.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRDS = sreg_t(CRDS) >> (32+CIMM5U);
diff --git a/riscv/insns/c_srli.h b/riscv/insns/c_srli.h
new file mode 100644
index 0000000..56e0681
--- /dev/null
+++ b/riscv/insns/c_srli.h
@@ -0,0 +1,5 @@
+require_rvc;
+if(xpr64)
+ CRDS = CRDS >> CIMM5U;
+else
+ CRDS = sext32(uint32_t(CRDS) >> CIMM5U);
diff --git a/riscv/insns/c_srli32.h b/riscv/insns/c_srli32.h
new file mode 100644
index 0000000..4f5b8ea
--- /dev/null
+++ b/riscv/insns/c_srli32.h
@@ -0,0 +1,3 @@
+require_rvc;
+require_xpr64;
+CRDS = CRDS >> (32+CIMM5U);
diff --git a/riscv/insns/c_sub.h b/riscv/insns/c_sub.h
new file mode 100644
index 0000000..9fd8932
--- /dev/null
+++ b/riscv/insns/c_sub.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRD = CRS1 - CRS2;
diff --git a/riscv/insns/c_sub3.h b/riscv/insns/c_sub3.h
new file mode 100644
index 0000000..53afc84
--- /dev/null
+++ b/riscv/insns/c_sub3.h
@@ -0,0 +1,2 @@
+require_rvc;
+CRDS = CRS1S - CRS2BS;
diff --git a/riscv/insns/c_sw.h b/riscv/insns/c_sw.h
new file mode 100644
index 0000000..f604adf
--- /dev/null
+++ b/riscv/insns/c_sw.h
@@ -0,0 +1,2 @@
+require_rvc;
+mmu.store_uint32(CRS1S+CIMM5*4, CRS2S);
diff --git a/riscv/insns/c_swsp.h b/riscv/insns/c_swsp.h
new file mode 100644
index 0000000..0508f12
--- /dev/null
+++ b/riscv/insns/c_swsp.h
@@ -0,0 +1,2 @@
+require_rvc;
+mmu.store_uint32(XPR[30]+CIMM6*4, CRS2);
diff --git a/riscv/insns/cflush.h b/riscv/insns/cflush.h
new file mode 100644
index 0000000..5117ca0
--- /dev/null
+++ b/riscv/insns/cflush.h
@@ -0,0 +1 @@
+require_supervisor;
diff --git a/riscv/insns/di.h b/riscv/insns/di.h
new file mode 100644
index 0000000..31280d5
--- /dev/null
+++ b/riscv/insns/di.h
@@ -0,0 +1,4 @@
+require_supervisor;
+uint32_t temp = sr;
+set_sr(sr & ~SR_ET);
+RD = temp;
diff --git a/riscv/insns/div.h b/riscv/insns/div.h
new file mode 100644
index 0000000..82a4066
--- /dev/null
+++ b/riscv/insns/div.h
@@ -0,0 +1,6 @@
+if(RS2 == 0)
+ RD = UINT64_MAX;
+else if(sreg_t(RS1) == INT64_MIN && sreg_t(RS2) == -1)
+ RD = RS1;
+else
+ RD = sext_xprlen(sext_xprlen(RS1) / sext_xprlen(RS2));
diff --git a/riscv/insns/divu.h b/riscv/insns/divu.h
new file mode 100644
index 0000000..681afd2
--- /dev/null
+++ b/riscv/insns/divu.h
@@ -0,0 +1,4 @@
+if(RS2 == 0)
+ RD = UINT64_MAX;
+else
+ RD = sext_xprlen(zext_xprlen(RS1) / zext_xprlen(RS2));
diff --git a/riscv/insns/divuw.h b/riscv/insns/divuw.h
new file mode 100644
index 0000000..0ceb040
--- /dev/null
+++ b/riscv/insns/divuw.h
@@ -0,0 +1,5 @@
+require_xpr64;
+if(RS2 == 0)
+ RD = UINT64_MAX;
+else
+ RD = sext32(zext32(RS1) / zext32(RS2));
diff --git a/riscv/insns/divw.h b/riscv/insns/divw.h
new file mode 100644
index 0000000..51c3d80
--- /dev/null
+++ b/riscv/insns/divw.h
@@ -0,0 +1,7 @@
+require_xpr64;
+if(RS2 == 0)
+ RD = UINT64_MAX;
+else if(int32_t(RS1) == INT32_MIN && int32_t(RS2) == -1)
+ RD = RS1;
+else
+ RD = sext32(int32_t(RS1) / int32_t(RS2));
diff --git a/riscv/insns/ei.h b/riscv/insns/ei.h
new file mode 100644
index 0000000..8306aeb
--- /dev/null
+++ b/riscv/insns/ei.h
@@ -0,0 +1,4 @@
+require_supervisor;
+uint32_t temp = sr;
+set_sr(sr | SR_ET);
+RD = temp;
diff --git a/riscv/insns/eret.h b/riscv/insns/eret.h
new file mode 100644
index 0000000..46d5bed
--- /dev/null
+++ b/riscv/insns/eret.h
@@ -0,0 +1,5 @@
+require_supervisor;
+if(sr & SR_ET)
+ throw trap_illegal_instruction;
+set_sr(((sr & SR_PS) ? sr : (sr & ~SR_S)) | SR_ET);
+set_pc(epc);
diff --git a/riscv/insns/fadd_d.h b/riscv/insns/fadd_d.h
new file mode 100644
index 0000000..48c76a7
--- /dev/null
+++ b/riscv/insns/fadd_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_add(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fadd_s.h b/riscv/insns/fadd_s.h
new file mode 100644
index 0000000..2fd5429
--- /dev/null
+++ b/riscv/insns/fadd_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_add(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_d_l.h b/riscv/insns/fcvt_d_l.h
new file mode 100644
index 0000000..68c0482
--- /dev/null
+++ b/riscv/insns/fcvt_d_l.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+FRD = i64_to_f64(RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_d_lu.h b/riscv/insns/fcvt_d_lu.h
new file mode 100644
index 0000000..2032758
--- /dev/null
+++ b/riscv/insns/fcvt_d_lu.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+FRD = ui64_to_f64(RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_d_s.h b/riscv/insns/fcvt_d_s.h
new file mode 100644
index 0000000..6b1a09c
--- /dev/null
+++ b/riscv/insns/fcvt_d_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_to_f64(FRS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_d_w.h b/riscv/insns/fcvt_d_w.h
new file mode 100644
index 0000000..52abd75
--- /dev/null
+++ b/riscv/insns/fcvt_d_w.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = i32_to_f64((int32_t)RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_d_wu.h b/riscv/insns/fcvt_d_wu.h
new file mode 100644
index 0000000..61a8a78
--- /dev/null
+++ b/riscv/insns/fcvt_d_wu.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = ui32_to_f64((uint32_t)RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_l_d.h b/riscv/insns/fcvt_l_d.h
new file mode 100644
index 0000000..206ba4f
--- /dev/null
+++ b/riscv/insns/fcvt_l_d.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+RD = f64_to_i64(FRS1, RM, true);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_l_s.h b/riscv/insns/fcvt_l_s.h
new file mode 100644
index 0000000..e05f476
--- /dev/null
+++ b/riscv/insns/fcvt_l_s.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+RD = f32_to_i64(FRS1, RM, true);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_lu_d.h b/riscv/insns/fcvt_lu_d.h
new file mode 100644
index 0000000..44c3dd6
--- /dev/null
+++ b/riscv/insns/fcvt_lu_d.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+RD = f64_to_ui64(FRS1, RM, true);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_lu_s.h b/riscv/insns/fcvt_lu_s.h
new file mode 100644
index 0000000..13de436
--- /dev/null
+++ b/riscv/insns/fcvt_lu_s.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+RD = f32_to_ui64(FRS1, RM, true);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_s_d.h b/riscv/insns/fcvt_s_d.h
new file mode 100644
index 0000000..e5289c4
--- /dev/null
+++ b/riscv/insns/fcvt_s_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_to_f32(FRS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_s_l.h b/riscv/insns/fcvt_s_l.h
new file mode 100644
index 0000000..f149229
--- /dev/null
+++ b/riscv/insns/fcvt_s_l.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+FRD = i64_to_f32(RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_s_lu.h b/riscv/insns/fcvt_s_lu.h
new file mode 100644
index 0000000..d9d0946
--- /dev/null
+++ b/riscv/insns/fcvt_s_lu.h
@@ -0,0 +1,5 @@
+require_xpr64;
+require_fp;
+softfloat_roundingMode = RM;
+FRD = ui64_to_f32(RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_s_w.h b/riscv/insns/fcvt_s_w.h
new file mode 100644
index 0000000..dedebb5
--- /dev/null
+++ b/riscv/insns/fcvt_s_w.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = i32_to_f32((int32_t)RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_s_wu.h b/riscv/insns/fcvt_s_wu.h
new file mode 100644
index 0000000..abb782c
--- /dev/null
+++ b/riscv/insns/fcvt_s_wu.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = ui32_to_f32((uint32_t)RS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_w_d.h b/riscv/insns/fcvt_w_d.h
new file mode 100644
index 0000000..88dc3d3
--- /dev/null
+++ b/riscv/insns/fcvt_w_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+RD = sext32(f64_to_i32(FRS1, RM, true));
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_w_s.h b/riscv/insns/fcvt_w_s.h
new file mode 100644
index 0000000..f14cc19
--- /dev/null
+++ b/riscv/insns/fcvt_w_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+RD = sext32(f32_to_i32(FRS1, RM, true));
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_wu_d.h b/riscv/insns/fcvt_wu_d.h
new file mode 100644
index 0000000..43ad6f6
--- /dev/null
+++ b/riscv/insns/fcvt_wu_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+RD = sext32(f64_to_ui32(FRS1, RM, true));
+set_fp_exceptions;
diff --git a/riscv/insns/fcvt_wu_s.h b/riscv/insns/fcvt_wu_s.h
new file mode 100644
index 0000000..ff7a11c
--- /dev/null
+++ b/riscv/insns/fcvt_wu_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+RD = sext32(f32_to_ui32(FRS1, RM, true));
+set_fp_exceptions;
diff --git a/riscv/insns/fdiv_d.h b/riscv/insns/fdiv_d.h
new file mode 100644
index 0000000..aa00c98
--- /dev/null
+++ b/riscv/insns/fdiv_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_div(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fdiv_s.h b/riscv/insns/fdiv_s.h
new file mode 100644
index 0000000..8c76587
--- /dev/null
+++ b/riscv/insns/fdiv_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_div(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fence.h b/riscv/insns/fence.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/fence.h
diff --git a/riscv/insns/fence_g_cv.h b/riscv/insns/fence_g_cv.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/fence_g_cv.h
diff --git a/riscv/insns/fence_g_v.h b/riscv/insns/fence_g_v.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/fence_g_v.h
diff --git a/riscv/insns/fence_i.h b/riscv/insns/fence_i.h
new file mode 100644
index 0000000..a2dbffe
--- /dev/null
+++ b/riscv/insns/fence_i.h
@@ -0,0 +1 @@
+mmu.flush_icache();
diff --git a/riscv/insns/fence_l_cv.h b/riscv/insns/fence_l_cv.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/fence_l_cv.h
diff --git a/riscv/insns/fence_l_v.h b/riscv/insns/fence_l_v.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/fence_l_v.h
diff --git a/riscv/insns/feq_d.h b/riscv/insns/feq_d.h
new file mode 100644
index 0000000..9db8760
--- /dev/null
+++ b/riscv/insns/feq_d.h
@@ -0,0 +1,3 @@
+require_fp;
+RD = f64_eq(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/feq_s.h b/riscv/insns/feq_s.h
new file mode 100644
index 0000000..658e8f6
--- /dev/null
+++ b/riscv/insns/feq_s.h
@@ -0,0 +1,3 @@
+require_fp;
+RD = f32_eq(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fld.h b/riscv/insns/fld.h
new file mode 100644
index 0000000..123dea4
--- /dev/null
+++ b/riscv/insns/fld.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = mmu.load_int64(RS1+SIMM);
diff --git a/riscv/insns/fle_d.h b/riscv/insns/fle_d.h
new file mode 100644
index 0000000..da76187
--- /dev/null
+++ b/riscv/insns/fle_d.h
@@ -0,0 +1,3 @@
+require_fp;
+RD = f64_le(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fle_s.h b/riscv/insns/fle_s.h
new file mode 100644
index 0000000..9c83a17
--- /dev/null
+++ b/riscv/insns/fle_s.h
@@ -0,0 +1,3 @@
+require_fp;
+RD = f32_le(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/flt_d.h b/riscv/insns/flt_d.h
new file mode 100644
index 0000000..01d135a
--- /dev/null
+++ b/riscv/insns/flt_d.h
@@ -0,0 +1,3 @@
+require_fp;
+RD = f64_lt(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/flt_s.h b/riscv/insns/flt_s.h
new file mode 100644
index 0000000..52eee5d
--- /dev/null
+++ b/riscv/insns/flt_s.h
@@ -0,0 +1,3 @@
+require_fp;
+RD = f32_lt(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/flw.h b/riscv/insns/flw.h
new file mode 100644
index 0000000..335fd7d
--- /dev/null
+++ b/riscv/insns/flw.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = mmu.load_int32(RS1+SIMM);
diff --git a/riscv/insns/fmadd_d.h b/riscv/insns/fmadd_d.h
new file mode 100644
index 0000000..f67853e
--- /dev/null
+++ b/riscv/insns/fmadd_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_mulAdd(FRS1, FRS2, FRS3);
+set_fp_exceptions;
diff --git a/riscv/insns/fmadd_s.h b/riscv/insns/fmadd_s.h
new file mode 100644
index 0000000..19db642
--- /dev/null
+++ b/riscv/insns/fmadd_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_mulAdd(FRS1, FRS2, FRS3);
+set_fp_exceptions;
diff --git a/riscv/insns/fmax_d.h b/riscv/insns/fmax_d.h
new file mode 100644
index 0000000..cbbb343
--- /dev/null
+++ b/riscv/insns/fmax_d.h
@@ -0,0 +1,4 @@
+require_fp;
+FRD = isNaNF64UI(FRS2) || f64_le_quiet(FRS2,FRS1) /* && FRS1 not NaN */
+ ? FRS1 : FRS2;
+set_fp_exceptions;
diff --git a/riscv/insns/fmax_s.h b/riscv/insns/fmax_s.h
new file mode 100644
index 0000000..8df665f
--- /dev/null
+++ b/riscv/insns/fmax_s.h
@@ -0,0 +1,4 @@
+require_fp;
+FRD = isNaNF32UI(FRS2) || f32_le_quiet(FRS2,FRS1) /* && FRS1 not NaN */
+ ? FRS1 : FRS2;
+set_fp_exceptions;
diff --git a/riscv/insns/fmin_d.h b/riscv/insns/fmin_d.h
new file mode 100644
index 0000000..3d3d454
--- /dev/null
+++ b/riscv/insns/fmin_d.h
@@ -0,0 +1,4 @@
+require_fp;
+FRD = isNaNF64UI(FRS2) || f64_lt_quiet(FRS1,FRS2) /* && FRS1 not NaN */
+ ? FRS1 : FRS2;
+set_fp_exceptions;
diff --git a/riscv/insns/fmin_s.h b/riscv/insns/fmin_s.h
new file mode 100644
index 0000000..994c860
--- /dev/null
+++ b/riscv/insns/fmin_s.h
@@ -0,0 +1,4 @@
+require_fp;
+FRD = isNaNF32UI(FRS2) || f32_lt_quiet(FRS1,FRS2) /* && FRS1 not NaN */
+ ? FRS1 : FRS2;
+set_fp_exceptions;
diff --git a/riscv/insns/fmovn.h b/riscv/insns/fmovn.h
new file mode 100644
index 0000000..394b56c
--- /dev/null
+++ b/riscv/insns/fmovn.h
@@ -0,0 +1,2 @@
+require_vector;
+if (RS1 & 0x1) FRD = FRS2;
diff --git a/riscv/insns/fmovz.h b/riscv/insns/fmovz.h
new file mode 100644
index 0000000..7862216
--- /dev/null
+++ b/riscv/insns/fmovz.h
@@ -0,0 +1,2 @@
+require_vector;
+if (~RS1 & 0x1) FRD = FRS2;
diff --git a/riscv/insns/fmsub_d.h b/riscv/insns/fmsub_d.h
new file mode 100644
index 0000000..b1e9340
--- /dev/null
+++ b/riscv/insns/fmsub_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_mulAdd(FRS1, FRS2, FRS3 ^ (uint64_t)INT64_MIN);
+set_fp_exceptions;
diff --git a/riscv/insns/fmsub_s.h b/riscv/insns/fmsub_s.h
new file mode 100644
index 0000000..d3349f5
--- /dev/null
+++ b/riscv/insns/fmsub_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_mulAdd(FRS1, FRS2, FRS3 ^ (uint32_t)INT32_MIN);
+set_fp_exceptions;
diff --git a/riscv/insns/fmul_d.h b/riscv/insns/fmul_d.h
new file mode 100644
index 0000000..a8adedd
--- /dev/null
+++ b/riscv/insns/fmul_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_mul(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fmul_s.h b/riscv/insns/fmul_s.h
new file mode 100644
index 0000000..6475578
--- /dev/null
+++ b/riscv/insns/fmul_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_mul(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fnmadd_d.h b/riscv/insns/fnmadd_d.h
new file mode 100644
index 0000000..1e2ee27
--- /dev/null
+++ b/riscv/insns/fnmadd_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_mulAdd(FRS1, FRS2, FRS3) ^ (uint64_t)INT64_MIN;
+set_fp_exceptions;
diff --git a/riscv/insns/fnmadd_s.h b/riscv/insns/fnmadd_s.h
new file mode 100644
index 0000000..78abb78
--- /dev/null
+++ b/riscv/insns/fnmadd_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_mulAdd(FRS1, FRS2, FRS3) ^ (uint32_t)INT32_MIN;
+set_fp_exceptions;
diff --git a/riscv/insns/fnmsub_d.h b/riscv/insns/fnmsub_d.h
new file mode 100644
index 0000000..ae643a5
--- /dev/null
+++ b/riscv/insns/fnmsub_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_mulAdd(FRS1, FRS2, FRS3 ^ (uint64_t)INT64_MIN) ^ (uint64_t)INT64_MIN;
+set_fp_exceptions;
diff --git a/riscv/insns/fnmsub_s.h b/riscv/insns/fnmsub_s.h
new file mode 100644
index 0000000..cbb70ba
--- /dev/null
+++ b/riscv/insns/fnmsub_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_mulAdd(FRS1, FRS2, FRS3 ^ (uint32_t)INT32_MIN) ^ (uint32_t)INT32_MIN;
+set_fp_exceptions;
diff --git a/riscv/insns/fsd.h b/riscv/insns/fsd.h
new file mode 100644
index 0000000..113398e
--- /dev/null
+++ b/riscv/insns/fsd.h
@@ -0,0 +1,2 @@
+require_fp;
+mmu.store_uint64(RS1+BIMM, FRS2);
diff --git a/riscv/insns/fsgnj_d.h b/riscv/insns/fsgnj_d.h
new file mode 100644
index 0000000..f66e804
--- /dev/null
+++ b/riscv/insns/fsgnj_d.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = (FRS1 &~ INT64_MIN) | (FRS2 & INT64_MIN);
diff --git a/riscv/insns/fsgnj_s.h b/riscv/insns/fsgnj_s.h
new file mode 100644
index 0000000..35609ac
--- /dev/null
+++ b/riscv/insns/fsgnj_s.h
@@ -0,0 +1,2 @@
+require_fp;
+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
new file mode 100644
index 0000000..22de215
--- /dev/null
+++ b/riscv/insns/fsgnjn_d.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = (FRS1 &~ INT64_MIN) | ((~FRS2) & INT64_MIN);
diff --git a/riscv/insns/fsgnjn_s.h b/riscv/insns/fsgnjn_s.h
new file mode 100644
index 0000000..dd66d71
--- /dev/null
+++ b/riscv/insns/fsgnjn_s.h
@@ -0,0 +1,2 @@
+require_fp;
+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
new file mode 100644
index 0000000..331b6e4
--- /dev/null
+++ b/riscv/insns/fsgnjx_d.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = FRS1 ^ (FRS2 & INT64_MIN);
diff --git a/riscv/insns/fsgnjx_s.h b/riscv/insns/fsgnjx_s.h
new file mode 100644
index 0000000..b455406
--- /dev/null
+++ b/riscv/insns/fsgnjx_s.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = FRS1 ^ (FRS2 & (uint32_t)INT32_MIN);
diff --git a/riscv/insns/fsqrt_d.h b/riscv/insns/fsqrt_d.h
new file mode 100644
index 0000000..7647c9c
--- /dev/null
+++ b/riscv/insns/fsqrt_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_sqrt(FRS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fsqrt_s.h b/riscv/insns/fsqrt_s.h
new file mode 100644
index 0000000..426f241
--- /dev/null
+++ b/riscv/insns/fsqrt_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_sqrt(FRS1);
+set_fp_exceptions;
diff --git a/riscv/insns/fsub_d.h b/riscv/insns/fsub_d.h
new file mode 100644
index 0000000..e25eebb
--- /dev/null
+++ b/riscv/insns/fsub_d.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f64_sub(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fsub_s.h b/riscv/insns/fsub_s.h
new file mode 100644
index 0000000..6c64d04
--- /dev/null
+++ b/riscv/insns/fsub_s.h
@@ -0,0 +1,4 @@
+require_fp;
+softfloat_roundingMode = RM;
+FRD = f32_sub(FRS1, FRS2);
+set_fp_exceptions;
diff --git a/riscv/insns/fsw.h b/riscv/insns/fsw.h
new file mode 100644
index 0000000..23d3333
--- /dev/null
+++ b/riscv/insns/fsw.h
@@ -0,0 +1,2 @@
+require_fp;
+mmu.store_uint32(RS1+BIMM, FRS2);
diff --git a/riscv/insns/j.h b/riscv/insns/j.h
new file mode 100644
index 0000000..3a4da2a
--- /dev/null
+++ b/riscv/insns/j.h
@@ -0,0 +1 @@
+set_pc(JUMP_TARGET);
diff --git a/riscv/insns/jal.h b/riscv/insns/jal.h
new file mode 100644
index 0000000..41dc403
--- /dev/null
+++ b/riscv/insns/jal.h
@@ -0,0 +1,2 @@
+RA = npc;
+set_pc(JUMP_TARGET);
diff --git a/riscv/insns/jalr_c.h b/riscv/insns/jalr_c.h
new file mode 100644
index 0000000..91be911
--- /dev/null
+++ b/riscv/insns/jalr_c.h
@@ -0,0 +1,3 @@
+reg_t temp = RS1;
+RD = npc;
+set_pc(temp + SIMM);
diff --git a/riscv/insns/jalr_j.h b/riscv/insns/jalr_j.h
new file mode 100644
index 0000000..0d2ef12
--- /dev/null
+++ b/riscv/insns/jalr_j.h
@@ -0,0 +1 @@
+#include "insns/jalr_c.h"
diff --git a/riscv/insns/jalr_r.h b/riscv/insns/jalr_r.h
new file mode 100644
index 0000000..0d2ef12
--- /dev/null
+++ b/riscv/insns/jalr_r.h
@@ -0,0 +1 @@
+#include "insns/jalr_c.h"
diff --git a/riscv/insns/lb.h b/riscv/insns/lb.h
new file mode 100644
index 0000000..81ba7de
--- /dev/null
+++ b/riscv/insns/lb.h
@@ -0,0 +1 @@
+RD = mmu.load_int8(RS1+SIMM);
diff --git a/riscv/insns/lbu.h b/riscv/insns/lbu.h
new file mode 100644
index 0000000..12c688a
--- /dev/null
+++ b/riscv/insns/lbu.h
@@ -0,0 +1 @@
+RD = mmu.load_uint8(RS1+SIMM);
diff --git a/riscv/insns/ld.h b/riscv/insns/ld.h
new file mode 100644
index 0000000..940d348
--- /dev/null
+++ b/riscv/insns/ld.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = mmu.load_int64(RS1+SIMM);
diff --git a/riscv/insns/lh.h b/riscv/insns/lh.h
new file mode 100644
index 0000000..ec25bc4
--- /dev/null
+++ b/riscv/insns/lh.h
@@ -0,0 +1 @@
+RD = mmu.load_int16(RS1+SIMM);
diff --git a/riscv/insns/lhu.h b/riscv/insns/lhu.h
new file mode 100644
index 0000000..0999c00
--- /dev/null
+++ b/riscv/insns/lhu.h
@@ -0,0 +1 @@
+RD = mmu.load_uint16(RS1+SIMM);
diff --git a/riscv/insns/lui.h b/riscv/insns/lui.h
new file mode 100644
index 0000000..6af2a2a
--- /dev/null
+++ b/riscv/insns/lui.h
@@ -0,0 +1 @@
+RD = sext32(BIGIMM << IMM_BITS);
diff --git a/riscv/insns/lw.h b/riscv/insns/lw.h
new file mode 100644
index 0000000..769c9fd
--- /dev/null
+++ b/riscv/insns/lw.h
@@ -0,0 +1 @@
+RD = mmu.load_int32(RS1+SIMM);
diff --git a/riscv/insns/lwu.h b/riscv/insns/lwu.h
new file mode 100644
index 0000000..f8f9841
--- /dev/null
+++ b/riscv/insns/lwu.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = mmu.load_uint32(RS1+SIMM);
diff --git a/riscv/insns/mffsr.h b/riscv/insns/mffsr.h
new file mode 100644
index 0000000..29debc4
--- /dev/null
+++ b/riscv/insns/mffsr.h
@@ -0,0 +1,2 @@
+require_fp;
+RD = fsr;
diff --git a/riscv/insns/mfpcr.h b/riscv/insns/mfpcr.h
new file mode 100644
index 0000000..7de089e
--- /dev/null
+++ b/riscv/insns/mfpcr.h
@@ -0,0 +1,68 @@
+require_supervisor;
+
+reg_t val;
+
+switch(insn.rtype.rs2)
+{
+ case 0:
+ val = sr;
+ break;
+ case 1:
+ val = epc;
+ break;
+ case 2:
+ val = badvaddr;
+ break;
+ case 3:
+ val = evec;
+ break;
+ case 4:
+ val = count;
+ break;
+ case 5:
+ val = compare;
+ break;
+ case 6:
+ val = cause;
+ break;
+ case 7:
+ val = 0;
+ cause &= ~(1 << (IPI_IRQ+CAUSE_IP_SHIFT));
+ break;
+
+ case 8:
+ val = mmu.memsz >> PGSHIFT;
+ break;
+
+ case 9:
+ val = mmu.get_ptbr();
+ break;
+
+ case 10:
+ val = id;
+ break;
+
+ case 11:
+ val = vecbanks;
+ break;
+
+ case 12:
+ val = sim.num_cores();
+ break;
+
+ case 17:
+ val = sim.get_fromhost();
+ break;
+
+ case 24:
+ val = pcr_k0;
+ break;
+ case 25:
+ val = pcr_k1;
+ break;
+
+ default:
+ val = -1;
+}
+
+RD = sext_xprlen(val);
diff --git a/riscv/insns/mftx_d.h b/riscv/insns/mftx_d.h
new file mode 100644
index 0000000..31be4cb
--- /dev/null
+++ b/riscv/insns/mftx_d.h
@@ -0,0 +1,3 @@
+require_xpr64;
+require_fp;
+RD = FRS2;
diff --git a/riscv/insns/mftx_s.h b/riscv/insns/mftx_s.h
new file mode 100644
index 0000000..589b33b
--- /dev/null
+++ b/riscv/insns/mftx_s.h
@@ -0,0 +1,2 @@
+require_fp;
+RD = sext32(FRS2);
diff --git a/riscv/insns/movn.h b/riscv/insns/movn.h
new file mode 100644
index 0000000..402d6d3
--- /dev/null
+++ b/riscv/insns/movn.h
@@ -0,0 +1,2 @@
+require_vector;
+if (RS1 & 0x1) RD = RS2;
diff --git a/riscv/insns/movz.h b/riscv/insns/movz.h
new file mode 100644
index 0000000..74cf8a9
--- /dev/null
+++ b/riscv/insns/movz.h
@@ -0,0 +1,2 @@
+require_vector;
+if (~RS1 & 0x1) RD = RS2;
diff --git a/riscv/insns/mtfsr.h b/riscv/insns/mtfsr.h
new file mode 100644
index 0000000..cc6f9ea
--- /dev/null
+++ b/riscv/insns/mtfsr.h
@@ -0,0 +1,4 @@
+require_fp;
+uint32_t tmp = fsr;
+set_fsr(RS1);
+RD = tmp;
diff --git a/riscv/insns/mtpcr.h b/riscv/insns/mtpcr.h
new file mode 100644
index 0000000..59f864f
--- /dev/null
+++ b/riscv/insns/mtpcr.h
@@ -0,0 +1,45 @@
+require_supervisor;
+
+switch(insn.rtype.rs2)
+{
+ case 0:
+ set_sr(RS1);
+ break;
+ case 1:
+ epc = RS1;
+ break;
+ case 3:
+ evec = RS1;
+ break;
+ case 4:
+ count = RS1;
+ break;
+ case 5:
+ cause &= ~(1 << (TIMER_IRQ+CAUSE_IP_SHIFT));
+ compare = RS1;
+ break;
+
+ case 7:
+ sim.send_ipi(RS1);
+ break;
+
+ case 9:
+ mmu.set_ptbr(RS1);
+ break;
+
+ case 11:
+ vecbanks = RS1 & 0xff;
+ vecbanks_count = __builtin_popcountll(vecbanks);
+ break;
+
+ case 16:
+ sim.set_tohost(RS1);
+ break;
+
+ case 24:
+ pcr_k0 = RS1;
+ break;
+ case 25:
+ pcr_k1 = RS1;
+ break;
+}
diff --git a/riscv/insns/mul.h b/riscv/insns/mul.h
new file mode 100644
index 0000000..770d733
--- /dev/null
+++ b/riscv/insns/mul.h
@@ -0,0 +1 @@
+RD = sext_xprlen(RS1 * RS2);
diff --git a/riscv/insns/mulh.h b/riscv/insns/mulh.h
new file mode 100644
index 0000000..f771a62
--- /dev/null
+++ b/riscv/insns/mulh.h
@@ -0,0 +1,8 @@
+if(xpr64)
+{
+ int64_t a = RS1;
+ int64_t b = RS2;
+ RD = (int128_t(a) * int128_t(b)) >> 64;
+}
+else
+ RD = sext32((sext32(RS1) * sext32(RS2)) >> 32);
diff --git a/riscv/insns/mulhsu.h b/riscv/insns/mulhsu.h
new file mode 100644
index 0000000..c832657
--- /dev/null
+++ b/riscv/insns/mulhsu.h
@@ -0,0 +1,8 @@
+if(xpr64)
+{
+ int64_t a = RS1;
+ uint64_t b = RS2;
+ RD = (int128_t(a) * uint128_t(b)) >> 64;
+}
+else
+ RD = sext32((sext32(RS1) * reg_t((uint32_t)RS2)) >> 32);
diff --git a/riscv/insns/mulhu.h b/riscv/insns/mulhu.h
new file mode 100644
index 0000000..6334426
--- /dev/null
+++ b/riscv/insns/mulhu.h
@@ -0,0 +1,4 @@
+if(xpr64)
+ RD = (uint128_t(RS1) * uint128_t(RS2)) >> 64;
+else
+ RD = sext32(((uint64_t)(uint32_t)RS1 * (uint64_t)(uint32_t)RS2) >> 32);
diff --git a/riscv/insns/mulw.h b/riscv/insns/mulw.h
new file mode 100644
index 0000000..7b0a934
--- /dev/null
+++ b/riscv/insns/mulw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(RS1 * RS2);
diff --git a/riscv/insns/mxtf_d.h b/riscv/insns/mxtf_d.h
new file mode 100644
index 0000000..29792ec
--- /dev/null
+++ b/riscv/insns/mxtf_d.h
@@ -0,0 +1,3 @@
+require_xpr64;
+require_fp;
+FRD = RS1;
diff --git a/riscv/insns/mxtf_s.h b/riscv/insns/mxtf_s.h
new file mode 100644
index 0000000..54546ea
--- /dev/null
+++ b/riscv/insns/mxtf_s.h
@@ -0,0 +1,2 @@
+require_fp;
+FRD = RS1;
diff --git a/riscv/insns/or.h b/riscv/insns/or.h
new file mode 100644
index 0000000..07bcac3
--- /dev/null
+++ b/riscv/insns/or.h
@@ -0,0 +1 @@
+RD = RS1 | RS2;
diff --git a/riscv/insns/ori.h b/riscv/insns/ori.h
new file mode 100644
index 0000000..9561b97
--- /dev/null
+++ b/riscv/insns/ori.h
@@ -0,0 +1 @@
+RD = SIMM | RS1;
diff --git a/riscv/insns/rdcycle.h b/riscv/insns/rdcycle.h
new file mode 100644
index 0000000..9b966a6
--- /dev/null
+++ b/riscv/insns/rdcycle.h
@@ -0,0 +1 @@
+RD = cycle;
diff --git a/riscv/insns/rdinstret.h b/riscv/insns/rdinstret.h
new file mode 100644
index 0000000..9b966a6
--- /dev/null
+++ b/riscv/insns/rdinstret.h
@@ -0,0 +1 @@
+RD = cycle;
diff --git a/riscv/insns/rdnpc.h b/riscv/insns/rdnpc.h
new file mode 100644
index 0000000..5525421
--- /dev/null
+++ b/riscv/insns/rdnpc.h
@@ -0,0 +1 @@
+RD = npc;
diff --git a/riscv/insns/rdtime.h b/riscv/insns/rdtime.h
new file mode 100644
index 0000000..9b966a6
--- /dev/null
+++ b/riscv/insns/rdtime.h
@@ -0,0 +1 @@
+RD = cycle;
diff --git a/riscv/insns/rem.h b/riscv/insns/rem.h
new file mode 100644
index 0000000..ac82a56
--- /dev/null
+++ b/riscv/insns/rem.h
@@ -0,0 +1,6 @@
+if(RS2 == 0)
+ RD = RS1;
+else if(sreg_t(RS1) == INT64_MIN && sreg_t(RS2) == -1)
+ RD = 0;
+else
+ RD = sext_xprlen(sext_xprlen(RS1) % sext_xprlen(RS2));
diff --git a/riscv/insns/remu.h b/riscv/insns/remu.h
new file mode 100644
index 0000000..c698aca
--- /dev/null
+++ b/riscv/insns/remu.h
@@ -0,0 +1,4 @@
+if(RS2 == 0)
+ RD = RS1;
+else
+ RD = sext_xprlen(zext_xprlen(RS1) % zext_xprlen(RS2));
diff --git a/riscv/insns/remuw.h b/riscv/insns/remuw.h
new file mode 100644
index 0000000..8234af3
--- /dev/null
+++ b/riscv/insns/remuw.h
@@ -0,0 +1,5 @@
+require_xpr64;
+if(RS2 == 0)
+ RD = RS1;
+else
+ RD = sext32(zext_xprlen(RS1) % zext_xprlen(RS2));
diff --git a/riscv/insns/remw.h b/riscv/insns/remw.h
new file mode 100644
index 0000000..93c3858
--- /dev/null
+++ b/riscv/insns/remw.h
@@ -0,0 +1,7 @@
+require_xpr64;
+if(RS2 == 0)
+ RD = RS1;
+else if(int32_t(RS1) == INT32_MIN && int32_t(RS2) == -1)
+ RD = 0;
+else
+ RD = sext32(int32_t(RS1) % int32_t(RS2));
diff --git a/riscv/insns/sb.h b/riscv/insns/sb.h
new file mode 100644
index 0000000..af5bd10
--- /dev/null
+++ b/riscv/insns/sb.h
@@ -0,0 +1 @@
+mmu.store_uint8(RS1+BIMM, RS2);
diff --git a/riscv/insns/sd.h b/riscv/insns/sd.h
new file mode 100644
index 0000000..2009149
--- /dev/null
+++ b/riscv/insns/sd.h
@@ -0,0 +1,2 @@
+require_xpr64;
+mmu.store_uint64(RS1+BIMM, RS2);
diff --git a/riscv/insns/sh.h b/riscv/insns/sh.h
new file mode 100644
index 0000000..a484e1e
--- /dev/null
+++ b/riscv/insns/sh.h
@@ -0,0 +1 @@
+mmu.store_uint16(RS1+BIMM, RS2);
diff --git a/riscv/insns/sll.h b/riscv/insns/sll.h
new file mode 100644
index 0000000..86eb966
--- /dev/null
+++ b/riscv/insns/sll.h
@@ -0,0 +1 @@
+RD = sext_xprlen(RS1 << (RS2 & (xprlen-1)));
diff --git a/riscv/insns/slli.h b/riscv/insns/slli.h
new file mode 100644
index 0000000..bfaf430
--- /dev/null
+++ b/riscv/insns/slli.h
@@ -0,0 +1,8 @@
+if(xpr64)
+ RD = RS1 << SHAMT;
+else
+{
+ if(SHAMT & 0x20)
+ throw trap_illegal_instruction;
+ RD = sext32(RS1 << SHAMT);
+}
diff --git a/riscv/insns/slliw.h b/riscv/insns/slliw.h
new file mode 100644
index 0000000..1f6e50d
--- /dev/null
+++ b/riscv/insns/slliw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(RS1 << SHAMTW);
diff --git a/riscv/insns/sllw.h b/riscv/insns/sllw.h
new file mode 100644
index 0000000..f3356d8
--- /dev/null
+++ b/riscv/insns/sllw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(RS1 << (RS2 & 0x1F));
diff --git a/riscv/insns/slt.h b/riscv/insns/slt.h
new file mode 100644
index 0000000..5c50534
--- /dev/null
+++ b/riscv/insns/slt.h
@@ -0,0 +1 @@
+RD = sreg_t(cmp_trunc(RS1)) < sreg_t(cmp_trunc(RS2));
diff --git a/riscv/insns/slti.h b/riscv/insns/slti.h
new file mode 100644
index 0000000..1dcd892
--- /dev/null
+++ b/riscv/insns/slti.h
@@ -0,0 +1 @@
+RD = sreg_t(cmp_trunc(RS1)) < sreg_t(cmp_trunc(SIMM));
diff --git a/riscv/insns/sltiu.h b/riscv/insns/sltiu.h
new file mode 100644
index 0000000..45e579b
--- /dev/null
+++ b/riscv/insns/sltiu.h
@@ -0,0 +1 @@
+RD = cmp_trunc(RS1) < cmp_trunc(SIMM);
diff --git a/riscv/insns/sltu.h b/riscv/insns/sltu.h
new file mode 100644
index 0000000..2c5bdc3
--- /dev/null
+++ b/riscv/insns/sltu.h
@@ -0,0 +1 @@
+RD = cmp_trunc(RS1) < cmp_trunc(RS2);
diff --git a/riscv/insns/sra.h b/riscv/insns/sra.h
new file mode 100644
index 0000000..7102da0
--- /dev/null
+++ b/riscv/insns/sra.h
@@ -0,0 +1 @@
+RD = sext_xprlen(sext_xprlen(RS1) >> (RS2 & (xprlen-1)));
diff --git a/riscv/insns/srai.h b/riscv/insns/srai.h
new file mode 100644
index 0000000..bb17d27
--- /dev/null
+++ b/riscv/insns/srai.h
@@ -0,0 +1,8 @@
+if(xpr64)
+ RD = sreg_t(RS1) >> SHAMT;
+else
+{
+ if(SHAMT & 0x20)
+ throw trap_illegal_instruction;
+ RD = sext32(int32_t(RS1) >> SHAMT);
+}
diff --git a/riscv/insns/sraiw.h b/riscv/insns/sraiw.h
new file mode 100644
index 0000000..4c56730
--- /dev/null
+++ b/riscv/insns/sraiw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(int32_t(RS1) >> SHAMTW);
diff --git a/riscv/insns/sraw.h b/riscv/insns/sraw.h
new file mode 100644
index 0000000..d178374
--- /dev/null
+++ b/riscv/insns/sraw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32(int32_t(RS1) >> (RS2 & 0x1F));
diff --git a/riscv/insns/srl.h b/riscv/insns/srl.h
new file mode 100644
index 0000000..8230d27
--- /dev/null
+++ b/riscv/insns/srl.h
@@ -0,0 +1,4 @@
+if(xpr64)
+ RD = RS1 >> (RS2 & 0x3F);
+else
+ RD = sext32((uint32_t)RS1 >> (RS2 & 0x1F));
diff --git a/riscv/insns/srli.h b/riscv/insns/srli.h
new file mode 100644
index 0000000..5378fd1
--- /dev/null
+++ b/riscv/insns/srli.h
@@ -0,0 +1,8 @@
+if(xpr64)
+ RD = RS1 >> SHAMT;
+else
+{
+ if(SHAMT & 0x20)
+ throw trap_illegal_instruction;
+ RD = sext32((uint32_t)RS1 >> SHAMT);
+}
diff --git a/riscv/insns/srliw.h b/riscv/insns/srliw.h
new file mode 100644
index 0000000..c400507
--- /dev/null
+++ b/riscv/insns/srliw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32((uint32_t)RS1 >> SHAMTW);
diff --git a/riscv/insns/srlw.h b/riscv/insns/srlw.h
new file mode 100644
index 0000000..b206f7c
--- /dev/null
+++ b/riscv/insns/srlw.h
@@ -0,0 +1,2 @@
+require_xpr64;
+RD = sext32((uint32_t)RS1 >> (RS2 & 0x1F));
diff --git a/riscv/insns/stop.h b/riscv/insns/stop.h
new file mode 100644
index 0000000..791a82c
--- /dev/null
+++ b/riscv/insns/stop.h
@@ -0,0 +1,3 @@
+require_vector;
+utmode = false;
+throw vt_command_stop;
diff --git a/riscv/insns/sub.h b/riscv/insns/sub.h
new file mode 100644
index 0000000..2b1e057
--- /dev/null
+++ b/riscv/insns/sub.h
@@ -0,0 +1 @@
+RD = sext_xprlen(RS1 - RS2);
diff --git a/riscv/insns/subw.h b/riscv/insns/subw.h
new file mode 100644
index 0000000..28db334
--- /dev/null
+++ b/riscv/insns/subw.h
@@ -0,0 +1,3 @@
+require_xpr64;
+RD = sext32(RS1 - RS2);
+
diff --git a/riscv/insns/sw.h b/riscv/insns/sw.h
new file mode 100644
index 0000000..dbe260f
--- /dev/null
+++ b/riscv/insns/sw.h
@@ -0,0 +1 @@
+mmu.store_uint32(RS1+BIMM, RS2);
diff --git a/riscv/insns/syscall.h b/riscv/insns/syscall.h
new file mode 100644
index 0000000..2c7199d
--- /dev/null
+++ b/riscv/insns/syscall.h
@@ -0,0 +1 @@
+throw trap_syscall;
diff --git a/riscv/insns/utidx.h b/riscv/insns/utidx.h
new file mode 100644
index 0000000..b3c944c
--- /dev/null
+++ b/riscv/insns/utidx.h
@@ -0,0 +1,2 @@
+require_vector;
+RD = utidx;
diff --git a/riscv/insns/vf.h b/riscv/insns/vf.h
new file mode 100644
index 0000000..7779645
--- /dev/null
+++ b/riscv/insns/vf.h
@@ -0,0 +1,8 @@
+require_vector;
+for (int i=0; i<VL; i++)
+{
+ uts[i]->pc = RS1+SIMM;
+ uts[i]->utmode = true;
+ while (uts[i]->utmode)
+ uts[i]->step(1, false); // XXX
+}
diff --git a/riscv/insns/vfld.h b/riscv/insns/vfld.h
new file mode 100644
index 0000000..9b40470
--- /dev/null
+++ b/riscv/insns/vfld.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_LOAD(FRD, load_int64, 8);
diff --git a/riscv/insns/vflsegd.h b/riscv/insns/vflsegd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vflsegd.h
diff --git a/riscv/insns/vflsegstd.h b/riscv/insns/vflsegstd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vflsegstd.h
diff --git a/riscv/insns/vflsegstw.h b/riscv/insns/vflsegstw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vflsegstw.h
diff --git a/riscv/insns/vflsegw.h b/riscv/insns/vflsegw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vflsegw.h
diff --git a/riscv/insns/vflstd.h b/riscv/insns/vflstd.h
new file mode 100644
index 0000000..fa9b32d
--- /dev/null
+++ b/riscv/insns/vflstd.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_LOAD(FRD, load_int64, RS2);
diff --git a/riscv/insns/vflstw.h b/riscv/insns/vflstw.h
new file mode 100644
index 0000000..716c818
--- /dev/null
+++ b/riscv/insns/vflstw.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_LOAD(FRD, load_int32, RS2);
diff --git a/riscv/insns/vflw.h b/riscv/insns/vflw.h
new file mode 100644
index 0000000..75fdd04
--- /dev/null
+++ b/riscv/insns/vflw.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_LOAD(FRD, load_int32, 4);
diff --git a/riscv/insns/vfmst.h b/riscv/insns/vfmst.h
new file mode 100644
index 0000000..686d7c5
--- /dev/null
+++ b/riscv/insns/vfmst.h
@@ -0,0 +1,4 @@
+require_vector;
+require_fp;
+assert(0 <= RS2 && RS2 < MAX_UTS);
+UT_FRD(RS2) = FRS1;
diff --git a/riscv/insns/vfmsv.h b/riscv/insns/vfmsv.h
new file mode 100644
index 0000000..a9aa876
--- /dev/null
+++ b/riscv/insns/vfmsv.h
@@ -0,0 +1,5 @@
+require_vector;
+require_fp;
+UT_LOOP_START
+ UT_LOOP_FRD = FRS1;
+UT_LOOP_END
diff --git a/riscv/insns/vfmts.h b/riscv/insns/vfmts.h
new file mode 100644
index 0000000..a6da126
--- /dev/null
+++ b/riscv/insns/vfmts.h
@@ -0,0 +1,4 @@
+require_vector;
+require_fp;
+assert(0 <= RS2 && RS2 < MAX_UTS);
+FRD = UT_FRS1(RS2);
diff --git a/riscv/insns/vfmvv.h b/riscv/insns/vfmvv.h
new file mode 100644
index 0000000..279da21
--- /dev/null
+++ b/riscv/insns/vfmvv.h
@@ -0,0 +1,5 @@
+require_vector;
+require_fp;
+UT_LOOP_START
+ UT_LOOP_FRD = UT_LOOP_FRS1;
+UT_LOOP_END
diff --git a/riscv/insns/vfsd.h b/riscv/insns/vfsd.h
new file mode 100644
index 0000000..f619fc8
--- /dev/null
+++ b/riscv/insns/vfsd.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_STORE(FRD, store_uint64, 8);
diff --git a/riscv/insns/vfssegd.h b/riscv/insns/vfssegd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vfssegd.h
diff --git a/riscv/insns/vfssegstd.h b/riscv/insns/vfssegstd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vfssegstd.h
diff --git a/riscv/insns/vfssegstw.h b/riscv/insns/vfssegstw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vfssegstw.h
diff --git a/riscv/insns/vfssegw.h b/riscv/insns/vfssegw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vfssegw.h
diff --git a/riscv/insns/vfsstd.h b/riscv/insns/vfsstd.h
new file mode 100644
index 0000000..b3bb260
--- /dev/null
+++ b/riscv/insns/vfsstd.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_STORE(FRD, store_uint64, RS2);
diff --git a/riscv/insns/vfsstw.h b/riscv/insns/vfsstw.h
new file mode 100644
index 0000000..9cef9b0
--- /dev/null
+++ b/riscv/insns/vfsstw.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_STORE(FRD, store_uint32, RS2);
diff --git a/riscv/insns/vfsw.h b/riscv/insns/vfsw.h
new file mode 100644
index 0000000..3fe3d3f
--- /dev/null
+++ b/riscv/insns/vfsw.h
@@ -0,0 +1,3 @@
+require_vector;
+require_fp;
+VEC_STORE(FRD, store_uint32, 4);
diff --git a/riscv/insns/vlb.h b/riscv/insns/vlb.h
new file mode 100644
index 0000000..618380a
--- /dev/null
+++ b/riscv/insns/vlb.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_int8, 1);
diff --git a/riscv/insns/vlbu.h b/riscv/insns/vlbu.h
new file mode 100644
index 0000000..f92c8b5
--- /dev/null
+++ b/riscv/insns/vlbu.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_uint8, 1);
diff --git a/riscv/insns/vld.h b/riscv/insns/vld.h
new file mode 100644
index 0000000..fb7a3c5
--- /dev/null
+++ b/riscv/insns/vld.h
@@ -0,0 +1,3 @@
+require_vector;
+require_xpr64;
+VEC_LOAD(RD, load_int64, 8);
diff --git a/riscv/insns/vlh.h b/riscv/insns/vlh.h
new file mode 100644
index 0000000..269c2a8
--- /dev/null
+++ b/riscv/insns/vlh.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_int16, 2);
diff --git a/riscv/insns/vlhu.h b/riscv/insns/vlhu.h
new file mode 100644
index 0000000..7a2019d
--- /dev/null
+++ b/riscv/insns/vlhu.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_uint16, 2);
diff --git a/riscv/insns/vlsegb.h b/riscv/insns/vlsegb.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegb.h
diff --git a/riscv/insns/vlsegbu.h b/riscv/insns/vlsegbu.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegbu.h
diff --git a/riscv/insns/vlsegd.h b/riscv/insns/vlsegd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegd.h
diff --git a/riscv/insns/vlsegh.h b/riscv/insns/vlsegh.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegh.h
diff --git a/riscv/insns/vlseghu.h b/riscv/insns/vlseghu.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlseghu.h
diff --git a/riscv/insns/vlsegstb.h b/riscv/insns/vlsegstb.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegstb.h
diff --git a/riscv/insns/vlsegstbu.h b/riscv/insns/vlsegstbu.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegstbu.h
diff --git a/riscv/insns/vlsegstd.h b/riscv/insns/vlsegstd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegstd.h
diff --git a/riscv/insns/vlsegsth.h b/riscv/insns/vlsegsth.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegsth.h
diff --git a/riscv/insns/vlsegsthu.h b/riscv/insns/vlsegsthu.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegsthu.h
diff --git a/riscv/insns/vlsegstw.h b/riscv/insns/vlsegstw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegstw.h
diff --git a/riscv/insns/vlsegstwu.h b/riscv/insns/vlsegstwu.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegstwu.h
diff --git a/riscv/insns/vlsegw.h b/riscv/insns/vlsegw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegw.h
diff --git a/riscv/insns/vlsegwu.h b/riscv/insns/vlsegwu.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vlsegwu.h
diff --git a/riscv/insns/vlstb.h b/riscv/insns/vlstb.h
new file mode 100644
index 0000000..219d90e
--- /dev/null
+++ b/riscv/insns/vlstb.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_int8, RS2);
diff --git a/riscv/insns/vlstbu.h b/riscv/insns/vlstbu.h
new file mode 100644
index 0000000..09faa29
--- /dev/null
+++ b/riscv/insns/vlstbu.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_uint8, RS2);
diff --git a/riscv/insns/vlstd.h b/riscv/insns/vlstd.h
new file mode 100644
index 0000000..5e5de9c
--- /dev/null
+++ b/riscv/insns/vlstd.h
@@ -0,0 +1,3 @@
+require_vector;
+require_xpr64;
+VEC_LOAD(RD, load_int64, RS2);
diff --git a/riscv/insns/vlsth.h b/riscv/insns/vlsth.h
new file mode 100644
index 0000000..af6b5b5
--- /dev/null
+++ b/riscv/insns/vlsth.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_int16, RS2);
diff --git a/riscv/insns/vlsthu.h b/riscv/insns/vlsthu.h
new file mode 100644
index 0000000..0fe8452
--- /dev/null
+++ b/riscv/insns/vlsthu.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_uint16, RS2);
diff --git a/riscv/insns/vlstw.h b/riscv/insns/vlstw.h
new file mode 100644
index 0000000..5375dc0
--- /dev/null
+++ b/riscv/insns/vlstw.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_int32, RS2);
diff --git a/riscv/insns/vlstwu.h b/riscv/insns/vlstwu.h
new file mode 100644
index 0000000..328e23f
--- /dev/null
+++ b/riscv/insns/vlstwu.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_uint32, RS2);
diff --git a/riscv/insns/vlw.h b/riscv/insns/vlw.h
new file mode 100644
index 0000000..6e35911
--- /dev/null
+++ b/riscv/insns/vlw.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_int32, 4);
diff --git a/riscv/insns/vlwu.h b/riscv/insns/vlwu.h
new file mode 100644
index 0000000..4fa1489
--- /dev/null
+++ b/riscv/insns/vlwu.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_LOAD(RD, load_uint32, 4);
diff --git a/riscv/insns/vmst.h b/riscv/insns/vmst.h
new file mode 100644
index 0000000..f4d03d9
--- /dev/null
+++ b/riscv/insns/vmst.h
@@ -0,0 +1,3 @@
+require_vector;
+assert(0 <= RS2 && RS2 < MAX_UTS);
+UT_RD(RS2) = RS1;
diff --git a/riscv/insns/vmsv.h b/riscv/insns/vmsv.h
new file mode 100644
index 0000000..c6f4c2c
--- /dev/null
+++ b/riscv/insns/vmsv.h
@@ -0,0 +1,4 @@
+require_vector;
+UT_LOOP_START
+ UT_LOOP_RD = RS1;
+UT_LOOP_END
diff --git a/riscv/insns/vmts.h b/riscv/insns/vmts.h
new file mode 100644
index 0000000..2d463bc
--- /dev/null
+++ b/riscv/insns/vmts.h
@@ -0,0 +1,3 @@
+require_vector;
+assert(0 <= RS2 && RS2 < MAX_UTS);
+RD = UT_RS1(RS2);
diff --git a/riscv/insns/vmvv.h b/riscv/insns/vmvv.h
new file mode 100644
index 0000000..91d63d4
--- /dev/null
+++ b/riscv/insns/vmvv.h
@@ -0,0 +1,4 @@
+require_vector;
+UT_LOOP_START
+ UT_LOOP_RD = UT_LOOP_RS1;
+UT_LOOP_END
diff --git a/riscv/insns/vsb.h b/riscv/insns/vsb.h
new file mode 100644
index 0000000..c3d5b9d
--- /dev/null
+++ b/riscv/insns/vsb.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_STORE(RD, store_uint8, 1);
diff --git a/riscv/insns/vsd.h b/riscv/insns/vsd.h
new file mode 100644
index 0000000..9c02069
--- /dev/null
+++ b/riscv/insns/vsd.h
@@ -0,0 +1,3 @@
+require_vector;
+require_xpr64;
+VEC_STORE(RD, store_uint64, 8);
diff --git a/riscv/insns/vsetvl.h b/riscv/insns/vsetvl.h
new file mode 100644
index 0000000..c2212ff
--- /dev/null
+++ b/riscv/insns/vsetvl.h
@@ -0,0 +1,3 @@
+require_vector;
+setvl(RS1);
+RD = VL;
diff --git a/riscv/insns/vsh.h b/riscv/insns/vsh.h
new file mode 100644
index 0000000..623eda8
--- /dev/null
+++ b/riscv/insns/vsh.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_STORE(RD, store_uint16, 2);
diff --git a/riscv/insns/vssegb.h b/riscv/insns/vssegb.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegb.h
diff --git a/riscv/insns/vssegd.h b/riscv/insns/vssegd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegd.h
diff --git a/riscv/insns/vssegh.h b/riscv/insns/vssegh.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegh.h
diff --git a/riscv/insns/vssegstb.h b/riscv/insns/vssegstb.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegstb.h
diff --git a/riscv/insns/vssegstd.h b/riscv/insns/vssegstd.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegstd.h
diff --git a/riscv/insns/vssegsth.h b/riscv/insns/vssegsth.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegsth.h
diff --git a/riscv/insns/vssegstw.h b/riscv/insns/vssegstw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegstw.h
diff --git a/riscv/insns/vssegw.h b/riscv/insns/vssegw.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vssegw.h
diff --git a/riscv/insns/vsstb.h b/riscv/insns/vsstb.h
new file mode 100644
index 0000000..b83cc50
--- /dev/null
+++ b/riscv/insns/vsstb.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_STORE(RD, store_uint8, RS2);
diff --git a/riscv/insns/vsstd.h b/riscv/insns/vsstd.h
new file mode 100644
index 0000000..26868d2
--- /dev/null
+++ b/riscv/insns/vsstd.h
@@ -0,0 +1,3 @@
+require_vector;
+require_xpr64;
+VEC_STORE(RD, store_uint64, RS2);
diff --git a/riscv/insns/vssth.h b/riscv/insns/vssth.h
new file mode 100644
index 0000000..3904331
--- /dev/null
+++ b/riscv/insns/vssth.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_STORE(RD, store_uint16, RS2);
diff --git a/riscv/insns/vsstw.h b/riscv/insns/vsstw.h
new file mode 100644
index 0000000..8f05953
--- /dev/null
+++ b/riscv/insns/vsstw.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_STORE(RD, store_uint32, RS2);
diff --git a/riscv/insns/vsw.h b/riscv/insns/vsw.h
new file mode 100644
index 0000000..662d4e3
--- /dev/null
+++ b/riscv/insns/vsw.h
@@ -0,0 +1,2 @@
+require_vector;
+VEC_STORE(RD, store_uint32, 4);
diff --git a/riscv/insns/vtcfgivl.h b/riscv/insns/vtcfgivl.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/riscv/insns/vtcfgivl.h
diff --git a/riscv/insns/vvcfgivl.h b/riscv/insns/vvcfgivl.h
new file mode 100644
index 0000000..0ded9f8
--- /dev/null
+++ b/riscv/insns/vvcfgivl.h
@@ -0,0 +1,6 @@
+require_vector;
+nxpr_use = SIMM & 0x3f;
+nfpr_use = (SIMM >> 6) & 0x3f;
+vcfg();
+setvl(RS1);
+RD = VL;
diff --git a/riscv/insns/xor.h b/riscv/insns/xor.h
new file mode 100644
index 0000000..49b1783
--- /dev/null
+++ b/riscv/insns/xor.h
@@ -0,0 +1 @@
+RD = RS1 ^ RS2;
diff --git a/riscv/insns/xori.h b/riscv/insns/xori.h
new file mode 100644
index 0000000..5852aac
--- /dev/null
+++ b/riscv/insns/xori.h
@@ -0,0 +1 @@
+RD = SIMM ^ RS1;
diff --git a/riscv/interactive.cc b/riscv/interactive.cc
new file mode 100644
index 0000000..4f7891f
--- /dev/null
+++ b/riscv/interactive.cc
@@ -0,0 +1,256 @@
+#include "sim.h"
+#include "htif.h"
+#include <sys/mman.h>
+#include <map>
+#include <iostream>
+#include <climits>
+#include <assert.h>
+
+void sim_t::interactive()
+{
+ putchar(':');
+ char s[128];
+ std::cin.getline(s,sizeof(s)-1);
+
+ char* p = strtok(s," ");
+ if(!p)
+ {
+ interactive_run_noisy(std::string("r"), std::vector<std::string>(1,"1"));
+ return;
+ }
+ std::string cmd = p;
+
+ std::vector<std::string> args;
+ while((p = strtok(NULL," ")))
+ args.push_back(p);
+
+
+ typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
+ std::map<std::string,interactive_func> funcs;
+
+ funcs["r"] = &sim_t::interactive_run_noisy;
+ funcs["rs"] = &sim_t::interactive_run_silent;
+ funcs["rp"] = &sim_t::interactive_run_proc_noisy;
+ funcs["rps"] = &sim_t::interactive_run_proc_silent;
+ funcs["reg"] = &sim_t::interactive_reg;
+ funcs["fregs"] = &sim_t::interactive_fregs;
+ funcs["fregd"] = &sim_t::interactive_fregd;
+ funcs["mem"] = &sim_t::interactive_mem;
+ funcs["str"] = &sim_t::interactive_str;
+ funcs["until"] = &sim_t::interactive_until;
+ funcs["while"] = &sim_t::interactive_until;
+ funcs["q"] = &sim_t::interactive_quit;
+
+ try
+ {
+ if(funcs.count(cmd))
+ (this->*funcs[cmd])(cmd, args);
+ }
+ catch(trap_t t) {}
+}
+
+void sim_t::interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args)
+{
+ interactive_run(cmd,args,true);
+}
+
+void sim_t::interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args)
+{
+ interactive_run(cmd,args,false);
+}
+
+void sim_t::interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy)
+{
+ if(args.size())
+ step_all(atoll(args[0].c_str()),1,noisy);
+ else
+ while(1) step_all(1,1,noisy);
+}
+
+void sim_t::interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args)
+{
+ interactive_run_proc(cmd,args,true);
+}
+
+void sim_t::interactive_run_proc_silent(const std::string& cmd, const std::vector<std::string>& args)
+{
+ interactive_run_proc(cmd,args,false);
+}
+
+void sim_t::interactive_run_proc(const std::string& cmd, const std::vector<std::string>& a, bool noisy)
+{
+ if(a.size() == 0)
+ return;
+
+ int p = atoi(a[0].c_str());
+ if(p >= (int)num_cores())
+ return;
+
+ if(a.size() == 2)
+ procs[p]->step(atoi(a[1].c_str()),noisy);
+ else
+ while(1) procs[p]->step(1,noisy);
+}
+
+void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
+{
+ stop();
+}
+
+reg_t sim_t::get_pc(const std::vector<std::string>& args)
+{
+ if(args.size() != 1)
+ throw trap_illegal_instruction;
+
+ int p = atoi(args[0].c_str());
+ if(p >= (int)num_cores())
+ throw trap_illegal_instruction;
+
+ return procs[p]->pc;
+}
+
+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 = atoi(args[1].c_str());
+ if(p >= (int)num_cores() || r >= NXPR)
+ throw trap_illegal_instruction;
+
+ return procs[p]->XPR[r];
+}
+
+reg_t sim_t::get_freg(const std::vector<std::string>& args)
+{
+ if(args.size() != 2)
+ throw trap_illegal_instruction;
+
+ int p = atoi(args[0].c_str());
+ int r = atoi(args[1].c_str());
+ if(p >= (int)num_cores() || r >= NFPR)
+ throw trap_illegal_instruction;
+
+ return procs[p]->FPR[r];
+}
+
+void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::string>& args)
+{
+ printf("0x%016llx\n",(unsigned long long)get_reg(args));
+}
+
+union fpr
+{
+ reg_t r;
+ float s;
+ double d;
+};
+
+void sim_t::interactive_fregs(const std::string& cmd, const std::vector<std::string>& args)
+{
+ fpr f;
+ f.r = get_freg(args);
+ printf("%g\n",f.s);
+}
+
+void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::string>& args)
+{
+ fpr f;
+ f.r = get_freg(args);
+ printf("%g\n",f.d);
+}
+
+reg_t sim_t::get_mem(const std::vector<std::string>& args)
+{
+ if(args.size() != 1 && args.size() != 2)
+ throw trap_illegal_instruction;
+
+ std::string addr_str = args[0];
+ if(args.size() == 2)
+ {
+ int p = atoi(args[0].c_str());
+ if(p >= (int)num_cores())
+ throw trap_illegal_instruction;
+ mmu->set_vm_enabled(!!(procs[p]->sr & SR_VM));
+ mmu->set_ptbr(procs[p]->mmu.get_ptbr());
+ addr_str = args[1];
+ }
+
+ reg_t addr = strtol(addr_str.c_str(),NULL,16), val;
+ if(addr == LONG_MAX)
+ addr = strtoul(addr_str.c_str(),NULL,16);
+
+ switch(addr % 8)
+ {
+ case 0:
+ val = mmu->load_uint64(addr);
+ break;
+ case 4:
+ val = mmu->load_uint32(addr);
+ break;
+ case 2:
+ case 6:
+ val = mmu->load_uint16(addr);
+ break;
+ default:
+ val = mmu->load_uint8(addr);
+ break;
+ }
+ return val;
+}
+
+void sim_t::interactive_mem(const std::string& cmd, const std::vector<std::string>& args)
+{
+ printf("0x%016llx\n",(unsigned long long)get_mem(args));
+}
+
+void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& args)
+{
+ if(args.size() != 1)
+ throw trap_illegal_instruction;
+
+ reg_t addr = strtol(args[0].c_str(),NULL,16);
+
+ char ch;
+ while((ch = mmu->load_uint8(addr++)))
+ putchar(ch);
+
+ putchar('\n');
+}
+
+void sim_t::interactive_until(const std::string& cmd, const std::vector<std::string>& args)
+{
+ if(args.size() < 3)
+ return;
+
+ std::string scmd = args[0];
+ reg_t val = strtol(args[args.size()-1].c_str(),NULL,16);
+ if(val == LONG_MAX)
+ val = strtoul(args[args.size()-1].c_str(),NULL,16);
+
+ std::vector<std::string> args2;
+ args2 = std::vector<std::string>(args.begin()+1,args.end()-1);
+
+ while(1)
+ {
+ reg_t current;
+ if(scmd == "reg")
+ current = get_reg(args2);
+ else if(scmd == "pc")
+ current = get_pc(args2);
+ else if(scmd == "mem")
+ current = get_mem(args2);
+ else if(scmd == "tohost")
+ current = tohost;
+ else
+ return;
+
+ if(cmd == "until" && current == val)
+ break;
+ if(cmd == "while" && current != val)
+ break;
+
+ step_all(1,1,false);
+ }
+}
diff --git a/riscv/mmu.cc b/riscv/mmu.cc
new file mode 100644
index 0000000..b2c8c98
--- /dev/null
+++ b/riscv/mmu.cc
@@ -0,0 +1,104 @@
+#include "mmu.h"
+#include "sim.h"
+#include "processor.h"
+
+mmu_t::mmu_t(char* _mem, size_t _memsz)
+ : mem(_mem), memsz(_memsz), badvaddr(0),
+ ptbr(0), supervisor(true), vm_enabled(false)
+{
+ flush_tlb();
+}
+
+mmu_t::~mmu_t()
+{
+}
+
+void mmu_t::flush_tlb()
+{
+ memset(tlb_insn_tag, -1, sizeof(tlb_insn_tag));
+ memset(tlb_load_tag, -1, sizeof(tlb_load_tag));
+ memset(tlb_store_tag, -1, sizeof(tlb_store_tag));
+
+ flush_icache();
+}
+
+void mmu_t::flush_icache()
+{
+ memset(icache_tag, -1, sizeof(icache_tag));
+}
+
+void* mmu_t::refill(reg_t addr, bool store, bool fetch)
+{
+ reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
+ reg_t expected_tag = addr & ~(PGSIZE-1);
+
+ reg_t pte = walk(addr);
+
+ reg_t pte_perm = pte & PTE_PERM;
+ if(supervisor) // shift supervisor permission bits into user perm bits
+ pte_perm = (pte_perm/(PTE_SX/PTE_UX)) & PTE_PERM;
+ pte_perm |= pte & PTE_E;
+
+ reg_t perm = (fetch ? PTE_UX : store ? PTE_UW : PTE_UR) | PTE_E;
+ if(unlikely((pte_perm & perm) != perm))
+ {
+ badvaddr = addr;
+ throw store ? trap_store_access_fault
+ : fetch ? trap_instruction_access_fault
+ : trap_load_access_fault;
+ }
+
+ tlb_load_tag[idx] = (pte_perm & PTE_UR) ? expected_tag : -1;
+ tlb_store_tag[idx] = (pte_perm & PTE_UW) ? expected_tag : -1;
+ tlb_insn_tag[idx] = (pte_perm & PTE_UX) ? expected_tag : -1;
+ tlb_data[idx] = (long)(pte >> PTE_PPN_SHIFT << PGSHIFT) + (long)mem;
+
+ return (void*)(((long)addr & (PGSIZE-1)) | tlb_data[idx]);
+}
+
+pte_t mmu_t::walk(reg_t addr)
+{
+ pte_t pte = 0;
+
+ if(!vm_enabled)
+ {
+ if(addr < memsz)
+ pte = PTE_E | PTE_PERM | ((addr >> PGSHIFT) << PTE_PPN_SHIFT);
+ }
+ else
+ {
+ reg_t base = 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_E)
+ {
+ // 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)) << PTE_PPN_SHIFT;
+
+ // fault if physical addr is invalid
+ reg_t ppn = ptd >> PTE_PPN_SHIFT;
+ if((ppn << PGSHIFT) + (addr & (PGSIZE-1)) < memsz)
+ pte = ptd;
+ break;
+ }
+ else if(!(ptd & PTE_T))
+ break;
+
+ base = (ptd >> PTE_PPN_SHIFT) << PGSHIFT;
+ }
+ }
+
+ return pte;
+}
diff --git a/riscv/mmu.h b/riscv/mmu.h
new file mode 100644
index 0000000..fb186ee
--- /dev/null
+++ b/riscv/mmu.h
@@ -0,0 +1,191 @@
+#ifndef _RISCV_MMU_H
+#define _RISCV_MMU_H
+
+#include "decode.h"
+#include "trap.h"
+#include "common.h"
+#include "processor.h"
+
+class processor_t;
+
+// virtual memory configuration
+typedef reg_t pte_t;
+const reg_t LEVELS = 4;
+const reg_t PGSHIFT = 12;
+const reg_t PGSIZE = 1 << PGSHIFT;
+const reg_t PTIDXBITS = PGSHIFT - (sizeof(pte_t) == 8 ? 3 : 2);
+const reg_t PPN_BITS = 8*sizeof(reg_t) - PGSHIFT;
+
+// page table entry (PTE) fields
+#define PTE_T 0x001 // Entry is a page Table descriptor
+#define PTE_E 0x002 // Entry is a page table Entry
+#define PTE_R 0x004 // Referenced
+#define PTE_D 0x008 // Dirty
+#define PTE_UX 0x010 // User eXecute permission
+#define PTE_UW 0x020 // User Read permission
+#define PTE_UR 0x040 // User Write permission
+#define PTE_SX 0x080 // Supervisor eXecute permission
+#define PTE_SW 0x100 // Supervisor Read permission
+#define PTE_SR 0x200 // Supervisor Write permission
+#define PTE_PERM (PTE_SR | PTE_SW | PTE_SX | PTE_UR | PTE_UW | PTE_UX)
+#define PTE_PERM_SHIFT 4
+#define PTE_PPN_SHIFT 12 // LSB of physical page number in the PTE
+
+// this class implements a processor's port into the virtual memory system.
+// an MMU and instruction cache are maintained for simulator performance.
+class mmu_t
+{
+public:
+ mmu_t(char* _mem, size_t _memsz);
+ ~mmu_t();
+
+ // template for functions that load an aligned value from memory
+ #define load_func(type) \
+ type##_t load_##type(reg_t addr) { \
+ if(unlikely(addr % sizeof(type##_t))) \
+ { \
+ badvaddr = addr; \
+ throw trap_load_address_misaligned; \
+ } \
+ void* paddr = translate(addr, false, false); \
+ return *(type##_t*)paddr; \
+ }
+
+ // load value from memory at aligned address; zero extend to register width
+ load_func(uint8)
+ load_func(uint16)
+ load_func(uint32)
+ load_func(uint64)
+
+ // load value from memory at aligned address; sign extend to register width
+ load_func(int8)
+ load_func(int16)
+ load_func(int32)
+ load_func(int64)
+
+ // template for functions that store an aligned value to memory
+ #define store_func(type) \
+ void store_##type(reg_t addr, type##_t val) { \
+ if(unlikely(addr % sizeof(type##_t))) \
+ { \
+ badvaddr = addr; \
+ throw trap_store_address_misaligned; \
+ } \
+ void* paddr = translate(addr, true, false); \
+ *(type##_t*)paddr = val; \
+ }
+
+ // store value to memory at aligned address
+ store_func(uint8)
+ store_func(uint16)
+ store_func(uint32)
+ store_func(uint64)
+
+ // load instruction from memory at aligned address.
+ // (needed because instruction alignment requirement is variable
+ // if RVC is supported)
+ // returns the instruction at the specified address, given the current
+ // RVC mode. func is set to a pointer to a function that knows how to
+ // execute the returned instruction.
+ insn_t __attribute__((always_inline)) load_insn(reg_t addr, bool rvc,
+ insn_func_t* func)
+ {
+ insn_t insn;
+
+ #ifdef RISCV_ENABLE_RVC
+ if(addr % 4 == 2 && rvc) // fetch across word boundary
+ {
+ void* addr_lo = translate(addr, false, true);
+ insn.bits = *(uint16_t*)addr_lo;
+
+ *func = processor_t::dispatch_table
+ [insn.bits % processor_t::DISPATCH_TABLE_SIZE];
+
+ if(!INSN_IS_RVC(insn.bits))
+ {
+ void* addr_hi = translate(addr+2, false, true);
+ insn.bits |= (uint32_t)*(uint16_t*)addr_hi << 16;
+ }
+ }
+ else
+ #endif
+ {
+ reg_t idx = (addr/sizeof(insn_t)) % ICACHE_ENTRIES;
+ insn_t data = icache_data[idx];
+ *func = icache_func[idx];
+ if(likely(icache_tag[idx] == addr))
+ return data;
+
+ // the processor guarantees alignment based upon rvc mode
+ void* paddr = translate(addr, false, true);
+ insn = *(insn_t*)paddr;
+
+ icache_tag[idx] = addr;
+ icache_data[idx] = insn;
+ icache_func[idx] = *func = processor_t::dispatch_table
+ [insn.bits % processor_t::DISPATCH_TABLE_SIZE];
+ }
+
+ return insn;
+ }
+
+ // get the virtual address that caused a fault
+ reg_t get_badvaddr() { return badvaddr; }
+
+ // get/set the page table base register
+ reg_t get_ptbr() { return ptbr; }
+ void set_ptbr(reg_t addr) { ptbr = addr & ~(PGSIZE-1); flush_tlb(); }
+
+ // keep the MMU in sync with processor mode
+ void set_supervisor(bool sup) { supervisor = sup; }
+ void set_vm_enabled(bool en) { vm_enabled = en; }
+
+ // flush the TLB and instruction cache
+ void flush_tlb();
+ void flush_icache();
+
+private:
+ char* mem;
+ size_t memsz;
+ reg_t badvaddr;
+
+ reg_t ptbr;
+ bool supervisor;
+ bool vm_enabled;
+
+ // implement a TLB for simulator performance
+ static const reg_t TLB_ENTRIES = 256;
+ long tlb_data[TLB_ENTRIES];
+ reg_t tlb_insn_tag[TLB_ENTRIES];
+ reg_t tlb_load_tag[TLB_ENTRIES];
+ reg_t tlb_store_tag[TLB_ENTRIES];
+
+ // implement an instruction cache for simulator performance
+ static const reg_t ICACHE_ENTRIES = 256;
+ insn_t icache_data[ICACHE_ENTRIES];
+ insn_func_t icache_func[ICACHE_ENTRIES];
+ reg_t icache_tag[ICACHE_ENTRIES];
+
+ // finish translation on a TLB miss and upate the TLB
+ void* refill(reg_t addr, bool store, bool fetch);
+
+ // perform a page table walk for a given virtual address
+ pte_t walk(reg_t addr);
+
+ // translate a virtual address to a physical address
+ void* translate(reg_t addr, bool store, bool fetch)
+ {
+ reg_t idx = (addr >> PGSHIFT) % TLB_ENTRIES;
+
+ reg_t* tlb_tag = fetch ? tlb_insn_tag : store ? tlb_store_tag :tlb_load_tag;
+ reg_t expected_tag = addr & ~(PGSIZE-1);
+ if(likely(tlb_tag[idx] == expected_tag))
+ return (void*)(((long)addr & (PGSIZE-1)) | tlb_data[idx]);
+
+ return refill(addr, store, fetch);
+ }
+
+ friend class processor_t;
+};
+
+#endif
diff --git a/riscv/opcodes.h b/riscv/opcodes.h
new file mode 100644
index 0000000..b37b833
--- /dev/null
+++ b/riscv/opcodes.h
@@ -0,0 +1,272 @@
+DECLARE_INSN(movn, 0x6f7, 0x1ffff)
+DECLARE_INSN(vfsstw, 0x150f, 0x1ffff)
+DECLARE_INSN(remuw, 0x7bb, 0x1ffff)
+DECLARE_INSN(fmin_d, 0x180d3, 0x1ffff)
+DECLARE_INSN(vlsthu, 0x128b, 0x1ffff)
+DECLARE_INSN(c_swsp, 0x8, 0x1f)
+DECLARE_INSN(bltu, 0x363, 0x3ff)
+DECLARE_INSN(vlsegstwu, 0xb0b, 0xfff)
+DECLARE_INSN(movz, 0x2f7, 0x1ffff)
+DECLARE_INSN(fcvt_lu_s, 0x9053, 0x3ff1ff)
+DECLARE_INSN(fence_l_cv, 0x32f, 0x3ff)
+DECLARE_INSN(fmin_s, 0x18053, 0x1ffff)
+DECLARE_INSN(c_lw0, 0x12, 0x801f)
+DECLARE_INSN(slliw, 0x9b, 0x3f83ff)
+DECLARE_INSN(lb, 0x3, 0x3ff)
+DECLARE_INSN(vlwu, 0x30b, 0x3fffff)
+DECLARE_INSN(fcvt_d_l, 0xc0d3, 0x3ff1ff)
+DECLARE_INSN(lh, 0x83, 0x3ff)
+DECLARE_INSN(fcvt_d_w, 0xe0d3, 0x3ff1ff)
+DECLARE_INSN(lw, 0x103, 0x3ff)
+DECLARE_INSN(add, 0x33, 0x1ffff)
+DECLARE_INSN(fcvt_d_s, 0x100d3, 0x3ff1ff)
+DECLARE_INSN(fence_g_v, 0x2af, 0x3ff)
+DECLARE_INSN(mfpcr, 0x17b, 0x7c1ffff)
+DECLARE_INSN(c_fsd, 0x18, 0x1f)
+DECLARE_INSN(fmax_d, 0x190d3, 0x1ffff)
+DECLARE_INSN(bne, 0xe3, 0x3ff)
+DECLARE_INSN(rdcycle, 0x277, 0x7ffffff)
+DECLARE_INSN(fcvt_s_d, 0x11053, 0x3ff1ff)
+DECLARE_INSN(vlh, 0x8b, 0x3fffff)
+DECLARE_INSN(bgeu, 0x3e3, 0x3ff)
+DECLARE_INSN(vflstd, 0x158b, 0x1ffff)
+DECLARE_INSN(c_li, 0x0, 0x1f)
+DECLARE_INSN(di, 0xfb, 0x7ffffff)
+DECLARE_INSN(sltiu, 0x193, 0x3ff)
+DECLARE_INSN(mtpcr, 0x1fb, 0xf801ffff)
+DECLARE_INSN(vlb, 0xb, 0x3fffff)
+DECLARE_INSN(stop, 0x177, 0xffffffff)
+DECLARE_INSN(vld, 0x18b, 0x3fffff)
+DECLARE_INSN(c_slli, 0x19, 0x1c1f)
+DECLARE_INSN(break, 0xf7, 0xffffffff)
+DECLARE_INSN(cflush, 0x2fb, 0xffffffff)
+DECLARE_INSN(fcvt_s_w, 0xe053, 0x3ff1ff)
+DECLARE_INSN(vflstw, 0x150b, 0x1ffff)
+DECLARE_INSN(mul, 0x433, 0x1ffff)
+DECLARE_INSN(c_lw, 0xa, 0x1f)
+DECLARE_INSN(vlw, 0x10b, 0x3fffff)
+DECLARE_INSN(vssegstw, 0x90f, 0xfff)
+DECLARE_INSN(amominu_d, 0x19ab, 0x1ffff)
+DECLARE_INSN(c_sdsp, 0x6, 0x1f)
+DECLARE_INSN(utidx, 0x1f7, 0x7ffffff)
+DECLARE_INSN(srli, 0x293, 0x3f03ff)
+DECLARE_INSN(c_srli, 0x819, 0x1c1f)
+DECLARE_INSN(c_ldsp, 0x4, 0x1f)
+DECLARE_INSN(c_flw, 0x14, 0x1f)
+DECLARE_INSN(c_srai32, 0x1419, 0x1c1f)
+DECLARE_INSN(amominu_w, 0x192b, 0x1ffff)
+DECLARE_INSN(divuw, 0x6bb, 0x1ffff)
+DECLARE_INSN(mulw, 0x43b, 0x1ffff)
+DECLARE_INSN(vssegstd, 0x98f, 0xfff)
+DECLARE_INSN(srlw, 0x2bb, 0x1ffff)
+DECLARE_INSN(vssegstb, 0x80f, 0xfff)
+DECLARE_INSN(mftx_d, 0x1c0d3, 0x7c1ffff)
+DECLARE_INSN(div, 0x633, 0x1ffff)
+DECLARE_INSN(c_ld, 0x9, 0x1f)
+DECLARE_INSN(mftx_s, 0x1c053, 0x7c1ffff)
+DECLARE_INSN(vssegsth, 0x88f, 0xfff)
+DECLARE_INSN(vvcfgivl, 0xf3, 0x3ff)
+DECLARE_INSN(j, 0x67, 0x7f)
+DECLARE_INSN(ei, 0x7b, 0x7ffffff)
+DECLARE_INSN(fence, 0x12f, 0x3ff)
+DECLARE_INSN(vsw, 0x10f, 0x3fffff)
+DECLARE_INSN(fnmsub_s, 0x4b, 0x1ff)
+DECLARE_INSN(vfssegstd, 0xd8f, 0xfff)
+DECLARE_INSN(fcvt_l_s, 0x8053, 0x3ff1ff)
+DECLARE_INSN(fle_s, 0x17053, 0x1ffff)
+DECLARE_INSN(vsb, 0xf, 0x3fffff)
+DECLARE_INSN(mffsr, 0x1d053, 0x7ffffff)
+DECLARE_INSN(fdiv_s, 0x3053, 0x1f1ff)
+DECLARE_INSN(vlstbu, 0x120b, 0x1ffff)
+DECLARE_INSN(vsetvl, 0x2f3, 0x3fffff)
+DECLARE_INSN(fle_d, 0x170d3, 0x1ffff)
+DECLARE_INSN(fence_i, 0xaf, 0x3ff)
+DECLARE_INSN(vlsegbu, 0x220b, 0x1ffff)
+DECLARE_INSN(fnmsub_d, 0xcb, 0x1ff)
+DECLARE_INSN(addw, 0x3b, 0x1ffff)
+DECLARE_INSN(sll, 0xb3, 0x1ffff)
+DECLARE_INSN(xor, 0x233, 0x1ffff)
+DECLARE_INSN(sub, 0x10033, 0x1ffff)
+DECLARE_INSN(eret, 0x27b, 0xffffffff)
+DECLARE_INSN(blt, 0x263, 0x3ff)
+DECLARE_INSN(vsstw, 0x110f, 0x1ffff)
+DECLARE_INSN(mtfsr, 0x1f053, 0x3fffff)
+DECLARE_INSN(vssth, 0x108f, 0x1ffff)
+DECLARE_INSN(rem, 0x733, 0x1ffff)
+DECLARE_INSN(srliw, 0x29b, 0x3f83ff)
+DECLARE_INSN(lui, 0x37, 0x7f)
+DECLARE_INSN(vsstb, 0x100f, 0x1ffff)
+DECLARE_INSN(fcvt_s_lu, 0xd053, 0x3ff1ff)
+DECLARE_INSN(vsstd, 0x118f, 0x1ffff)
+DECLARE_INSN(addi, 0x13, 0x3ff)
+DECLARE_INSN(vfmst, 0x1173, 0x1ffff)
+DECLARE_INSN(mulh, 0x4b3, 0x1ffff)
+DECLARE_INSN(fmul_s, 0x2053, 0x1f1ff)
+DECLARE_INSN(vlsegsthu, 0xa8b, 0xfff)
+DECLARE_INSN(srai, 0x10293, 0x3f03ff)
+DECLARE_INSN(amoand_d, 0x9ab, 0x1ffff)
+DECLARE_INSN(flt_d, 0x160d3, 0x1ffff)
+DECLARE_INSN(sraw, 0x102bb, 0x1ffff)
+DECLARE_INSN(fmul_d, 0x20d3, 0x1f1ff)
+DECLARE_INSN(ld, 0x183, 0x3ff)
+DECLARE_INSN(ori, 0x313, 0x3ff)
+DECLARE_INSN(flt_s, 0x16053, 0x1ffff)
+DECLARE_INSN(addiw, 0x1b, 0x3ff)
+DECLARE_INSN(amoand_w, 0x92b, 0x1ffff)
+DECLARE_INSN(feq_s, 0x15053, 0x1ffff)
+DECLARE_INSN(fsgnjx_d, 0x70d3, 0x1ffff)
+DECLARE_INSN(sra, 0x102b3, 0x1ffff)
+DECLARE_INSN(c_lwsp, 0x5, 0x1f)
+DECLARE_INSN(bge, 0x2e3, 0x3ff)
+DECLARE_INSN(c_add3, 0x1c, 0x31f)
+DECLARE_INSN(sraiw, 0x1029b, 0x3f83ff)
+DECLARE_INSN(vssegd, 0x218f, 0x1ffff)
+DECLARE_INSN(srl, 0x2b3, 0x1ffff)
+DECLARE_INSN(vfmts, 0x1973, 0x1ffff)
+DECLARE_INSN(fsgnjx_s, 0x7053, 0x1ffff)
+DECLARE_INSN(vfmsv, 0x973, 0x3fffff)
+DECLARE_INSN(feq_d, 0x150d3, 0x1ffff)
+DECLARE_INSN(fcvt_d_wu, 0xf0d3, 0x3ff1ff)
+DECLARE_INSN(vmts, 0x1873, 0x1ffff)
+DECLARE_INSN(or, 0x333, 0x1ffff)
+DECLARE_INSN(rdinstret, 0xa77, 0x7ffffff)
+DECLARE_INSN(fcvt_wu_d, 0xb0d3, 0x3ff1ff)
+DECLARE_INSN(subw, 0x1003b, 0x1ffff)
+DECLARE_INSN(jalr_c, 0x6b, 0x3ff)
+DECLARE_INSN(fmax_s, 0x19053, 0x1ffff)
+DECLARE_INSN(amomaxu_d, 0x1dab, 0x1ffff)
+DECLARE_INSN(c_slliw, 0x1819, 0x1c1f)
+DECLARE_INSN(jalr_j, 0x16b, 0x3ff)
+DECLARE_INSN(c_fld, 0x15, 0x1f)
+DECLARE_INSN(vlstw, 0x110b, 0x1ffff)
+DECLARE_INSN(vlsth, 0x108b, 0x1ffff)
+DECLARE_INSN(xori, 0x213, 0x3ff)
+DECLARE_INSN(jalr_r, 0xeb, 0x3ff)
+DECLARE_INSN(amomaxu_w, 0x1d2b, 0x1ffff)
+DECLARE_INSN(fcvt_wu_s, 0xb053, 0x3ff1ff)
+DECLARE_INSN(vlstb, 0x100b, 0x1ffff)
+DECLARE_INSN(vlstd, 0x118b, 0x1ffff)
+DECLARE_INSN(c_ld0, 0x8012, 0x801f)
+DECLARE_INSN(rdtime, 0x677, 0x7ffffff)
+DECLARE_INSN(andi, 0x393, 0x3ff)
+DECLARE_INSN(c_srli32, 0xc19, 0x1c1f)
+DECLARE_INSN(fsgnjn_d, 0x60d3, 0x1ffff)
+DECLARE_INSN(fnmadd_s, 0x4f, 0x1ff)
+DECLARE_INSN(jal, 0x6f, 0x7f)
+DECLARE_INSN(lwu, 0x303, 0x3ff)
+DECLARE_INSN(vlsegstbu, 0xa0b, 0xfff)
+DECLARE_INSN(c_beq, 0x10, 0x1f)
+DECLARE_INSN(vlhu, 0x28b, 0x3fffff)
+DECLARE_INSN(vfsstd, 0x158f, 0x1ffff)
+DECLARE_INSN(c_bne, 0x11, 0x1f)
+DECLARE_INSN(fnmadd_d, 0xcf, 0x1ff)
+DECLARE_INSN(fence_g_cv, 0x3af, 0x3ff)
+DECLARE_INSN(amoadd_d, 0x1ab, 0x1ffff)
+DECLARE_INSN(c_sw, 0xd, 0x1f)
+DECLARE_INSN(amomax_w, 0x152b, 0x1ffff)
+DECLARE_INSN(c_move, 0x2, 0x801f)
+DECLARE_INSN(fmovn, 0xef7, 0x1ffff)
+DECLARE_INSN(c_fsw, 0x16, 0x1f)
+DECLARE_INSN(c_j, 0x8002, 0x801f)
+DECLARE_INSN(mulhsu, 0x533, 0x1ffff)
+DECLARE_INSN(c_sd, 0xc, 0x1f)
+DECLARE_INSN(amoadd_w, 0x12b, 0x1ffff)
+DECLARE_INSN(fcvt_d_lu, 0xd0d3, 0x3ff1ff)
+DECLARE_INSN(amomax_d, 0x15ab, 0x1ffff)
+DECLARE_INSN(fcvt_w_d, 0xa0d3, 0x3ff1ff)
+DECLARE_INSN(fmovz, 0xaf7, 0x1ffff)
+DECLARE_INSN(c_or3, 0x21c, 0x31f)
+DECLARE_INSN(vmvv, 0x73, 0x3fffff)
+DECLARE_INSN(vfssegstw, 0xd0f, 0xfff)
+DECLARE_INSN(slt, 0x133, 0x1ffff)
+DECLARE_INSN(mxtf_d, 0x1e0d3, 0x3fffff)
+DECLARE_INSN(sllw, 0xbb, 0x1ffff)
+DECLARE_INSN(amoor_d, 0xdab, 0x1ffff)
+DECLARE_INSN(slti, 0x113, 0x3ff)
+DECLARE_INSN(remu, 0x7b3, 0x1ffff)
+DECLARE_INSN(flw, 0x107, 0x3ff)
+DECLARE_INSN(remw, 0x73b, 0x1ffff)
+DECLARE_INSN(sltu, 0x1b3, 0x1ffff)
+DECLARE_INSN(slli, 0x93, 0x3f03ff)
+DECLARE_INSN(c_and3, 0x31c, 0x31f)
+DECLARE_INSN(vssegw, 0x210f, 0x1ffff)
+DECLARE_INSN(amoor_w, 0xd2b, 0x1ffff)
+DECLARE_INSN(vsd, 0x18f, 0x3fffff)
+DECLARE_INSN(beq, 0x63, 0x3ff)
+DECLARE_INSN(fld, 0x187, 0x3ff)
+DECLARE_INSN(mxtf_s, 0x1e053, 0x3fffff)
+DECLARE_INSN(fsub_s, 0x1053, 0x1f1ff)
+DECLARE_INSN(and, 0x3b3, 0x1ffff)
+DECLARE_INSN(vtcfgivl, 0x1f3, 0x3ff)
+DECLARE_INSN(lbu, 0x203, 0x3ff)
+DECLARE_INSN(vf, 0x3f3, 0xf80003ff)
+DECLARE_INSN(vlsegstw, 0x90b, 0xfff)
+DECLARE_INSN(syscall, 0x77, 0xffffffff)
+DECLARE_INSN(fsgnj_s, 0x5053, 0x1ffff)
+DECLARE_INSN(c_addi, 0x1, 0x1f)
+DECLARE_INSN(vfmvv, 0x173, 0x3fffff)
+DECLARE_INSN(vlstwu, 0x130b, 0x1ffff)
+DECLARE_INSN(c_sub3, 0x11c, 0x31f)
+DECLARE_INSN(vsh, 0x8f, 0x3fffff)
+DECLARE_INSN(vlsegstb, 0x80b, 0xfff)
+DECLARE_INSN(vlsegstd, 0x98b, 0xfff)
+DECLARE_INSN(vflsegd, 0x258b, 0x1ffff)
+DECLARE_INSN(vflsegw, 0x250b, 0x1ffff)
+DECLARE_INSN(vlsegsth, 0x88b, 0xfff)
+DECLARE_INSN(fsgnj_d, 0x50d3, 0x1ffff)
+DECLARE_INSN(vflsegstw, 0xd0b, 0xfff)
+DECLARE_INSN(c_sub, 0x801a, 0x801f)
+DECLARE_INSN(mulhu, 0x5b3, 0x1ffff)
+DECLARE_INSN(fcvt_l_d, 0x80d3, 0x3ff1ff)
+DECLARE_INSN(vmsv, 0x873, 0x3fffff)
+DECLARE_INSN(vmst, 0x1073, 0x1ffff)
+DECLARE_INSN(fadd_d, 0xd3, 0x1f1ff)
+DECLARE_INSN(fcvt_s_wu, 0xf053, 0x3ff1ff)
+DECLARE_INSN(rdnpc, 0x26b, 0x7ffffff)
+DECLARE_INSN(fcvt_s_l, 0xc053, 0x3ff1ff)
+DECLARE_INSN(vflsegstd, 0xd8b, 0xfff)
+DECLARE_INSN(c_add, 0x1a, 0x801f)
+DECLARE_INSN(fcvt_lu_d, 0x90d3, 0x3ff1ff)
+DECLARE_INSN(vfld, 0x58b, 0x3fffff)
+DECLARE_INSN(fsub_d, 0x10d3, 0x1f1ff)
+DECLARE_INSN(fmadd_s, 0x43, 0x1ff)
+DECLARE_INSN(fcvt_w_s, 0xa053, 0x3ff1ff)
+DECLARE_INSN(vssegh, 0x208f, 0x1ffff)
+DECLARE_INSN(fsqrt_s, 0x4053, 0x3ff1ff)
+DECLARE_INSN(c_srai, 0x1019, 0x1c1f)
+DECLARE_INSN(amomin_w, 0x112b, 0x1ffff)
+DECLARE_INSN(fsgnjn_s, 0x6053, 0x1ffff)
+DECLARE_INSN(c_slli32, 0x419, 0x1c1f)
+DECLARE_INSN(vlsegwu, 0x230b, 0x1ffff)
+DECLARE_INSN(vfsw, 0x50f, 0x3fffff)
+DECLARE_INSN(amoswap_d, 0x5ab, 0x1ffff)
+DECLARE_INSN(fence_l_v, 0x22f, 0x3ff)
+DECLARE_INSN(fsqrt_d, 0x40d3, 0x3ff1ff)
+DECLARE_INSN(vflw, 0x50b, 0x3fffff)
+DECLARE_INSN(fdiv_d, 0x30d3, 0x1f1ff)
+DECLARE_INSN(fmadd_d, 0xc3, 0x1ff)
+DECLARE_INSN(divw, 0x63b, 0x1ffff)
+DECLARE_INSN(amomin_d, 0x11ab, 0x1ffff)
+DECLARE_INSN(divu, 0x6b3, 0x1ffff)
+DECLARE_INSN(amoswap_w, 0x52b, 0x1ffff)
+DECLARE_INSN(vfsd, 0x58f, 0x3fffff)
+DECLARE_INSN(fadd_s, 0x53, 0x1f1ff)
+DECLARE_INSN(vlsegb, 0x200b, 0x1ffff)
+DECLARE_INSN(fsd, 0x1a7, 0x3ff)
+DECLARE_INSN(vlsegd, 0x218b, 0x1ffff)
+DECLARE_INSN(vlsegh, 0x208b, 0x1ffff)
+DECLARE_INSN(sw, 0x123, 0x3ff)
+DECLARE_INSN(fmsub_s, 0x47, 0x1ff)
+DECLARE_INSN(vfssegw, 0x250f, 0x1ffff)
+DECLARE_INSN(c_addiw, 0x1d, 0x1f)
+DECLARE_INSN(lhu, 0x283, 0x3ff)
+DECLARE_INSN(sh, 0xa3, 0x3ff)
+DECLARE_INSN(vlsegw, 0x210b, 0x1ffff)
+DECLARE_INSN(fsw, 0x127, 0x3ff)
+DECLARE_INSN(vlbu, 0x20b, 0x3fffff)
+DECLARE_INSN(sb, 0x23, 0x3ff)
+DECLARE_INSN(fmsub_d, 0xc7, 0x1ff)
+DECLARE_INSN(vlseghu, 0x228b, 0x1ffff)
+DECLARE_INSN(vssegb, 0x200f, 0x1ffff)
+DECLARE_INSN(vfssegd, 0x258f, 0x1ffff)
+DECLARE_INSN(sd, 0x1a3, 0x3ff)
diff --git a/riscv/processor.cc b/riscv/processor.cc
new file mode 100644
index 0000000..2a53cca
--- /dev/null
+++ b/riscv/processor.cc
@@ -0,0 +1,240 @@
+#include "processor.h"
+#include "common.h"
+#include "config.h"
+#include "sim.h"
+#include <bfd.h>
+#include <dis-asm.h>
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <assert.h>
+
+processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
+ : sim(*_sim), mmu(*_mmu), id(_id), utidx(0)
+{
+ reset();
+
+ // create microthreads
+ for (int i=0; i<MAX_UTS; i++)
+ uts[i] = new processor_t(&sim, &mmu, id, i);
+}
+
+processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id,
+ uint32_t _utidx)
+ : sim(*_sim), mmu(*_mmu), id(_id), utidx(_utidx)
+{
+ reset();
+ set_sr(sr | SR_EF | SR_EV);
+
+ // microthreads don't possess their own microthreads
+ for (int i=0; i<MAX_UTS; i++)
+ uts[i] = NULL;
+}
+
+processor_t::~processor_t()
+{
+}
+
+void processor_t::reset()
+{
+ run = false;
+
+ // the ISA guarantees the following initial state
+ set_sr(SR_S | SR_SX);
+ pc = 0;
+
+ // the following state is undefined upon boot-up,
+ // but we zero it for determinism
+ memset(XPR,0,sizeof(XPR));
+ memset(FPR,0,sizeof(FPR));
+
+ evec = 0;
+ epc = 0;
+ badvaddr = 0;
+ cause = 0;
+ pcr_k0 = 0;
+ pcr_k1 = 0;
+ count = 0;
+ compare = 0;
+ cycle = 0;
+ set_fsr(0);
+
+ // vector stuff
+ vecbanks = 0xff;
+ vecbanks_count = 8;
+ utidx = -1;
+ vlmax = 32;
+ vl = 0;
+ nxfpr_bank = 256;
+ nxpr_use = 32;
+ nfpr_use = 32;
+}
+
+void processor_t::set_sr(uint32_t val)
+{
+ sr = val & ~SR_ZERO; // clear SR bits that read as zero
+
+#ifndef RISCV_ENABLE_64BIT
+ sr &= ~(SR_SX | SR_UX); // SX=UX=0 for RV32 implementations
+#endif
+#ifndef RISCV_ENABLE_FPU
+ sr &= ~SR_EF;
+#endif
+#ifndef RISCV_ENABLE_RVC
+ sr &= ~SR_EC;
+#endif
+#ifndef RISCV_ENABLE_VEC
+ sr &= ~SR_EV;
+#endif
+
+ // update MMU state and flush TLB
+ mmu.set_vm_enabled(sr & SR_VM);
+ mmu.set_supervisor(sr & SR_S);
+ mmu.flush_tlb();
+
+ // set the fixed-point register length
+ xprlen = ((sr & SR_S) ? (sr & SR_SX) : (sr & SR_UX)) ? 64 : 32;
+}
+
+void processor_t::set_fsr(uint32_t val)
+{
+ fsr = val & ~FSR_ZERO; // clear FSR bits that read as zero
+}
+
+void processor_t::vcfg()
+{
+ if (nxpr_use + nfpr_use < 2)
+ vlmax = nxfpr_bank * vecbanks_count;
+ else
+ vlmax = (nxfpr_bank / (nxpr_use + nfpr_use - 1)) * vecbanks_count;
+
+ vlmax = std::min(vlmax, MAX_UTS);
+}
+
+void processor_t::setvl(int vlapp)
+{
+ vl = std::min(vlmax, vlapp);
+}
+
+void processor_t::take_interrupt()
+{
+ uint32_t interrupts = (cause & CAUSE_IP) >> CAUSE_IP_SHIFT;
+ interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
+
+ if(interrupts && (sr & SR_ET))
+ throw trap_interrupt;
+}
+
+void processor_t::step(size_t n, bool noisy)
+{
+ if(!run)
+ return;
+
+ size_t i = 0;
+ while(1) try
+ {
+ take_interrupt();
+
+ mmu_t& _mmu = mmu;
+ insn_t insn;
+ insn_func_t func;
+ reg_t npc = pc;
+
+ // execute_insn fetches and executes one instruction
+ #define execute_insn(noisy) \
+ do { \
+ insn = _mmu.load_insn(npc, sr & SR_EC, &func); \
+ if(noisy) disasm(insn,pc); \
+ npc = func(this, insn, npc); \
+ pc = npc; \
+ } while(0)
+
+ if(noisy) for( ; i < n; i++) // print out instructions as we go
+ execute_insn(true);
+ else
+ {
+ // unrolled for speed
+ for( ; n > 3 && i < n-3; i+=4)
+ {
+ execute_insn(false);
+ execute_insn(false);
+ execute_insn(false);
+ execute_insn(false);
+ }
+ for( ; i < n; i++)
+ execute_insn(false);
+ }
+
+ break;
+ }
+ catch(trap_t t)
+ {
+ // an exception occurred in the target processor
+ i++;
+ take_trap(t,noisy);
+ }
+ catch(vt_command_t cmd)
+ {
+ // this microthread has finished
+ i++;
+ assert(cmd == vt_command_stop);
+ break;
+ }
+ catch(halt_t t)
+ {
+ // sleep until IPI
+ reset();
+ return;
+ }
+
+ cycle += i;
+
+ // update timer and possibly register a timer interrupt
+ uint32_t old_count = count;
+ count += i;
+ if(old_count < compare && uint64_t(old_count) + i >= compare)
+ cause |= 1 << (TIMER_IRQ+CAUSE_IP_SHIFT);
+}
+
+void processor_t::take_trap(trap_t t, bool noisy)
+{
+ if(noisy)
+ printf("core %3d: trap %s, pc 0x%016llx\n",
+ id, trap_name(t), (unsigned long long)pc);
+
+ // switch to supervisor, set previous supervisor bit, disable traps
+ set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
+ cause = (cause & ~CAUSE_EXCCODE) | (t << CAUSE_EXCCODE_SHIFT);
+ epc = pc;
+ pc = evec;
+ badvaddr = mmu.get_badvaddr();
+}
+
+void processor_t::deliver_ipi()
+{
+ cause |= 1 << (IPI_IRQ+CAUSE_IP_SHIFT);
+ run = true;
+}
+
+void processor_t::disasm(insn_t insn, reg_t pc)
+{
+ printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);
+
+ #ifdef RISCV_HAVE_LIBOPCODES
+ disassemble_info info;
+ INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
+ info.flavour = bfd_target_unknown_flavour;
+ info.arch = bfd_arch_mips;
+ info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
+ info.endian = BFD_ENDIAN_LITTLE;
+ info.buffer = (bfd_byte*)&insn;
+ info.buffer_length = sizeof(insn);
+ info.buffer_vma = pc;
+
+ int ret = print_insn_little_mips(pc, &info);
+ assert(ret == insn_length(insn.bits));
+ #else
+ printf("unknown");
+ #endif
+ printf("\n");
+}
diff --git a/riscv/processor.h b/riscv/processor.h
new file mode 100644
index 0000000..3bc1177
--- /dev/null
+++ b/riscv/processor.h
@@ -0,0 +1,89 @@
+#ifndef _RISCV_PROCESSOR_H
+#define _RISCV_PROCESSOR_H
+
+#include "decode.h"
+#include <cstring>
+#include "trap.h"
+
+#define MAX_UTS 2048
+
+class processor_t;
+class mmu_t;
+typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t);
+class sim_t;
+
+// this class represents one processor in a RISC-V machine.
+class processor_t
+{
+public:
+ processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id);
+ ~processor_t();
+
+ void step(size_t n, bool noisy); // run for n cycles
+ void deliver_ipi(); // register an interprocessor interrupt
+
+private:
+ sim_t& sim;
+ mmu_t& mmu; // main memory is always accessed via the mmu
+
+ // user-visible architected state
+ reg_t XPR[NXPR];
+ freg_t FPR[NFPR];
+ reg_t pc;
+ uint32_t fsr;
+
+ // counters
+ reg_t cycle;
+
+ // privileged control registers
+ reg_t epc;
+ reg_t badvaddr;
+ reg_t cause;
+ reg_t evec;
+ reg_t pcr_k0;
+ reg_t pcr_k1;
+ uint32_t id;
+ uint32_t sr; // only modify the status register using set_sr()
+ uint32_t count;
+ uint32_t compare;
+
+ // # of bits in an XPR (32 or 64). (redundant with sr)
+ int xprlen;
+
+ // is this processor running? (deliver_ipi() sets this)
+ bool run;
+
+ // functions
+ void reset(); // resets architected state; halts processor if it was running
+ void take_interrupt(); // take a trap if any interrupts are pending
+ void set_sr(uint32_t val); // set the status register
+ void set_fsr(uint32_t val); // set the floating-point status register
+ void take_trap(trap_t t, bool noisy); // take an exception
+ void disasm(insn_t insn, reg_t pc); // disassemble and print an instruction
+
+ // vector stuff
+ void vcfg();
+ void setvl(int vlapp);
+
+ reg_t vecbanks;
+ uint32_t vecbanks_count;
+
+ bool utmode;
+ uint32_t utidx;
+ int vlmax;
+ int vl;
+ int nxfpr_bank;
+ int nxpr_use;
+ int nfpr_use;
+ processor_t* uts[MAX_UTS];
+
+ // this constructor is used for each of the uts
+ processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id, uint32_t _utidx);
+
+ friend class sim_t;
+ friend class mmu_t;
+
+ #include "dispatch.h"
+};
+
+#endif
diff --git a/riscv/riscv-isa-run.cc b/riscv/riscv-isa-run.cc
new file mode 100644
index 0000000..a0af8de
--- /dev/null
+++ b/riscv/riscv-isa-run.cc
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include "sim.h"
+#include "htif.h"
+
+static void help()
+{
+ fprintf(stderr, "usage: riscv-isa-run -f <fd> -t <fd> [additional options]\n");
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -f <fd> From-host pipe file descriptor\n");
+ fprintf(stderr, " -t <fd> To-host pipe file descriptor\n");
+ fprintf(stderr, " -p <n> Simulate <n> processors\n");
+ fprintf(stderr, " -d Interactive debug mode\n");
+ exit(1);
+}
+
+int main(int argc, char** argv)
+{
+ bool debug = false;
+ int nprocs = 1;
+ int fromhost_fd = -1, tohost_fd = -1;
+
+ // parse command-line arguments
+ for(int c; (c = getopt(argc,argv,"hdp:f:t:")) != -1; )
+ {
+ switch(c)
+ {
+ case 'd':
+ debug = true;
+ break;
+ case 'p':
+ nprocs = atoi(optarg);
+ break;
+ case 'f':
+ fromhost_fd = atoi(optarg);
+ break;
+ case 't':
+ tohost_fd = atoi(optarg);
+ break;
+ default:
+ fprintf(stderr, "unknown option: -%c", optopt);
+ case 'h':
+ help();
+ }
+ }
+
+ // we require -f and -t to be specified so we can communicate with the host
+ if(fromhost_fd == -1 || tohost_fd == -1)
+ help();
+
+ // initialize host-target interface
+ htif_t htif(tohost_fd, fromhost_fd);
+
+ // initalize simulator and run to completion
+ sim_t s(nprocs, &htif);
+ s.run(debug);
+}
diff --git a/riscv/riscv.ac b/riscv/riscv.ac
new file mode 100644
index 0000000..5766d6d
--- /dev/null
+++ b/riscv/riscv.ac
@@ -0,0 +1,32 @@
+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([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([rvc], AS_HELP_STRING([--enable-rvc], [Enable instruction compression]))
+AS_IF([test "x$enable_rvc" = "xyes"], [
+ AC_DEFINE([RISCV_ENABLE_RVC],,[Define if instruction compression is supported])
+])
+
+AC_ARG_ENABLE([vec], AS_HELP_STRING([--disable-vec], [Disable vector processor]))
+AS_IF([test "x$enable_vec" != "xno"], [
+ AC_DEFINE([RISCV_ENABLE_VEC],,[Define if vector processor is supported])
+])
+
+libopc=`dirname \`which riscv-gcc\``/../`$ac_config_guess`/riscv/lib/libopcodes.a
+AC_CHECK_FILES([$libopc],[have_libopcodes="yes"],[have_libopcodes="no"])
+
+AC_SEARCH_LIBS([bfd_init],[bfd],[],[have_libopcodes="no"])
+
+AS_IF([test "$have_libopcodes" = "no"],[
+ AC_MSG_WARN([Could not find opcodes library])
+ AC_MSG_WARN([Build will not include disassembly support])
+],[
+ LIBS="$libopc $LIBS"
+ AC_DEFINE([RISCV_HAVE_LIBOPCODES],,[Define if libopcodes exists])
+])
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
new file mode 100644
index 0000000..50dc76a
--- /dev/null
+++ b/riscv/riscv.mk.in
@@ -0,0 +1,50 @@
+riscv_subproject_deps = \
+ softfloat_riscv \
+ softfloat \
+
+riscv_hdrs = \
+ htif.h \
+ common.h \
+ decode.h \
+ mmu.h \
+ processor.h \
+ sim.h \
+ trap.h \
+ opcodes.h \
+ insn_header.h \
+ dispatch.h \
+
+NDISPATCH := 10
+DISPATCH_SRCS := \
+ dispatch0.cc \
+ dispatch1.cc \
+ dispatch2.cc \
+ dispatch3.cc \
+ dispatch4.cc \
+ dispatch5.cc \
+ dispatch6.cc \
+ dispatch7.cc \
+ dispatch8.cc \
+ dispatch9.cc \
+ dispatch10.cc \
+
+$(DISPATCH_SRCS): %.cc: dispatch $(wildcard insns/*.h) $(riscv_hdrs)
+ $< $(subst dispatch,,$(subst .cc,,$@)) $(NDISPATCH) 1024 < $(src_dir)/riscv/opcodes.h > $@
+
+$(src_dir)/riscv/dispatch.h: %.h: dispatch
+ $< $(NDISPATCH) 1024 < $(src_dir)/riscv/opcodes.h > $@
+
+riscv_srcs = \
+ htif.cc \
+ processor.cc \
+ sim.cc \
+ interactive.cc \
+ trap.cc \
+ icsim.cc \
+ mmu.cc \
+ $(DISPATCH_SRCS) \
+
+riscv_test_srcs =
+
+riscv_install_prog_srcs = \
+ riscv-isa-run.cc \
diff --git a/riscv/sim.cc b/riscv/sim.cc
new file mode 100644
index 0000000..85d0995
--- /dev/null
+++ b/riscv/sim.cc
@@ -0,0 +1,92 @@
+#include "sim.h"
+#include "htif.h"
+#include <sys/mman.h>
+#include <map>
+#include <iostream>
+#include <climits>
+#include <assert.h>
+
+sim_t::sim_t(int _nprocs, htif_t* _htif)
+ : htif(_htif),
+ procs(_nprocs),
+ running(false)
+{
+ // allocate target machine's memory, shrinking it as necessary
+ // until the allocation succeeds
+
+ size_t memsz0 = sizeof(size_t) == 8 ? 0x100000000ULL : 0x70000000UL;
+ size_t quantum = std::max(PGSIZE, (reg_t)sysconf(_SC_PAGESIZE));
+ memsz0 = memsz0/quantum*quantum;
+
+ memsz = memsz0;
+ mem = (char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+
+ if(mem == MAP_FAILED)
+ {
+ while(mem == MAP_FAILED && (memsz = memsz*10/11/quantum*quantum))
+ mem = (char*)mmap64(NULL, memsz, PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ assert(mem != MAP_FAILED);
+ fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n",
+ (unsigned long)memsz, (unsigned long)memsz0);
+ }
+
+ mmu = new mmu_t(mem, memsz);
+
+ for(size_t i = 0; i < num_cores(); i++)
+ procs[i] = new processor_t(this, new mmu_t(mem, memsz), i);
+
+ htif->init(this);
+}
+
+sim_t::~sim_t()
+{
+ for(size_t i = 0; i < num_cores(); i++)
+ {
+ mmu_t* pmmu = &procs[i]->mmu;
+ delete procs[i];
+ delete pmmu;
+ }
+ delete mmu;
+ munmap(mem, memsz);
+}
+
+void sim_t::set_tohost(reg_t val)
+{
+ fromhost = 0;
+ tohost = val;
+}
+
+reg_t sim_t::get_fromhost()
+{
+ htif->wait_for_fromhost_write();
+ return fromhost;
+}
+
+void sim_t::send_ipi(reg_t who)
+{
+ if(who < num_cores())
+ procs[who]->deliver_ipi();
+}
+
+void sim_t::run(bool debug)
+{
+ htif->wait_for_start();
+
+ // start core 0
+ send_ipi(0);
+
+ for(running = true; running; )
+ {
+ if(!debug)
+ step_all(100,100,false);
+ else
+ interactive();
+ }
+}
+
+void sim_t::step_all(size_t n, size_t interleave, bool noisy)
+{
+ for(size_t j = 0; j < n; j+=interleave)
+ for(int i = 0; i < (int)num_cores(); i++)
+ procs[i]->step(interleave,noisy);
+}
diff --git a/riscv/sim.h b/riscv/sim.h
new file mode 100644
index 0000000..c4058d3
--- /dev/null
+++ b/riscv/sim.h
@@ -0,0 +1,82 @@
+#ifndef _RISCV_SIM_H
+#define _RISCV_SIM_H
+
+#include <vector>
+#include <string>
+#include "processor.h"
+#include "mmu.h"
+
+class htif_t;
+
+// this class encapsulates the processors and memory in a RISC-V machine.
+class sim_t
+{
+public:
+ sim_t(int _nprocs, htif_t* _htif);
+ ~sim_t();
+
+ // run the simulation to completion
+ void run(bool debug);
+
+ // communicate with the host machine
+ void set_tohost(reg_t val);
+ reg_t get_fromhost();
+
+ // deliver an IPI to a specific processor
+ void send_ipi(reg_t who);
+
+ // returns the number of processors in this simulator
+ size_t num_cores() { return procs.size(); }
+
+private:
+ htif_t* htif;
+
+ // global registers for communication with host machine
+ reg_t tohost;
+ reg_t fromhost;
+
+ // main memory, shared between processors
+ char* mem;
+ size_t memsz; // memory size in bytes
+ mmu_t* mmu; // debug port into main memory
+
+ // processors
+ std::vector<processor_t*> procs;
+
+ // terminate the simulation loop after the current iteration
+ void stop() { running = false; }
+ bool running;
+
+ // run each processor for n instructions; interleave instructions are
+ // run on a processor before moving on to the next processor.
+ // interleave must divide n.
+ // if noisy, print out the instructions as they execute.
+ void step_all(size_t n, size_t interleave, bool noisy);
+
+ // presents a prompt for introspection into the simulation
+ void interactive();
+
+ // functions that help implement interactive()
+ void interactive_quit(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_run(const std::string& cmd, const std::vector<std::string>& args, bool noisy);
+ void interactive_run_noisy(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_run_silent(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_run_proc(const std::string& cmd, const std::vector<std::string>& args, bool noisy);
+ void interactive_run_proc_noisy(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_run_proc_silent(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_reg(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_fregs(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_fregd(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_mem(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_str(const std::string& cmd, const std::vector<std::string>& args);
+ void interactive_until(const std::string& cmd, const std::vector<std::string>& args);
+ reg_t get_reg(const std::vector<std::string>& args);
+ reg_t get_freg(const std::vector<std::string>& args);
+ reg_t get_mem(const std::vector<std::string>& args);
+ reg_t get_pc(const std::vector<std::string>& args);
+ reg_t get_tohost(const std::vector<std::string>& args);
+
+ friend class htif_t;
+};
+
+#endif
diff --git a/riscv/trap.cc b/riscv/trap.cc
new file mode 100644
index 0000000..d873a19
--- /dev/null
+++ b/riscv/trap.cc
@@ -0,0 +1,10 @@
+#include "trap.h"
+
+const char* trap_name(trap_t t)
+{
+ #define DECLARE_TRAP(x) "trap_"#x
+ static const char* names[] = { TRAP_LIST };
+ #undef DECLARE_TRAP
+
+ return (unsigned)t >= sizeof(names)/sizeof(names[0]) ? "unknown" : names[t];
+}
diff --git a/riscv/trap.h b/riscv/trap.h
new file mode 100644
index 0000000..ad5491a
--- /dev/null
+++ b/riscv/trap.h
@@ -0,0 +1,44 @@
+#ifndef _RISCV_TRAP_H
+#define _RISCV_TRAP_H
+
+#define TRAP_LIST \
+ DECLARE_TRAP(instruction_address_misaligned), \
+ DECLARE_TRAP(instruction_access_fault), \
+ DECLARE_TRAP(illegal_instruction), \
+ DECLARE_TRAP(privileged_instruction), \
+ DECLARE_TRAP(fp_disabled), \
+ DECLARE_TRAP(interrupt), \
+ DECLARE_TRAP(syscall), \
+ DECLARE_TRAP(breakpoint), \
+ DECLARE_TRAP(load_address_misaligned), \
+ DECLARE_TRAP(store_address_misaligned), \
+ DECLARE_TRAP(load_access_fault), \
+ DECLARE_TRAP(store_access_fault), \
+ DECLARE_TRAP(vector_disabled), \
+ DECLARE_TRAP(vector_bank), \
+ DECLARE_TRAP(vector_illegal_instruction), \
+ DECLARE_TRAP(reserved1), \
+ DECLARE_TRAP(reserved2), \
+ DECLARE_TRAP(reserved3), \
+ DECLARE_TRAP(int0), \
+ DECLARE_TRAP(int1), \
+ DECLARE_TRAP(int2), \
+ DECLARE_TRAP(int3), \
+ DECLARE_TRAP(int4), \
+ DECLARE_TRAP(int5), \
+ DECLARE_TRAP(int6), \
+ DECLARE_TRAP(int7), \
+
+#define DECLARE_TRAP(x) trap_##x
+enum trap_t
+{
+ TRAP_LIST
+ NUM_TRAPS
+};
+#undef DECLARE_TRAP
+
+struct halt_t {}; // thrown to stop the processor from running
+
+extern "C" const char* trap_name(trap_t t);
+
+#endif