diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4cf06263863358a718d4b374c9b756e72db27ad1..78a85ac689afdc82bf0928f2f262362638382e66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 - Official support for floating point unit
 - Added AXI-64bit adapter for write-through cache system
 - Added AXI atomic ops and exclusive access support to write-through cache system
+- Provision `riscv-isa-sim` tandem simulation
+- Support for preloading
 
 ### Changed
 
@@ -19,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
 - Fixed problem which decoded compressed hints as illegal instructions
 - Reduce clock frequency of FPGA to 30 MHz to accomodate FPU
 - Bugfixes in write-through cache system
+- ID width fix in random delayer
 
 ### 4.0.0
 
diff --git a/Makefile b/Makefile
index 2ac83f0c74be662fd9b53baea5073a348985594a..5e66ea8edf81e2e9fdf12e168e5b591d245c9046 100644
--- a/Makefile
+++ b/Makefile
@@ -41,20 +41,28 @@ ifndef RISCV
 $(error RISCV not set - please point your RISCV variable to your RISCV installation)
 endif
 
+# spike tandem verification
+ifdef spike-tandem
+    compile_flag += -define SPIKE_TANDEM
+    ifndef preload
+        $(error Tandem verification requires preloading)
+    endif
+endif
+
 # Sources
 # Package files -> compile first
 ariane_pkg := include/riscv_pkg.sv                          \
-			        src/riscv-dbg/src/dm_pkg.sv                   \
-			        include/ariane_pkg.sv                         \
-			        include/std_cache_pkg.sv                      \
-			        include/serpent_cache_pkg.sv                  \
-			        src/axi/src/axi_pkg.sv                        \
-			        src/register_interface/src/reg_intf.sv        \
-			        include/axi_intf.sv                           \
-			        tb/ariane_soc_pkg.sv                          \
-			        include/ariane_axi_pkg.sv                     \
-			        src/fpu/src/fpnew_pkg.sv                      \
-			        src/fpu/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
+			  src/riscv-dbg/src/dm_pkg.sv                   \
+			  include/ariane_pkg.sv                         \
+			  include/std_cache_pkg.sv                      \
+			  include/serpent_cache_pkg.sv                  \
+			  src/axi/src/axi_pkg.sv                        \
+			  src/register_interface/src/reg_intf.sv        \
+			  include/axi_intf.sv                           \
+			  tb/ariane_soc_pkg.sv                          \
+			  include/ariane_axi_pkg.sv                     \
+			  src/fpu/src/fpnew_pkg.sv                      \
+			  src/fpu/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
 ariane_pkg := $(addprefix $(root-dir), $(ariane_pkg))
 
 # utility modules
@@ -64,18 +72,34 @@ util := $(wildcard src/util/*.svh)                          \
         src/tech_cells_generic/src/cluster_clock_gating.sv  \
         tb/common/mock_uart.sv                              \
         src/util/sram.sv
+
+ifdef spike-tandem
+    util += tb/common/spike.sv
+endif
+
 util := $(addprefix $(root-dir), $(util))
 # Test packages
 test_pkg := $(wildcard tb/test/*/*sequence_pkg.sv*) \
 			$(wildcard tb/test/*/*_pkg.sv*)
 # DPI
-dpi := $(patsubst tb/dpi/%.cc,${dpi-library}/%.o,$(wildcard tb/dpi/*.cc))
+dpi_list := $(patsubst tb/dpi/%.cc, ${dpi-library}/%.o, $(wildcard tb/dpi/*.cc))
+# filter spike stuff if tandem is not activated
+ifndef spike-tandem
+    dpi = $(filter-out ${dpi-library}/spike.o ${dpi-library}/sim_spike.o, $(dpi_list))
+else
+    dpi = $(dpi_list)
+endif
+
 dpi_hdr := $(wildcard tb/dpi/*.h)
 dpi_hdr := $(addprefix $(root-dir), $(dpi_hdr))
 CFLAGS := -I$(QUESTASIM_HOME)/include         \
           -I$(RISCV)/include                  \
           -std=c++11 -I../tb/dpi
 
+ifdef spike-tandem
+    CFLAGS += -Itb/riscv-isa-sim/install/include/spike
+endif
+
 # this list contains the standalone components
 src :=  $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv))              \
         $(filter-out src/fpu/src/fpnew_pkg.sv, $(wildcard src/fpu/src/*.sv))   \
@@ -198,12 +222,12 @@ endif
 ifdef preload
 	questa-cmd += +PRELOAD=$(preload)
 	elf-bin = none
-	# tandem verify with spike, this requires pre-loading
-	ifdef tandem
-		compile_flag += +define+TANDEM
-		questa-cmd += -gblso tb/riscv-isa-sim/install/lib/libriscv.so
-	endif
 endif
+
+ifdef spike-tandem
+    questa-cmd += -gblso tb/riscv-isa-sim/install/lib/libriscv.so
+endif
+
 # remote bitbang is enabled
 ifdef rbb
 	questa-cmd += +jtag_rbb_enable=1
@@ -252,7 +276,7 @@ $(dpi-library)/ariane_dpi.so: $(dpi)
 # alternatively you can call make sim elf-bin=<path/to/elf-bin> in order to load an arbitrary binary
 sim: build
 	vsim${questa_version} +permissive $(questa-flags) $(questa-cmd) -lib $(library) +MAX_CYCLES=$(max_cycles) +UVM_TESTNAME=$(test_case) \
-	+BASEDIR=$(riscv-test-dir) $(uvm-flags) $(QUESTASIM_FLAGS) -gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi        \
+	+BASEDIR=$(riscv-test-dir) $(uvm-flags) $(QUESTASIM_FLAGS) -gblso $(RISCV)/lib/libfesvr.so -sv_lib $(dpi-library)/ariane_dpi  \
 	${top_level}_optimized +permissive-off ++$(elf-bin) ++$(target-options) | tee sim.log
 
 $(riscv-asm-tests): build
@@ -353,7 +377,7 @@ $(addsuffix -verilator,$(riscv-asm-tests)): verilate
 	$(ver-library)/Variane_testharness $(riscv-test-dir)/$(subst -verilator,,$@)
 
 $(addsuffix -verilator,$(riscv-amo-tests)): verilate
-	$(ver-library)/Variane_testharness $(riscv-test-dir)/$(subst -verilator,,$@) 
+	$(ver-library)/Variane_testharness $(riscv-test-dir)/$(subst -verilator,,$@)
 
 $(addsuffix -verilator,$(riscv-mul-tests)): verilate
 	$(ver-library)/Variane_testharness $(riscv-test-dir)/$(subst -verilator,,$@)
@@ -425,18 +449,23 @@ check-torture:
 	grep 'All signatures match for $(test-location)' $(riscv-torture-dir)/$(test-location).log
 	diff -s $(riscv-torture-dir)/$(test-location).spike.sig $(riscv-torture-dir)/$(test-location).rtlsim.sig
 
+fpga_filter := $(addprefix $(root-dir), bootrom/bootrom.sv)
+
 fpga: $(ariane_pkg) $(util) $(src) $(fpga_src) $(util) $(uart_src)
 	@echo "[FPGA] Generate sources"
 	@echo read_vhdl        {$(uart_src)}    > fpga/scripts/add_sources.tcl
 	@echo read_verilog -sv {$(ariane_pkg)} >> fpga/scripts/add_sources.tcl
 	@echo read_verilog -sv {$(util)}       >> fpga/scripts/add_sources.tcl
-	@echo read_verilog -sv {$(filter-out bootrom.sv, $(src))} 	   >> fpga/scripts/add_sources.tcl
+	@echo read_verilog -sv {$(filter-out $(fpga_filter), $(src))} 	   >> fpga/scripts/add_sources.tcl
 	@echo read_verilog -sv {$(fpga_src)}   >> fpga/scripts/add_sources.tcl
 	@echo "[FPGA] Generate Bitstream"
 	cd fpga && make BOARD="genesys2" XILINX_PART="xc7k325tffg900-2" XILINX_BOARD="digilentinc.com:genesys2:part0:1.1" CLK_PERIOD_NS="20"
 
 .PHONY: fpga
 
+build-spike:
+	cd tb/riscv-isa-sim && mkdir -p build && cd build && ../configure --prefix=`pwd`/../install --with-fesvr=$(RISCV) --enable-commitlog && make -j8 install
+
 clean:
 	rm -rf $(riscv-torture-dir)/output/test*
 	rm -rf $(library)/ $(dpi-library)/ $(ver-library)/
diff --git a/README.md b/README.md
index 8d091751b1ae0937781a37fef0c6c212618e007e..30fef013c78c6b133928b3681bf23205a0ca0b99 100644
--- a/README.md
+++ b/README.md
@@ -291,6 +291,18 @@ $ make
 $ [sudo] make install
 ```
 
+### Memory Preloading
+
+In standard configuration the debug module will take care of loading the memory content. It will also handle communication with `riscv-fesvr`.
+Depending on the scenario this might not be diserable (e.g.: preloading of a large elf or linux boot in simulation). You can use the preload elf flag to specify the path
+to a binary which will be preloaded.
+
+> You will loose all `riscv-fesvr` communcation like sytemcalls and eoc capabilities.
+
+```
+$ make sim preload=elf
+```
+
 <!-- ### Tandem Verification with Spike
 
 ```
diff --git a/bootrom/ariane.dts b/bootrom/ariane.dts
index 34153911ca40ef6cbf49b39b367c61e0c8d78de9..9cd2df99f297c62372f2e8d2d0cc464ae2309431 100644
--- a/bootrom/ariane.dts
+++ b/bootrom/ariane.dts
@@ -5,9 +5,6 @@
   #size-cells = <2>;
   compatible = "eth,ariane-bare-dev";
   model = "eth,ariane-bare";
-  // chosen {
-  //   stdout-path = "/soc/uart@10000000:115200";
-  // };
   cpus {
     #address-cells = <1>;
     #size-cells = <0>;
@@ -31,7 +28,7 @@
   };
   memory@80000000 {
     device_type = "memory";
-    reg = <0x0 0x80000000 0x0 0x1800000>;
+    reg = <0x0 0x80000000 0x0 0x10000000>;
   };
   soc {
     #address-cells = <2>;
@@ -44,16 +41,17 @@
       reg = <0x0 0x2000000 0x0 0xc0000>;
       reg-names = "control";
     };
-    PLIC0: interrupt-controller@c000000 {
-      #address-cells = <0>;
-      #interrupt-cells = <1>;
-      compatible = "sifive,plic-1.0.0", "riscv,plic0";
-      interrupt-controller;
-      interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
-      reg = <0x0 0xc000000 0x0 0x4000000>;
-      riscv,max-priority = <7>;
-      riscv,ndev = <2>;
-    };
+    // PLIC needs to be disabeld for tandem verification
+    // PLIC0: interrupt-controller@c000000 {
+    //   #address-cells = <0>;
+    //   #interrupt-cells = <1>;
+    //   compatible = "sifive,plic-1.0.0", "riscv,plic0";
+    //   interrupt-controller;
+    //   interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+    //   reg = <0x0 0xc000000 0x0 0x4000000>;
+    //   riscv,max-priority = <7>;
+    //   riscv,ndev = <2>;
+    // };
     debug-controller@0 {
       compatible = "riscv,debug-013";
       interrupts-extended = <&CPU0_intc 65535>;
@@ -65,7 +63,7 @@
       reg = <0x0 0x10000000 0x0 0x1000>;
       clock-frequency = <50000000>;
       current-speed = <115200>;
-      interrupt-parent = <&PLIC0>;
+      // interrupt-parent = <&PLIC0>;
       interrupts = <1>;
       reg-shift = <2>; // regs are spaced on 32 bit boundary
       reg-io-width = <4>; // only 32-bit access are supported
diff --git a/bootrom/bootrom.h b/bootrom/bootrom.h
index 8814605688d296a35aa19d833cef19c1ee1f4960..e3228c2560637c21a8f0e6da667e66aee80c6b75 100644
--- a/bootrom/bootrom.h
+++ b/bootrom/bootrom.h
@@ -1,6 +1,6 @@
 // Auto-generated code
 
-const int reset_vec_size = 452;
+const int reset_vec_size = 374;
 
 uint32_t reset_vec[reset_vec_size] = {
     0x0010041b,
@@ -36,15 +36,15 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x00000000,
     0xedfe0dd0,
-    0x8f060000,
+    0x58050000,
     0x38000000,
-    0x54050000,
+    0x4c040000,
     0x28000000,
     0x11000000,
     0x10000000,
     0x00000000,
-    0x3b010000,
-    0x1c050000,
+    0x0c010000,
+    0x14040000,
     0x00000000,
     0x00000000,
     0x00000000,
@@ -121,8 +121,8 @@ uint32_t reset_vec[reset_vec_size] = {
     0x0b000000,
     0x66000000,
     0x34367672,
-    0x63616d69,
-    0x00007573,
+    0x66616d69,
+    0x00006364,
     0x03000000,
     0x0b000000,
     0x70000000,
@@ -180,7 +180,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x00000080,
     0x00000000,
-    0x00008001,
+    0x00000010,
     0x02000000,
     0x01000000,
     0x00636f73,
@@ -239,68 +239,6 @@ uint32_t reset_vec[reset_vec_size] = {
     0x006c6f72,
     0x02000000,
     0x01000000,
-    0x65746e69,
-    0x70757272,
-    0x6f632d74,
-    0x6f72746e,
-    0x72656c6c,
-    0x30306340,
-    0x30303030,
-    0x00000000,
-    0x03000000,
-    0x04000000,
-    0x00000000,
-    0x00000000,
-    0x03000000,
-    0x04000000,
-    0x83000000,
-    0x01000000,
-    0x03000000,
-    0x1e000000,
-    0x1b000000,
-    0x69666973,
-    0x702c6576,
-    0x2d63696c,
-    0x2e302e31,
-    0x69720030,
-    0x2c766373,
-    0x63696c70,
-    0x00000030,
-    0x03000000,
-    0x00000000,
-    0x94000000,
-    0x03000000,
-    0x10000000,
-    0xbe000000,
-    0x01000000,
-    0x0b000000,
-    0x01000000,
-    0x09000000,
-    0x03000000,
-    0x10000000,
-    0x5b000000,
-    0x00000000,
-    0x0000000c,
-    0x00000000,
-    0x00000004,
-    0x03000000,
-    0x04000000,
-    0xdc000000,
-    0x07000000,
-    0x03000000,
-    0x04000000,
-    0xef000000,
-    0x02000000,
-    0x03000000,
-    0x04000000,
-    0xa9000000,
-    0x02000000,
-    0x03000000,
-    0x04000000,
-    0xaf000000,
-    0x02000000,
-    0x02000000,
-    0x01000000,
     0x75626564,
     0x6f632d67,
     0x6f72746e,
@@ -354,23 +292,19 @@ uint32_t reset_vec[reset_vec_size] = {
     0x80f0fa02,
     0x03000000,
     0x04000000,
-    0xfa000000,
+    0xdc000000,
     0x00c20100,
     0x03000000,
     0x04000000,
-    0x08010000,
-    0x02000000,
-    0x03000000,
-    0x04000000,
-    0x19010000,
+    0xea000000,
     0x01000000,
     0x03000000,
     0x04000000,
-    0x24010000,
+    0xf5000000,
     0x02000000,
     0x03000000,
     0x04000000,
-    0x2e010000,
+    0xff000000,
     0x04000000,
     0x02000000,
     0x02000000,
@@ -431,28 +365,16 @@ uint32_t reset_vec[reset_vec_size] = {
     0x65720064,
     0x616e2d67,
     0x0073656d,
-    0x63736972,
-    0x616d2c76,
-    0x72702d78,
-    0x69726f69,
-    0x72007974,
-    0x76637369,
-    0x65646e2c,
-    0x75630076,
-    0x6e657272,
-    0x70732d74,
-    0x00646565,
-    0x65746e69,
-    0x70757272,
-    0x61702d74,
-    0x746e6572,
-    0x746e6900,
-    0x75727265,
-    0x00737470,
-    0x2d676572,
-    0x66696873,
-    0x65720074,
-    0x6f692d67,
-    0x6469772d,
-    0x00006874
+    0x72727563,
+    0x2d746e65,
+    0x65657073,
+    0x6e690064,
+    0x72726574,
+    0x73747075,
+    0x67657200,
+    0x6968732d,
+    0x72007466,
+    0x692d6765,
+    0x69772d6f,
+    0x00687464
 };
diff --git a/bootrom/bootrom.img b/bootrom/bootrom.img
index 05c3a8da67b727e17a87c03d38e68a68a416e22d..3883804890b2e1ee8d6fc3934e364d8611a937d1 100644
Binary files a/bootrom/bootrom.img and b/bootrom/bootrom.img differ
diff --git a/bootrom/bootrom.sv b/bootrom/bootrom.sv
index 62cb4ceff22fa0bb7273500374e5156a1a92d1e4..e5efa9f4affa4167783dc732197a69e83efa3d63 100644
--- a/bootrom/bootrom.sv
+++ b/bootrom/bootrom.sv
@@ -20,21 +20,15 @@ module bootrom (
    input  logic [63:0]  addr_i,
    output logic [63:0]  rdata_o
 );
-    localparam int RomSize = 226;
+    localparam int RomSize = 187;
 
     const logic [RomSize-1:0][63:0] mem = {
-        64'h00006874_6469772d,
-        64'h6f692d67_65720074,
-        64'h66696873_2d676572,
-        64'h00737470_75727265,
-        64'h746e6900_746e6572,
-        64'h61702d74_70757272,
-        64'h65746e69_00646565,
-        64'h70732d74_6e657272,
-        64'h75630076_65646e2c,
-        64'h76637369_72007974,
-        64'h69726f69_72702d78,
-        64'h616d2c76_63736972,
+        64'h00687464_69772d6f,
+        64'h692d6765_72007466,
+        64'h6968732d_67657200,
+        64'h73747075_72726574,
+        64'h6e690064_65657073,
+        64'h2d746e65_72727563,
         64'h0073656d_616e2d67,
         64'h65720064_65646e65,
         64'h7478652d_73747075,
@@ -65,15 +59,13 @@ module bootrom (
         64'h64646123_09000000,
         64'h02000000_02000000,
         64'h02000000_04000000,
-        64'h2e010000_04000000,
+        64'hff000000_04000000,
         64'h03000000_02000000,
-        64'h24010000_04000000,
+        64'hf5000000_04000000,
         64'h03000000_01000000,
-        64'h19010000_04000000,
-        64'h03000000_02000000,
-        64'h08010000_04000000,
+        64'hea000000_04000000,
         64'h03000000_00c20100,
-        64'hfa000000_04000000,
+        64'hdc000000_04000000,
         64'h03000000_80f0fa02,
         64'h3f000000_04000000,
         64'h03000000_00100000,
@@ -101,37 +93,6 @@ module bootrom (
         64'h72656c6c_6f72746e,
         64'h6f632d67_75626564,
         64'h01000000_02000000,
-        64'h02000000_af000000,
-        64'h04000000_03000000,
-        64'h02000000_a9000000,
-        64'h04000000_03000000,
-        64'h02000000_ef000000,
-        64'h04000000_03000000,
-        64'h07000000_dc000000,
-        64'h04000000_03000000,
-        64'h00000004_00000000,
-        64'h0000000c_00000000,
-        64'h5b000000_10000000,
-        64'h03000000_09000000,
-        64'h01000000_0b000000,
-        64'h01000000_be000000,
-        64'h10000000_03000000,
-        64'h94000000_00000000,
-        64'h03000000_00000030,
-        64'h63696c70_2c766373,
-        64'h69720030_2e302e31,
-        64'h2d63696c_702c6576,
-        64'h69666973_1b000000,
-        64'h1e000000_03000000,
-        64'h01000000_83000000,
-        64'h04000000_03000000,
-        64'h00000000_00000000,
-        64'h04000000_03000000,
-        64'h00000000_30303030,
-        64'h30306340_72656c6c,
-        64'h6f72746e_6f632d74,
-        64'h70757272_65746e69,
-        64'h01000000_02000000,
         64'h006c6f72_746e6f63,
         64'hd2000000_08000000,
         64'h03000000_00000c00,
@@ -160,7 +121,7 @@ module bootrom (
         64'h00000000_04000000,
         64'h03000000_00636f73,
         64'h01000000_02000000,
-        64'h00008001_00000000,
+        64'h00000010_00000000,
         64'h00000080_00000000,
         64'h5b000000_10000000,
         64'h03000000_00007972,
@@ -189,7 +150,7 @@ module bootrom (
         64'h00003933_76732c76,
         64'h63736972_70000000,
         64'h0b000000_03000000,
-        64'h00007573_63616d69,
+        64'h00006364_66616d69,
         64'h34367672_66000000,
         64'h0b000000_03000000,
         64'h00000076_63736972,
@@ -228,11 +189,11 @@ module bootrom (
         64'h00000000_01000000,
         64'h00000000_00000000,
         64'h00000000_00000000,
-        64'h1c050000_3b010000,
+        64'h14040000_0c010000,
         64'h00000000_10000000,
         64'h11000000_28000000,
-        64'h54050000_38000000,
-        64'h8f060000_edfe0dd0,
+        64'h4c040000_38000000,
+        64'h58050000_edfe0dd0,
         64'h00000000_00000000,
         64'h00000000_00000000,
         64'h00000000_00000000,
diff --git a/fpga/constraints/genesys-2.xdc b/fpga/constraints/genesys-2.xdc
index fd4302bba7979991b1a80354b0cdfe348ddaf4ed..52fd71445263203dedf4b17d1821f95b8ae65c83 100644
--- a/fpga/constraints/genesys-2.xdc
+++ b/fpga/constraints/genesys-2.xdc
@@ -66,12 +66,50 @@ create_clock -period 8.000 -name eth_rxck [get_ports eth_rxck]
 set_clock_groups -asynchronous -group [get_clocks eth_rxck -include_generated_clocks]
 set_clock_groups -asynchronous -group [get_clocks clk_out2_xlnx_clk_gen]
 
-
+#############################################
 ## SD Card
+#############################################
 set_property -dict {PACKAGE_PIN R28 IOSTANDARD LVCMOS33} [get_ports spi_clk_o]
 set_property -dict {PACKAGE_PIN T30 IOSTANDARD LVCMOS33} [get_ports spi_ss]
 set_property -dict {PACKAGE_PIN R26 IOSTANDARD LVCMOS33} [get_ports spi_miso]
 set_property -dict {PACKAGE_PIN R29 IOSTANDARD LVCMOS33} [get_ports spi_mosi]
+# set_property -dict { PACKAGE_PIN P28   IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L8N_T1_D12_14 Sch=sd_cd
+# set_property -dict { PACKAGE_PIN R29   IOSTANDARD LVCMOS33 } [get_ports { sd_cmd }]; #IO_L7N_T1_D10_14 Sch=sd_cmd
+# set_property -dict { PACKAGE_PIN R26   IOSTANDARD LVCMOS33 } [get_ports { sd_dat[0] }]; #IO_L10N_T1_D15_14 Sch=sd_dat[0]
+# set_property -dict { PACKAGE_PIN R30   IOSTANDARD LVCMOS33 } [get_ports { sd_dat[1] }]; #IO_L9P_T1_DQS_14 Sch=sd_dat[1]
+# set_property -dict { PACKAGE_PIN P29   IOSTANDARD LVCMOS33 } [get_ports { sd_dat[2] }]; #IO_L7P_T1_D09_14 Sch=sd_dat[2]
+# set_property -dict { PACKAGE_PIN T30   IOSTANDARD LVCMOS33 } [get_ports { sd_dat[3] }]; #IO_L9N_T1_DQS_D13_14 Sch=sd_dat[3]
+# set_property -dict { PACKAGE_PIN AE24  IOSTANDARD LVCMOS33 } [get_ports { sd_reset }]; #IO_L12N_T1_MRCC_12 Sch=sd_reset
+# set_property -dict { PACKAGE_PIN R28   IOSTANDARD LVCMOS33 } [get_ports { sd_clk }]; #IO_L11P_T1_SRCC_14 Sch=sd_sclk
+
+# create_generated_clock -name sd_fast_clk -source [get_pins clk_mmcm/sd_sys_clk] -divide_by 2 [get_pins chipset_impl/piton_sd_top/sdc_controller/clock_divider0/fast_clk_reg/Q]
+# create_generated_clock -name sd_slow_clk -source [get_pins clk_mmcm/sd_sys_clk] -divide_by 200 [get_pins chipset_impl/piton_sd_top/sdc_controller/clock_divider0/slow_clk_reg/Q]
+# create_generated_clock -name sd_clk_out -source [get_pins sd_clk_oddr/C] -divide_by 1 -add -master_clock sd_fast_clk [get_ports sd_clk_out]
+# create_generated_clock -name sd_clk_out_1 -source [get_pins sd_clk_oddr/C] -divide_by 1 -add -master_clock sd_slow_clk [get_ports sd_clk_out]
+
+# create_clock -period 40.000 -name VIRTUAL_sd_fast_clk -waveform {0.000 20.000}
+# create_clock -period 4000.000 -name VIRTUAL_sd_slow_clk -waveform {0.000 2000.000}
+
+# set_output_delay -clock [get_clocks sd_clk_out] -min -add_delay 5.000 [get_ports {sd_dat[*]}]
+# set_output_delay -clock [get_clocks sd_clk_out] -max -add_delay 15.000 [get_ports {sd_dat[*]}]
+# set_output_delay -clock [get_clocks sd_clk_out_1] -min -add_delay 5.000 [get_ports {sd_dat[*]}]
+# set_output_delay -clock [get_clocks sd_clk_out_1] -max -add_delay 1500.000 [get_ports {sd_dat[*]}]
+# set_output_delay -clock [get_clocks sd_clk_out] -min -add_delay 5.000 [get_ports sd_cmd]
+# set_output_delay -clock [get_clocks sd_clk_out] -max -add_delay 15.000 [get_ports sd_cmd]
+# set_output_delay -clock [get_clocks sd_clk_out_1] -min -add_delay 5.000 [get_ports sd_cmd]
+# set_output_delay -clock [get_clocks sd_clk_out_1] -max -add_delay 1500.000 [get_ports sd_cmd]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -min -add_delay 20.000 [get_ports {sd_dat[*]}]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -max -add_delay 35.000 [get_ports {sd_dat[*]}]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -min -add_delay 2000.000 [get_ports {sd_dat[*]}]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -max -add_delay 3500.000 [get_ports {sd_dat[*]}]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -min -add_delay 20.000 [get_ports sd_cmd]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -max -add_delay 35.000 [get_ports sd_cmd]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -min -add_delay 2000.000 [get_ports sd_cmd]
+# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -max -add_delay 3500.000 [get_ports sd_cmd]
+# set_clock_groups -physically_exclusive -group [get_clocks -include_generated_clocks sd_clk_out] -group [get_clocks -include_generated_clocks sd_clk_out_1]
+# set_clock_groups -logically_exclusive -group [get_clocks -include_generated_clocks {VIRTUAL_sd_fast_clk sd_fast_clk}] -group [get_clocks -include_generated_clocks {sd_slow_clk VIRTUAL_sd_slow_clk}]
+# set_clock_groups -asynchronous -group [get_clocks [list [get_clocks -of_objects [get_pins clk_mmcm/chipset_clk]]]] -group [get_clocks -filter { NAME =~  "*sd*" }]
+
 
 # Genesys 2 has a quad SPI flash
 set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
diff --git a/fpga/scripts/run.tcl b/fpga/scripts/run.tcl
index e4f771733a862eaf0fef142e551ff513596569d2..6ba81a64695295076101dc72772e5768f7793994 100644
--- a/fpga/scripts/run.tcl
+++ b/fpga/scripts/run.tcl
@@ -23,6 +23,7 @@ read_ip xilinx/xlnx_axi_dwidth_converter/ip/xlnx_axi_dwidth_converter.xci
 read_ip xilinx/xlnx_axi_gpio/ip/xlnx_axi_gpio.xci
 read_ip xilinx/xlnx_axi_quad_spi/ip/xlnx_axi_quad_spi.xci
 read_ip xilinx/xlnx_clk_gen/ip/xlnx_clk_gen.xci
+# read_ip xilinx/xlnx_protocol_checker/ip/xlnx_protocol_checker.xci
 
 source scripts/add_sources.tcl
 
@@ -40,11 +41,11 @@ set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file" "*$r
 set_property -dict { file_type {Verilog Header} is_global_include 1} -objects $file_obj
 
 update_compile_order -fileset sources_1
-update_compile_order -fileset sim_1
 
 add_files -fileset constrs_1 -norecurse constraints/$project.xdc
 
-# synth_design -retiming -rtl -name rtl_1 -verilog_define SYNTHESIS -verilog_define
+set_property include_dirs src/axi_sd_bridge/include [current_fileset]
+
 synth_design -rtl -name rtl_1
 
 set_property STEPS.SYNTH_DESIGN.ARGS.RETIMING true [get_runs synth_1]
diff --git a/fpga/src/ariane_peripherals_xilinx.sv b/fpga/src/ariane_peripherals_xilinx.sv
index 920a71107204cb91d50a9bb422ab6daca670c42f..09932b8e751918bebaba73ffef92f9cddf098283 100644
--- a/fpga/src/ariane_peripherals_xilinx.sv
+++ b/fpga/src/ariane_peripherals_xilinx.sv
@@ -51,6 +51,8 @@ module ariane_peripherals #(
     output logic       spi_mosi        ,
     input  logic       spi_miso        ,
     output logic       spi_ss          ,
+    // SD Card
+    input  logic       sd_clk_i        ,
     output logic [7:0] leds_o          ,
     input  logic [7:0] dip_switches_i
 );
@@ -466,7 +468,7 @@ module ariane_peripherals #(
         assign spi_mosi = 1'b0;
         assign spi_ss = 1'b0;
 
-        assign irq_sources [1] = 1'b0;
+        // assign irq_sources [1] = 1'b0;
         assign spi.aw_ready = 1'b1;
         assign spi.ar_ready = 1'b1;
         assign spi.w_ready = 1'b1;
@@ -489,73 +491,72 @@ module ariane_peripherals #(
 
     if (InclEthernet) begin : gen_ethernet
 
-logic                    clk_200_int, clk_rgmii, clk_rgmii_quad; 
-logic                    eth_en, eth_we, eth_int_n, eth_pme_n, eth_mdio_i, eth_mdio_o, eth_mdio_oe;
-logic [AxiAddrWidth-1:0] eth_addr;
-logic [AxiDataWidth-1:0] eth_wrdata, eth_rdata;
-logic [AxiDataWidth/8-1:0] eth_be;
-
-axi2mem #(
-    .AXI_ID_WIDTH   ( AxiIdWidth       ),
-    .AXI_ADDR_WIDTH ( AxiAddrWidth     ),
-    .AXI_DATA_WIDTH ( AxiDataWidth     ),
-    .AXI_USER_WIDTH ( AxiUserWidth     )
-) i_axi2rom (
-    .clk_i  ( clk_i                   ),
-    .rst_ni ( rst_ni                  ),
-    .slave  ( ethernet                ),
-    .req_o  ( eth_en                  ),
-    .we_o   ( eth_we                  ),
-    .addr_o ( eth_addr                ),
-    .be_o   ( eth_be                  ),
-    .data_o ( eth_wrdata              ),
-    .data_i ( eth_rdata               )
-);
+    logic                    clk_200_int, clk_rgmii, clk_rgmii_quad;
+    logic                    eth_en, eth_we, eth_int_n, eth_pme_n, eth_mdio_i, eth_mdio_o, eth_mdio_oe;
+    logic [AxiAddrWidth-1:0] eth_addr;
+    logic [AxiDataWidth-1:0] eth_wrdata, eth_rdata;
+    logic [AxiDataWidth/8-1:0] eth_be;
+
+    axi2mem #(
+        .AXI_ID_WIDTH   ( AxiIdWidth       ),
+        .AXI_ADDR_WIDTH ( AxiAddrWidth     ),
+        .AXI_DATA_WIDTH ( AxiDataWidth     ),
+        .AXI_USER_WIDTH ( AxiUserWidth     )
+    ) i_axi2rom (
+        .clk_i  ( clk_i                   ),
+        .rst_ni ( rst_ni                  ),
+        .slave  ( ethernet                ),
+        .req_o  ( eth_en                  ),
+        .we_o   ( eth_we                  ),
+        .addr_o ( eth_addr                ),
+        .be_o   ( eth_be                  ),
+        .data_o ( eth_wrdata              ),
+        .data_i ( eth_rdata               )
+    );
 
-framing_top eth_rgmii
-  (
-   .msoc_clk(clk_i),
-   .core_lsu_addr(eth_addr[14:0]),
-   .core_lsu_wdata(eth_wrdata),
-   .core_lsu_be(eth_be),
-   .ce_d(eth_en),
-   .we_d(eth_en & eth_we),
-   .framing_sel(eth_en),
-   .framing_rdata(eth_rdata),
-   .rst_int(!rst_ni),
-   .clk_int(phy_tx_clk_i), // 125 MHz in-phase
-   .clk90_int(eth_clk_i),    // 125 MHz quadrature
-   .clk_200_int(clk_200MHz_i),
-   /*
-    * Ethernet: 1000BASE-T RGMII
-    */
-   .phy_rx_clk(eth_rxck),
-   .phy_rxd(eth_rxd),
-   .phy_rx_ctl(eth_rxctl),
-   .phy_tx_clk(eth_txck),
-   .phy_txd(eth_txd),
-   .phy_tx_ctl(eth_txctl),
-   .phy_reset_n(eth_rst_n),
-   .phy_int_n(eth_int_n),
-   .phy_pme_n(eth_pme_n),
-   .phy_mdc(eth_mdc),
-   .phy_mdio_i(eth_mdio_i),
-   .phy_mdio_o(eth_mdio_o),
-   .phy_mdio_oe(eth_mdio_oe),
-   .eth_irq(irq_sources[2])
-);
+    framing_top eth_rgmii (
+       .msoc_clk(clk_i),
+       .core_lsu_addr(eth_addr[14:0]),
+       .core_lsu_wdata(eth_wrdata),
+       .core_lsu_be(eth_be),
+       .ce_d(eth_en),
+       .we_d(eth_en & eth_we),
+       .framing_sel(eth_en),
+       .framing_rdata(eth_rdata),
+       .rst_int(!rst_ni),
+       .clk_int(phy_tx_clk_i), // 125 MHz in-phase
+       .clk90_int(eth_clk_i),    // 125 MHz quadrature
+       .clk_200_int(clk_200MHz_i),
+       /*
+        * Ethernet: 1000BASE-T RGMII
+        */
+       .phy_rx_clk(eth_rxck),
+       .phy_rxd(eth_rxd),
+       .phy_rx_ctl(eth_rxctl),
+       .phy_tx_clk(eth_txck),
+       .phy_txd(eth_txd),
+       .phy_tx_ctl(eth_txctl),
+       .phy_reset_n(eth_rst_n),
+       .phy_int_n(eth_int_n),
+       .phy_pme_n(eth_pme_n),
+       .phy_mdc(eth_mdc),
+       .phy_mdio_i(eth_mdio_i),
+       .phy_mdio_o(eth_mdio_o),
+       .phy_mdio_oe(eth_mdio_oe),
+       .eth_irq(irq_sources[2])
+    );
 
-   IOBUF #(
-      .DRIVE(12), // Specify the output drive strength
-      .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE" 
-      .IOSTANDARD("DEFAULT"), // Specify the I/O standard
-      .SLEW("SLOW") // Specify the output slew rate
-   ) IOBUF_inst (
-      .O(eth_mdio_i),     // Buffer output
-      .IO(eth_mdio),   // Buffer inout port (connect directly to top-level port)
-      .I(eth_mdio_o),     // Buffer input
-      .T(~eth_mdio_oe)      // 3-state enable input, high=input, low=output
-   );
+       IOBUF #(
+          .DRIVE(12), // Specify the output drive strength
+          .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
+          .IOSTANDARD("DEFAULT"), // Specify the I/O standard
+          .SLEW("SLOW") // Specify the output slew rate
+       ) IOBUF_inst (
+          .O(eth_mdio_i),     // Buffer output
+          .IO(eth_mdio),   // Buffer inout port (connect directly to top-level port)
+          .I(eth_mdio_o),     // Buffer input
+          .T(~eth_mdio_oe)      // 3-state enable input, high=input, low=output
+       );
 
     end else begin
         assign irq_sources [2] = 1'b0;
@@ -607,7 +608,7 @@ framing_top eth_rgmii
         logic        s_axi_gpio_rlast;
         logic        s_axi_gpio_rvalid;
         logic        s_axi_gpio_rready;
-       
+
         // system-bus is 64-bit, convert down to 32 bit
         xlnx_axi_dwidth_converter i_xlnx_axi_dwidth_converter_gpio (
             .s_axi_aclk     ( clk_i              ),
diff --git a/fpga/src/ariane_xilinx.sv b/fpga/src/ariane_xilinx.sv
index 68c336c84e2887418c4424247bb59381fb19fc90..a8a2ed044c14fb665ff6a3adfd6ff058ec9e035a 100644
--- a/fpga/src/ariane_xilinx.sv
+++ b/fpga/src/ariane_xilinx.sv
@@ -86,7 +86,7 @@ module ariane_xilinx (
 // 24 MByte in 8 byte words
 localparam NumWords = (24 * 1024 * 1024) / 8;
 localparam NBSlave = 2; // debug, ariane
-localparam logic [63:0] CacheStartAddr = 64'h80000000;
+localparam logic [63:0] CacheStartAddr = 64'h8000_0000;
 localparam AxiAddrWidth = 64;
 localparam AxiDataWidth = 64;
 localparam AxiIdWidthMaster = 4;
@@ -119,6 +119,7 @@ logic clk;
 logic eth_clk;
 logic spi_clk_i;
 logic phy_tx_clk;
+logic sd_clk_sys;
 
 logic ddr_sync_reset;
 logic ddr_clock_out;
@@ -297,8 +298,8 @@ axi2mem #(
     .AXI_DATA_WIDTH ( AxiDataWidth        ),
     .AXI_USER_WIDTH ( AxiUserWidth        )
 ) i_dm_axi2mem (
-    .clk_i      ( clk_i                     ),
-    .rst_ni     ( rst_ni                    ),
+    .clk_i      ( clk                       ),
+    .rst_ni     ( rst_n                     ),
     .slave      ( master[ariane_soc::Debug] ),
     .req_o      ( dm_slave_req              ),
     .we_o       ( dm_slave_we               ),
@@ -317,8 +318,8 @@ axi_master_connect i_dm_axi_master_connect (
 axi_adapter #(
     .DATA_WIDTH            ( AxiDataWidth              )
 ) i_dm_axi_master (
-    .clk_i                 ( clk_i                     ),
-    .rst_ni                ( rst_ni                    ),
+    .clk_i                 ( clk                       ),
+    .rst_ni                ( rst_n                     ),
     .req_i                 ( dm_master_req             ),
     .type_i                ( ariane_axi::SINGLE_REQ    ),
     .gnt_o                 ( dm_master_gnt             ),
@@ -461,6 +462,7 @@ ariane_peripherals #(
     .eth_mdio,
     .eth_mdc,
     .phy_tx_clk_i   ( phy_tx_clk                  ),
+    .sd_clk_i       ( sd_clk_sys                  ),
     .spi_clk_o      ( spi_clk_o                   ),
     .spi_mosi       ( spi_mosi                    ),
     .spi_miso       ( spi_miso                    ),
@@ -469,6 +471,7 @@ ariane_peripherals #(
     .dip_switches_i ( sw                          )
 );
 
+
 // ---------------------
 // Board peripherals
 // ---------------------
@@ -536,6 +539,63 @@ axi_riscv_atomics_wrap #(
     .mst    ( dram                     )
 );
 
+`ifdef PROTOCOL_CHECKER
+logic pc_status;
+// assign led[0] = pc_status;
+// assign led[7:1] = '0;
+
+xlnx_protocol_checker i_xlnx_protocol_checker (
+  .pc_status(),
+  .pc_asserted(pc_status),
+  .aclk(clk),
+  .aresetn(ndmreset_n),
+  .pc_axi_awid     (dram.aw_id),
+  .pc_axi_awaddr   (dram.aw_addr),
+  .pc_axi_awlen    (dram.aw_len),
+  .pc_axi_awsize   (dram.aw_size),
+  .pc_axi_awburst  (dram.aw_burst),
+  .pc_axi_awlock   (dram.aw_lock),
+  .pc_axi_awcache  (dram.aw_cache),
+  .pc_axi_awprot   (dram.aw_prot),
+  .pc_axi_awqos    (dram.aw_qos),
+  .pc_axi_awregion (dram.aw_region),
+  .pc_axi_awuser   (dram.aw_user),
+  .pc_axi_awvalid  (dram.aw_valid),
+  .pc_axi_awready  (dram.aw_ready),
+  .pc_axi_wlast    (dram.w_last),
+  .pc_axi_wdata    (dram.w_data),
+  .pc_axi_wstrb    (dram.w_strb),
+  .pc_axi_wuser    (dram.w_user),
+  .pc_axi_wvalid   (dram.w_valid),
+  .pc_axi_wready   (dram.w_ready),
+  .pc_axi_bid      (dram.b_id),
+  .pc_axi_bresp    (dram.b_resp),
+  .pc_axi_buser    (dram.b_user),
+  .pc_axi_bvalid   (dram.b_valid),
+  .pc_axi_bready   (dram.b_ready),
+  .pc_axi_arid     (dram.ar_id),
+  .pc_axi_araddr   (dram.ar_addr),
+  .pc_axi_arlen    (dram.ar_len),
+  .pc_axi_arsize   (dram.ar_size),
+  .pc_axi_arburst  (dram.ar_burst),
+  .pc_axi_arlock   (dram.ar_lock),
+  .pc_axi_arcache  (dram.ar_cache),
+  .pc_axi_arprot   (dram.ar_prot),
+  .pc_axi_arqos    (dram.ar_qos),
+  .pc_axi_arregion (dram.ar_region),
+  .pc_axi_aruser   (dram.ar_user),
+  .pc_axi_arvalid  (dram.ar_valid),
+  .pc_axi_arready  (dram.ar_ready),
+  .pc_axi_rid      (dram.r_id),
+  .pc_axi_rlast    (dram.r_last),
+  .pc_axi_rdata    (dram.r_data),
+  .pc_axi_rresp    (dram.r_resp),
+  .pc_axi_ruser    (dram.r_user),
+  .pc_axi_rvalid   (dram.r_valid),
+  .pc_axi_rready   (dram.r_ready)
+);
+`endif
+
 assign dram.r_user = '0;
 assign dram.b_user = '0;
 
@@ -582,53 +642,54 @@ xlnx_axi_clock_converter i_xlnx_axi_clock_converter_ddr (
   .s_axi_rvalid   ( dram.r_valid     ),
   .s_axi_rready   ( dram.r_ready     ),
   // to size converter
-  .m_axi_aclk     ( ddr_clock_out                      ),
-  .m_axi_aresetn  ( ndmreset_n                         ),
-  .m_axi_awid     ( s_axi_awid                         ),
-  .m_axi_awaddr   ( s_axi_awaddr                       ),
-  .m_axi_awlen    ( s_axi_awlen                        ),
-  .m_axi_awsize   ( s_axi_awsize                       ),
-  .m_axi_awburst  ( s_axi_awburst                      ),
-  .m_axi_awlock   ( s_axi_awlock                       ),
-  .m_axi_awcache  ( s_axi_awcache                      ),
-  .m_axi_awprot   ( s_axi_awprot                       ),
-  .m_axi_awregion ( s_axi_awregion                     ),
-  .m_axi_awqos    ( s_axi_awqos                        ),
-  .m_axi_awvalid  ( s_axi_awvalid                      ),
-  .m_axi_awready  ( s_axi_awready                      ),
-  .m_axi_wdata    ( s_axi_wdata                        ),
-  .m_axi_wstrb    ( s_axi_wstrb                        ),
-  .m_axi_wlast    ( s_axi_wlast                        ),
-  .m_axi_wvalid   ( s_axi_wvalid                       ),
-  .m_axi_wready   ( s_axi_wready                       ),
-  .m_axi_bid      ( s_axi_bid                          ),
-  .m_axi_bresp    ( s_axi_bresp                        ),
-  .m_axi_bvalid   ( s_axi_bvalid                       ),
-  .m_axi_bready   ( s_axi_bready                       ),
-  .m_axi_arid     ( s_axi_arid                         ),
-  .m_axi_araddr   ( s_axi_araddr                       ),
-  .m_axi_arlen    ( s_axi_arlen                        ),
-  .m_axi_arsize   ( s_axi_arsize                       ),
-  .m_axi_arburst  ( s_axi_arburst                      ),
-  .m_axi_arlock   ( s_axi_arlock                       ),
-  .m_axi_arcache  ( s_axi_arcache                      ),
-  .m_axi_arprot   ( s_axi_arprot                       ),
-  .m_axi_arregion ( s_axi_arregion                     ),
-  .m_axi_arqos    ( s_axi_arqos                        ),
-  .m_axi_arvalid  ( s_axi_arvalid                      ),
-  .m_axi_arready  ( s_axi_arready                      ),
-  .m_axi_rid      ( s_axi_rid                          ),
-  .m_axi_rdata    ( s_axi_rdata                        ),
-  .m_axi_rresp    ( s_axi_rresp                        ),
-  .m_axi_rlast    ( s_axi_rlast                        ),
-  .m_axi_rvalid   ( s_axi_rvalid                       ),
-  .m_axi_rready   ( s_axi_rready                       )
+  .m_axi_aclk     ( ddr_clock_out    ),
+  .m_axi_aresetn  ( ndmreset_n       ),
+  .m_axi_awid     ( s_axi_awid       ),
+  .m_axi_awaddr   ( s_axi_awaddr     ),
+  .m_axi_awlen    ( s_axi_awlen      ),
+  .m_axi_awsize   ( s_axi_awsize     ),
+  .m_axi_awburst  ( s_axi_awburst    ),
+  .m_axi_awlock   ( s_axi_awlock     ),
+  .m_axi_awcache  ( s_axi_awcache    ),
+  .m_axi_awprot   ( s_axi_awprot     ),
+  .m_axi_awregion ( s_axi_awregion   ),
+  .m_axi_awqos    ( s_axi_awqos      ),
+  .m_axi_awvalid  ( s_axi_awvalid    ),
+  .m_axi_awready  ( s_axi_awready    ),
+  .m_axi_wdata    ( s_axi_wdata      ),
+  .m_axi_wstrb    ( s_axi_wstrb      ),
+  .m_axi_wlast    ( s_axi_wlast      ),
+  .m_axi_wvalid   ( s_axi_wvalid     ),
+  .m_axi_wready   ( s_axi_wready     ),
+  .m_axi_bid      ( s_axi_bid        ),
+  .m_axi_bresp    ( s_axi_bresp      ),
+  .m_axi_bvalid   ( s_axi_bvalid     ),
+  .m_axi_bready   ( s_axi_bready     ),
+  .m_axi_arid     ( s_axi_arid       ),
+  .m_axi_araddr   ( s_axi_araddr     ),
+  .m_axi_arlen    ( s_axi_arlen      ),
+  .m_axi_arsize   ( s_axi_arsize     ),
+  .m_axi_arburst  ( s_axi_arburst    ),
+  .m_axi_arlock   ( s_axi_arlock     ),
+  .m_axi_arcache  ( s_axi_arcache    ),
+  .m_axi_arprot   ( s_axi_arprot     ),
+  .m_axi_arregion ( s_axi_arregion   ),
+  .m_axi_arqos    ( s_axi_arqos      ),
+  .m_axi_arvalid  ( s_axi_arvalid    ),
+  .m_axi_arready  ( s_axi_arready    ),
+  .m_axi_rid      ( s_axi_rid        ),
+  .m_axi_rdata    ( s_axi_rdata      ),
+  .m_axi_rresp    ( s_axi_rresp      ),
+  .m_axi_rlast    ( s_axi_rlast      ),
+  .m_axi_rvalid   ( s_axi_rvalid     ),
+  .m_axi_rready   ( s_axi_rready     )
 );
 
 xlnx_clk_gen i_xlnx_clk_gen (
   .clk_out1 ( clk           ), // 50 MHz
   .clk_out2 ( phy_tx_clk    ), // 125 MHz (for RGMII PHY)
-  .clk_out3 ( eth_clk       ), // 125 MHz quadrature
+  .clk_out3 ( eth_clk       ), // 125 MHz quadrature (90 deg phase shift)
+  .clk_out4 ( sd_clk_sys    ), // 50 MHz clock
   .reset    ( cpu_reset     ),
   .locked   ( pll_locked    ),
   .clk_in1  ( ddr_clock_out )
diff --git a/fpga/src/bootrom/ariane.dts b/fpga/src/bootrom/ariane.dts
index 9711494c9f0c881e49fcc06907d582fee324839a..59ee3341a7c04edcdcfa984fcd11d52e2c560b03 100644
--- a/fpga/src/bootrom/ariane.dts
+++ b/fpga/src/bootrom/ariane.dts
@@ -11,9 +11,9 @@
   cpus {
     #address-cells = <1>;
     #size-cells = <0>;
-    timebase-frequency = <25000000>; // 25 MHz
+    timebase-frequency = <15000000>; // 15 MHz
     CPU0: cpu@0 {
-      clock-frequency = <30000000>; // 30 MHz
+      clock-frequency = <50000000>; // 50 MHz
       device_type = "cpu";
       reg = <0>;
       status = "okay";
@@ -71,7 +71,7 @@
     uart@10000000 {
       compatible = "ns16750";
       reg = <0x0 0x10000000 0x0 0x1000>;
-      clock-frequency = <30000000>;
+      clock-frequency = <50000000>;
       current-speed = <115200>;
       interrupt-parent = <&PLIC0>;
       interrupts = <1>;
diff --git a/fpga/src/bootrom/bootrom.h b/fpga/src/bootrom/bootrom.h
index a650a9a378cfc096ef077fa05e33f95a68635984..c7e3c30a2c12056dbe873519b272a86e30f3af46 100644
--- a/fpga/src/bootrom/bootrom.h
+++ b/fpga/src/bootrom/bootrom.h
@@ -1,6 +1,6 @@
 // Auto-generated code
 
-const int reset_vec_size = 1720;
+const int reset_vec_size = 1732;
 
 uint32_t reset_vec[reset_vec_size] = {
     0x00800913,
@@ -157,7 +157,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x80824108,
     0x00001517,
     0x05131101,
-    0xec065905,
+    0xec065c05,
     0xe426e822,
     0xf05ff0ef,
     0x200007b7,
@@ -168,30 +168,30 @@ uint32_t reset_vec[reset_vec_size] = {
     0x10400793,
     0x5064d03c,
     0x00001517,
-    0x57050513,
+    0x5a050513,
     0xeddff0ef,
     0x95132481,
     0x91010204,
     0xf53ff0ef,
     0x00001517,
-    0x57850513,
+    0x5a850513,
     0xec5ff0ef,
     0x16600793,
     0x5064d03c,
     0x00001517,
-    0x54450513,
+    0x57450513,
     0xeb1ff0ef,
     0x95132481,
     0x91010204,
     0xf27ff0ef,
     0x00001517,
-    0x54c50513,
+    0x57c50513,
     0xe99ff0ef,
     0xd03c4799,
     0x60e26442,
     0x151764a2,
     0x05130000,
-    0x61055265,
+    0x61055565,
     0xe81ff06f,
     0x07b71101,
     0xec062000,
@@ -209,12 +209,12 @@ uint32_t reset_vec[reset_vec_size] = {
     0x8b852401,
     0x1517e395,
     0x05130000,
-    0xf0ef4f65,
+    0xf0ef5265,
     0x4088e3bf,
     0x91011502,
     0xeb3ff0ef,
     0x00001517,
-    0x4d850513,
+    0x50850513,
     0xe25ff0ef,
     0x200007b7,
     0x7513577d,
@@ -287,19 +287,19 @@ uint32_t reset_vec[reset_vec_size] = {
     0x11018082,
     0x842ae822,
     0x00001517,
-    0x3d450513,
+    0x40450513,
     0xe42eec06,
     0xcfdff0ef,
     0xf0ef8522,
     0x1517cf7f,
     0x05130000,
-    0xf0ef3ce5,
+    0xf0ef3fe5,
     0x65a2cebf,
     0xf0ef852e,
     0x6442da7f,
     0x151760e2,
     0x05130000,
-    0x61053865,
+    0x61053b65,
     0xcd1ff06f,
     0xe8221101,
     0xe4266409,
@@ -313,7 +313,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xc00df25f,
     0xfe9915e3,
     0x00001517,
-    0x38c50513,
+    0x3bc50513,
     0xf0ef4585,
     0x4505f89f,
     0x644260e2,
@@ -351,7 +351,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xf0ef842a,
     0x1517e89f,
     0x85a20000,
-    0x2fe50513,
+    0x32e50513,
     0xef3ff0ef,
     0x0004051b,
     0x640260a2,
@@ -367,7 +367,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xe53ff0ef,
     0x85aa842a,
     0x00001517,
-    0x2c450513,
+    0x2f450513,
     0xeb3ff0ef,
     0xe37ff0ef,
     0xfc940ce3,
@@ -379,7 +379,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xe022e406,
     0xc89ff0ef,
     0x00001517,
-    0x29c50513,
+    0x2cc50513,
     0xb91ff0ef,
     0x347d4429,
     0xe03ff0ef,
@@ -474,7 +474,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x0359e7b3,
     0x1517e799,
     0x05130000,
-    0xf0ef15a5,
+    0xf0ef18a5,
     0x19fda17f,
     0xf93046e3,
     0x46054401,
@@ -491,7 +491,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xf0efc5df,
     0x1517c59f,
     0x05130000,
-    0xf0ef0f65,
+    0xf0ef1265,
     0x547d9d3f,
     0x60ae8522,
     0x74ea640e,
@@ -510,7 +510,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xdf3ff0ef,
     0x1517c51d,
     0x05130000,
-    0xf0ef0d25,
+    0xf0ef1025,
     0x54fd987f,
     0xfb040113,
     0x852660a6,
@@ -521,74 +521,74 @@ uint32_t reset_vec[reset_vec_size] = {
     0x61616c02,
     0x15178082,
     0x05130000,
-    0xf0ef0ce5,
+    0xf0ef0fe5,
     0x710195bf,
     0x45854605,
     0xf0ef850a,
     0x890ae49f,
     0xc90584aa,
     0x00001517,
-    0x0c850513,
+    0x0f850513,
     0x93dff0ef,
     0x00001517,
-    0x0d450513,
+    0x10450513,
     0x931ff0ef,
     0xf0ef8526,
     0x15179adf,
     0x05130000,
-    0xf0effd25,
+    0xf0ef0025,
     0x54f991ff,
     0x1517bf61,
     0x05130000,
-    0xf0ef0ca5,
+    0xf0ef0fa5,
     0x151790ff,
     0x05130000,
-    0xf0ef0de5,
+    0xf0ef10e5,
     0x6502903f,
     0xf0ef4b91,
     0x151797df,
     0x05130000,
-    0xf0ef0da5,
+    0xf0ef10a5,
     0x45228eff,
     0x92bff0ef,
     0x00001517,
-    0x0d850513,
+    0x10850513,
     0x8ddff0ef,
     0xf0ef4532,
     0x1517919f,
     0x05130000,
-    0xf0ef0d65,
+    0xf0ef1065,
     0x45428cbf,
     0x907ff0ef,
     0x00001517,
-    0x0d450513,
+    0x10450513,
     0x8b9ff0ef,
     0xf0ef4552,
     0x15178f5f,
     0x05130000,
-    0xf0ef0d25,
+    0xf0ef1025,
     0x65628a7f,
     0x923ff0ef,
     0x00001517,
-    0x0d850513,
+    0x10850513,
     0x895ff0ef,
     0xf0ef7502,
     0x1517911f,
     0x05130000,
-    0xf0ef0d65,
+    0xf0ef1065,
     0x6526883f,
     0x8ffff0ef,
     0x00001517,
-    0x0e450513,
+    0x11450513,
     0x871ff0ef,
     0xf0ef4546,
     0x15178adf,
     0x05130000,
-    0xf0ef0f25,
+    0xf0ef1225,
     0x455685ff,
     0x89bff0ef,
     0x00001517,
-    0xf0050513,
+    0xf3050513,
     0x84dff0ef,
     0x04892583,
     0x46057101,
@@ -597,29 +597,29 @@ uint32_t reset_vec[reset_vec_size] = {
     0x080489aa,
     0x1517c50d,
     0x05130000,
-    0xf0effb65,
+    0xf0effe65,
     0x151782bf,
     0x05130000,
-    0xf0effc25,
+    0xf0efff25,
     0x854e81ff,
     0x89bff0ef,
     0x00001517,
-    0xec050513,
+    0xef050513,
     0x1517b5fd,
     0x05130000,
-    0xf0ef0b65,
+    0xf0ef0e65,
     0xf513803f,
     0xf0ef0ff9,
     0x15178bff,
     0x05130000,
-    0xf0ef0ba5,
+    0xf0ef0ea5,
     0x8913feef,
     0x4503ff04,
     0x09050009,
     0x8a5ff0ef,
     0xfe991be3,
     0x00001517,
-    0x0bc50513,
+    0x0ec50513,
     0xfd0ff0ef,
     0x01090c13,
     0x00094503,
@@ -627,60 +627,60 @@ uint32_t reset_vec[reset_vec_size] = {
     0x1be3887f,
     0x1517ff2c,
     0x05130000,
-    0xf0ef0be5,
+    0xf0ef0ee5,
     0x6888fb2f,
     0x02848913,
     0x07048c13,
     0x827ff0ef,
     0x00001517,
-    0x0b450513,
+    0x0e450513,
     0xf98ff0ef,
     0xf0ef6c88,
     0x1517815f,
     0x05130000,
-    0xf0ef0b25,
+    0xf0ef0e25,
     0x7088f86f,
     0x803ff0ef,
     0x00001517,
-    0x0b050513,
+    0x0e050513,
     0xf74ff0ef,
     0x00094503,
     0xf0ef0905,
     0x1be382ff,
     0x1517ff2c,
     0x05130000,
-    0x2985e0e5,
+    0x2985e3e5,
     0xf58ff0ef,
     0x08048493,
     0xf57993e3,
     0x00001517,
-    0x09050513,
+    0x0c050513,
     0xf44ff0ef,
     0x020aa583,
     0x8552865a,
     0xc33ff0ef,
     0xc50d84aa,
     0x00001517,
-    0xeb450513,
+    0xee450513,
     0xf28ff0ef,
     0x00001517,
-    0xec050513,
+    0xef050513,
     0xf1cff0ef,
     0xf0ef8526,
     0x1517f98f,
     0x05130000,
-    0xb3f5dbe5,
+    0xb3f5dee5,
     0x00001517,
-    0x06450513,
+    0x09450513,
     0xf00ff0ef,
     0x65f1bbb5,
-    0x01c9c537,
+    0x02faf537,
     0x85931141,
     0x05132005,
-    0xe4063805,
+    0xe4060805,
     0xea4ff0ef,
     0x00001517,
-    0xd5050513,
+    0xd8050513,
     0xedcff0ef,
     0x65a14505,
     0xf0ef057e,
@@ -772,15 +772,15 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x00000000,
     0xedfe0dd0,
-    0xda0b0000,
+    0x100c0000,
     0x38000000,
-    0x08090000,
+    0x38090000,
     0x28000000,
     0x11000000,
     0x10000000,
     0x00000000,
-    0xd2020000,
-    0xd0080000,
+    0xd8020000,
+    0x00090000,
     0x00000000,
     0x00000000,
     0x00000000,
@@ -838,14 +838,14 @@ uint32_t reset_vec[reset_vec_size] = {
     0x03000000,
     0x04000000,
     0x38000000,
-    0x40787d01,
+    0xc0e1e400,
     0x01000000,
     0x40757063,
     0x00000030,
     0x03000000,
     0x04000000,
     0x4b000000,
-    0x80c3c901,
+    0x80f0fa02,
     0x03000000,
     0x04000000,
     0x5b000000,
@@ -907,6 +907,10 @@ uint32_t reset_vec[reset_vec_size] = {
     0x04000000,
     0xb5000000,
     0x02000000,
+    0x03000000,
+    0x04000000,
+    0xbb000000,
+    0x02000000,
     0x02000000,
     0x02000000,
     0x02000000,
@@ -944,19 +948,19 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000064,
     0x03000000,
     0x0c000000,
-    0xbd000000,
+    0xc3000000,
     0x01000000,
     0x01000000,
     0x00000000,
     0x03000000,
     0x0a000000,
-    0xc3000000,
+    0xc9000000,
     0x72616568,
     0x61656274,
     0x00000074,
     0x03000000,
     0x00000000,
-    0xd9000000,
+    0xdf000000,
     0x02000000,
     0x02000000,
     0x01000000,
@@ -982,7 +986,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00007375,
     0x03000000,
     0x00000000,
-    0xf0000000,
+    0xf6000000,
     0x01000000,
     0x6e696c63,
     0x30324074,
@@ -997,7 +1001,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x03000000,
     0x10000000,
-    0xf7000000,
+    0xfd000000,
     0x02000000,
     0x03000000,
     0x02000000,
@@ -1011,7 +1015,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000c00,
     0x03000000,
     0x08000000,
-    0x0b010000,
+    0x11010000,
     0x746e6f63,
     0x006c6f72,
     0x02000000,
@@ -1043,7 +1047,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0xa0000000,
     0x03000000,
     0x10000000,
-    0xf7000000,
+    0xfd000000,
     0x02000000,
     0x0b000000,
     0x02000000,
@@ -1057,16 +1061,20 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000004,
     0x03000000,
     0x04000000,
-    0x15010000,
+    0x1b010000,
     0x07000000,
     0x03000000,
     0x04000000,
-    0x28010000,
+    0x2e010000,
     0x03000000,
     0x03000000,
     0x04000000,
     0xb5000000,
     0x03000000,
+    0x03000000,
+    0x04000000,
+    0xbb000000,
+    0x03000000,
     0x02000000,
     0x01000000,
     0x75626564,
@@ -1083,7 +1091,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00333130,
     0x03000000,
     0x08000000,
-    0xf7000000,
+    0xfd000000,
     0x02000000,
     0xffff0000,
     0x03000000,
@@ -1095,7 +1103,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00100000,
     0x03000000,
     0x08000000,
-    0x0b010000,
+    0x11010000,
     0x746e6f63,
     0x006c6f72,
     0x02000000,
@@ -1119,26 +1127,26 @@ uint32_t reset_vec[reset_vec_size] = {
     0x03000000,
     0x04000000,
     0x4b000000,
-    0x80c3c901,
+    0x80f0fa02,
     0x03000000,
     0x04000000,
-    0x33010000,
+    0x39010000,
     0x00c20100,
     0x03000000,
     0x04000000,
-    0x41010000,
+    0x47010000,
     0x03000000,
     0x03000000,
     0x04000000,
-    0x52010000,
+    0x58010000,
     0x01000000,
     0x03000000,
     0x04000000,
-    0x5d010000,
+    0x63010000,
     0x02000000,
     0x03000000,
     0x04000000,
-    0x67010000,
+    0x6d010000,
     0x04000000,
     0x02000000,
     0x01000000,
@@ -1170,11 +1178,11 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x03000000,
     0x04000000,
-    0x41010000,
+    0x47010000,
     0x03000000,
     0x03000000,
     0x08000000,
-    0x52010000,
+    0x58010000,
     0x02000000,
     0x02000000,
     0x03000000,
@@ -1186,24 +1194,24 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00100000,
     0x03000000,
     0x08000000,
-    0x74010000,
+    0x7a010000,
     0x746e696b,
     0x00377865,
     0x03000000,
     0x04000000,
-    0x80010000,
+    0x86010000,
     0x01000000,
     0x03000000,
     0x04000000,
-    0x90010000,
+    0x96010000,
     0x01000000,
     0x03000000,
     0x04000000,
-    0xa1010000,
+    0xa7010000,
     0x08000000,
     0x03000000,
     0x04000000,
-    0xb8010000,
+    0xbe010000,
     0x04000000,
     0x01000000,
     0x40636d6d,
@@ -1221,16 +1229,16 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x03000000,
     0x04000000,
-    0xc7010000,
+    0xcd010000,
     0x20bcbe00,
     0x03000000,
     0x08000000,
-    0xd9010000,
+    0xdf010000,
     0xe40c0000,
     0xe40c0000,
     0x03000000,
     0x00000000,
-    0xe8010000,
+    0xee010000,
     0x02000000,
     0x02000000,
     0x01000000,
@@ -1253,16 +1261,16 @@ uint32_t reset_vec[reset_vec_size] = {
     0x006b726f,
     0x03000000,
     0x04000000,
-    0x41010000,
+    0x47010000,
     0x03000000,
     0x03000000,
     0x08000000,
-    0x52010000,
+    0x58010000,
     0x03000000,
     0x00000000,
     0x03000000,
     0x06000000,
-    0xf3010000,
+    0xf9010000,
     0x023e1800,
     0x00007fe3,
     0x03000000,
@@ -1280,7 +1288,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000030,
     0x03000000,
     0x04000000,
-    0x05020000,
+    0x0b020000,
     0x02000000,
     0x03000000,
     0x15000000,
@@ -1293,7 +1301,7 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000000,
     0x03000000,
     0x00000000,
-    0x11020000,
+    0x17020000,
     0x03000000,
     0x10000000,
     0x67000000,
@@ -1303,48 +1311,52 @@ uint32_t reset_vec[reset_vec_size] = {
     0x00000100,
     0x03000000,
     0x04000000,
-    0x21020000,
+    0x27020000,
     0x00000000,
     0x03000000,
     0x04000000,
-    0x31020000,
+    0x37020000,
     0x00000000,
     0x03000000,
     0x04000000,
-    0x43020000,
+    0x49020000,
     0x00000000,
     0x03000000,
     0x04000000,
-    0x55020000,
+    0x5b020000,
     0x00000000,
     0x03000000,
     0x04000000,
-    0x69020000,
+    0x6f020000,
     0x08000000,
     0x03000000,
     0x04000000,
-    0x79020000,
+    0x7f020000,
     0x08000000,
     0x03000000,
     0x04000000,
-    0x8a020000,
+    0x90020000,
     0x00000000,
     0x03000000,
     0x04000000,
-    0xa1020000,
+    0xa7020000,
     0x01000000,
     0x03000000,
     0x04000000,
-    0xae020000,
+    0xb4020000,
     0xffffffff,
     0x03000000,
     0x04000000,
-    0xbf020000,
+    0xc5020000,
     0xffffffff,
     0x03000000,
     0x04000000,
     0xb5000000,
     0x01000000,
+    0x03000000,
+    0x04000000,
+    0xbb000000,
+    0x01000000,
     0x02000000,
     0x02000000,
     0x02000000,
@@ -1394,143 +1406,143 @@ uint32_t reset_vec[reset_vec_size] = {
     0x6f632d74,
     0x6f72746e,
     0x72656c6c,
-    0x61687000,
-    0x656c646e,
-    0x69706700,
-    0x6c00736f,
-    0x78756e69,
-    0x6665642c,
-    0x746c7561,
-    0x6972742d,
-    0x72656767,
-    0x74657200,
-    0x2d6e6961,
-    0x74617473,
-    0x75732d65,
-    0x6e657073,
-    0x00646564,
-    0x676e6172,
-    0x69007365,
-    0x7265746e,
-    0x74707572,
-    0x78652d73,
-    0x646e6574,
-    0x72006465,
-    0x6e2d6765,
-    0x73656d61,
-    0x73697200,
-    0x6d2c7663,
-    0x702d7861,
-    0x726f6972,
-    0x00797469,
-    0x63736972,
-    0x646e2c76,
-    0x63007665,
-    0x65727275,
-    0x732d746e,
-    0x64656570,
+    0x6e696c00,
+    0x702c7875,
+    0x646e6168,
+    0x6700656c,
+    0x736f6970,
+    0x6e696c00,
+    0x642c7875,
+    0x75616665,
+    0x742d746c,
+    0x67676972,
+    0x72007265,
+    0x69617465,
+    0x74732d6e,
+    0x2d657461,
+    0x70737573,
+    0x65646e65,
+    0x61720064,
+    0x7365676e,
     0x746e6900,
     0x75727265,
-    0x702d7470,
-    0x6e657261,
-    0x6e690074,
-    0x72726574,
-    0x73747075,
+    0x2d737470,
+    0x65747865,
+    0x6465646e,
     0x67657200,
-    0x6968732d,
-    0x72007466,
-    0x692d6765,
-    0x69772d6f,
-    0x00687464,
-    0x786e6c78,
-    0x6d61662c,
-    0x00796c69,
-    0x786e6c78,
-    0x6669662c,
-    0x78652d6f,
-    0x00747369,
-    0x786e6c78,
-    0x6d756e2c,
-    0x2d73732d,
-    0x73746962,
-    0x6e6c7800,
-    0x756e2c78,
-    0x72742d6d,
-    0x66736e61,
-    0x622d7265,
-    0x00737469,
-    0x786e6c78,
-    0x6b63732c,
-    0x7461722d,
-    0x73006f69,
-    0x6d2d6970,
-    0x662d7861,
-    0x75716572,
-    0x79636e65,
-    0x6c6f7600,
-    0x65676174,
-    0x6e61722d,
-    0x00736567,
-    0x61736964,
-    0x2d656c62,
-    0x6c007077,
-    0x6c61636f,
-    0x63616d2d,
-    0x6464612d,
-    0x73736572,
-    0x70672300,
-    0x632d6f69,
-    0x736c6c65,
-    0x69706700,
-    0x6f632d6f,
-    0x6f72746e,
-    0x72656c6c,
-    0x6e6c7800,
-    0x6c612c78,
-    0x6e692d6c,
-    0x73747570,
-    0x6e6c7800,
-    0x6c612c78,
-    0x6e692d6c,
-    0x73747570,
-    0x7800322d,
+    0x6d616e2d,
+    0x72007365,
+    0x76637369,
+    0x78616d2c,
+    0x6972702d,
+    0x7469726f,
+    0x69720079,
+    0x2c766373,
+    0x7665646e,
+    0x72756300,
+    0x746e6572,
+    0x6570732d,
+    0x69006465,
+    0x7265746e,
+    0x74707572,
+    0x7261702d,
+    0x00746e65,
+    0x65746e69,
+    0x70757272,
+    0x72007374,
+    0x732d6765,
+    0x74666968,
+    0x67657200,
+    0x2d6f692d,
+    0x74646977,
+    0x6c780068,
+    0x662c786e,
+    0x6c696d61,
+    0x6c780079,
+    0x662c786e,
+    0x2d6f6669,
+    0x73697865,
+    0x6c780074,
+    0x6e2c786e,
+    0x732d6d75,
+    0x69622d73,
+    0x78007374,
     0x2c786e6c,
-    0x74756f64,
-    0x6665642d,
-    0x746c7561,
+    0x2d6d756e,
+    0x6e617274,
+    0x72656673,
+    0x7469622d,
+    0x6c780073,
+    0x732c786e,
+    0x722d6b63,
+    0x6f697461,
+    0x69707300,
+    0x78616d2d,
+    0x6572662d,
+    0x6e657571,
+    0x76007963,
+    0x61746c6f,
+    0x722d6567,
+    0x65676e61,
+    0x69640073,
+    0x6c626173,
+    0x70772d65,
+    0x636f6c00,
+    0x6d2d6c61,
+    0x612d6361,
+    0x65726464,
+    0x23007373,
+    0x6f697067,
+    0x6c65632d,
+    0x6700736c,
+    0x2d6f6970,
+    0x746e6f63,
+    0x6c6c6f72,
+    0x78007265,
+    0x2c786e6c,
+    0x2d6c6c61,
+    0x75706e69,
+    0x78007374,
+    0x2c786e6c,
+    0x2d6c6c61,
+    0x75706e69,
+    0x322d7374,
     0x6e6c7800,
     0x6f642c78,
     0x642d7475,
     0x75616665,
-    0x322d746c,
-    0x6e6c7800,
-    0x70672c78,
-    0x772d6f69,
-    0x68746469,
-    0x6e6c7800,
-    0x70672c78,
-    0x2d326f69,
-    0x74646977,
-    0x6c780068,
-    0x692c786e,
-    0x7265746e,
-    0x74707572,
-    0x6572702d,
-    0x746e6573,
-    0x6e6c7800,
-    0x73692c78,
-    0x6175642d,
-    0x6c78006c,
-    0x742c786e,
-    0x642d6972,
-    0x75616665,
     0x7800746c,
     0x2c786e6c,
-    0x2d697274,
-    0x61666564,
-    0x2d746c75,
-    0x00000032,
-    0x00000000,
+    0x74756f64,
+    0x6665642d,
+    0x746c7561,
+    0x7800322d,
+    0x2c786e6c,
+    0x6f697067,
+    0x6469772d,
+    0x78006874,
+    0x2c786e6c,
+    0x6f697067,
+    0x69772d32,
+    0x00687464,
+    0x786e6c78,
+    0x746e692c,
+    0x75727265,
+    0x702d7470,
+    0x65736572,
+    0x7800746e,
+    0x2c786e6c,
+    0x642d7369,
+    0x006c6175,
+    0x786e6c78,
+    0x6972742c,
+    0x6665642d,
+    0x746c7561,
+    0x6e6c7800,
+    0x72742c78,
+    0x65642d69,
+    0x6c756166,
+    0x00322d74,
     0x6c6c6548,
     0x6f57206f,
     0x21646c72,
diff --git a/fpga/src/bootrom/bootrom.sv b/fpga/src/bootrom/bootrom.sv
index 344c4f5a1bf90d587c797f2f0849892bd1e0a3cb..5987194f94f2c4cdd69761a25382bdde23900d36 100644
--- a/fpga/src/bootrom/bootrom.sv
+++ b/fpga/src/bootrom/bootrom.sv
@@ -20,7 +20,7 @@ module bootrom (
    input  logic [63:0]  addr_i,
    output logic [63:0]  rdata_o
 );
-    localparam int RomSize = 860;
+    localparam int RomSize = 866;
 
     const logic [RomSize-1:0][63:0] mem = {
         64'h00000000_00000000,
@@ -119,75 +119,75 @@ module bootrom (
         64'h49505320_74696e69,
         64'h00000a0d_21646c72,
         64'h6f57206f_6c6c6548,
-        64'h00000000_00000032,
-        64'h2d746c75_61666564,
-        64'h2d697274_2c786e6c,
-        64'h7800746c_75616665,
-        64'h642d6972_742c786e,
-        64'h6c78006c_6175642d,
-        64'h73692c78_6e6c7800,
-        64'h746e6573_6572702d,
-        64'h74707572_7265746e,
-        64'h692c786e_6c780068,
-        64'h74646977_2d326f69,
-        64'h70672c78_6e6c7800,
-        64'h68746469_772d6f69,
-        64'h70672c78_6e6c7800,
-        64'h322d746c_75616665,
-        64'h642d7475_6f642c78,
+        64'h00322d74_6c756166,
+        64'h65642d69_72742c78,
         64'h6e6c7800_746c7561,
+        64'h6665642d_6972742c,
+        64'h786e6c78_006c6175,
+        64'h642d7369_2c786e6c,
+        64'h7800746e_65736572,
+        64'h702d7470_75727265,
+        64'h746e692c_786e6c78,
+        64'h00687464_69772d32,
+        64'h6f697067_2c786e6c,
+        64'h78006874_6469772d,
+        64'h6f697067_2c786e6c,
+        64'h7800322d_746c7561,
         64'h6665642d_74756f64,
-        64'h2c786e6c_7800322d,
-        64'h73747570_6e692d6c,
-        64'h6c612c78_6e6c7800,
-        64'h73747570_6e692d6c,
-        64'h6c612c78_6e6c7800,
-        64'h72656c6c_6f72746e,
-        64'h6f632d6f_69706700,
-        64'h736c6c65_632d6f69,
-        64'h70672300_73736572,
-        64'h6464612d_63616d2d,
-        64'h6c61636f_6c007077,
-        64'h2d656c62_61736964,
-        64'h00736567_6e61722d,
-        64'h65676174_6c6f7600,
-        64'h79636e65_75716572,
-        64'h662d7861_6d2d6970,
-        64'h73006f69_7461722d,
-        64'h6b63732c_786e6c78,
-        64'h00737469_622d7265,
-        64'h66736e61_72742d6d,
-        64'h756e2c78_6e6c7800,
-        64'h73746962_2d73732d,
-        64'h6d756e2c_786e6c78,
-        64'h00747369_78652d6f,
-        64'h6669662c_786e6c78,
-        64'h00796c69_6d61662c,
-        64'h786e6c78_00687464,
-        64'h69772d6f_692d6765,
-        64'h72007466_6968732d,
-        64'h67657200_73747075,
-        64'h72726574_6e690074,
-        64'h6e657261_702d7470,
-        64'h75727265_746e6900,
-        64'h64656570_732d746e,
-        64'h65727275_63007665,
-        64'h646e2c76_63736972,
-        64'h00797469_726f6972,
-        64'h702d7861_6d2c7663,
-        64'h73697200_73656d61,
-        64'h6e2d6765_72006465,
-        64'h646e6574_78652d73,
+        64'h2c786e6c_7800746c,
+        64'h75616665_642d7475,
+        64'h6f642c78_6e6c7800,
+        64'h322d7374_75706e69,
+        64'h2d6c6c61_2c786e6c,
+        64'h78007374_75706e69,
+        64'h2d6c6c61_2c786e6c,
+        64'h78007265_6c6c6f72,
+        64'h746e6f63_2d6f6970,
+        64'h6700736c_6c65632d,
+        64'h6f697067_23007373,
+        64'h65726464_612d6361,
+        64'h6d2d6c61_636f6c00,
+        64'h70772d65_6c626173,
+        64'h69640073_65676e61,
+        64'h722d6567_61746c6f,
+        64'h76007963_6e657571,
+        64'h6572662d_78616d2d,
+        64'h69707300_6f697461,
+        64'h722d6b63_732c786e,
+        64'h6c780073_7469622d,
+        64'h72656673_6e617274,
+        64'h2d6d756e_2c786e6c,
+        64'h78007374_69622d73,
+        64'h732d6d75_6e2c786e,
+        64'h6c780074_73697865,
+        64'h2d6f6669_662c786e,
+        64'h6c780079_6c696d61,
+        64'h662c786e_6c780068,
+        64'h74646977_2d6f692d,
+        64'h67657200_74666968,
+        64'h732d6765_72007374,
+        64'h70757272_65746e69,
+        64'h00746e65_7261702d,
         64'h74707572_7265746e,
-        64'h69007365_676e6172,
-        64'h00646564_6e657073,
-        64'h75732d65_74617473,
-        64'h2d6e6961_74657200,
-        64'h72656767_6972742d,
-        64'h746c7561_6665642c,
-        64'h78756e69_6c00736f,
-        64'h69706700_656c646e,
-        64'h61687000_72656c6c,
+        64'h69006465_6570732d,
+        64'h746e6572_72756300,
+        64'h7665646e_2c766373,
+        64'h69720079_7469726f,
+        64'h6972702d_78616d2c,
+        64'h76637369_72007365,
+        64'h6d616e2d_67657200,
+        64'h6465646e_65747865,
+        64'h2d737470_75727265,
+        64'h746e6900_7365676e,
+        64'h61720064_65646e65,
+        64'h70737573_2d657461,
+        64'h74732d6e_69617465,
+        64'h72007265_67676972,
+        64'h742d746c_75616665,
+        64'h642c7875_6e696c00,
+        64'h736f6970_6700656c,
+        64'h646e6168_702c7875,
+        64'h6e696c00_72656c6c,
         64'h6f72746e_6f632d74,
         64'h70757272_65746e69,
         64'h00736c6c_65632d74,
@@ -212,39 +212,41 @@ module bootrom (
         64'h73736572_64646123,
         64'h09000000_02000000,
         64'h02000000_02000000,
+        64'h01000000_bb000000,
+        64'h04000000_03000000,
         64'h01000000_b5000000,
         64'h04000000_03000000,
-        64'hffffffff_bf020000,
+        64'hffffffff_c5020000,
         64'h04000000_03000000,
-        64'hffffffff_ae020000,
+        64'hffffffff_b4020000,
         64'h04000000_03000000,
-        64'h01000000_a1020000,
+        64'h01000000_a7020000,
         64'h04000000_03000000,
-        64'h00000000_8a020000,
+        64'h00000000_90020000,
         64'h04000000_03000000,
-        64'h08000000_79020000,
+        64'h08000000_7f020000,
         64'h04000000_03000000,
-        64'h08000000_69020000,
+        64'h08000000_6f020000,
         64'h04000000_03000000,
-        64'h00000000_55020000,
+        64'h00000000_5b020000,
         64'h04000000_03000000,
-        64'h00000000_43020000,
+        64'h00000000_49020000,
         64'h04000000_03000000,
-        64'h00000000_31020000,
+        64'h00000000_37020000,
         64'h04000000_03000000,
-        64'h00000000_21020000,
+        64'h00000000_27020000,
         64'h04000000_03000000,
         64'h00000100_00000000,
         64'h00000040_00000000,
         64'h67000000_10000000,
-        64'h03000000_11020000,
+        64'h03000000_17020000,
         64'h00000000_03000000,
         64'h00000000_612e3030,
         64'h2e312d6f_6970672d,
         64'h7370782c_786e6c78,
         64'h1b000000_15000000,
         64'h03000000_02000000,
-        64'h05020000_04000000,
+        64'h0b020000_04000000,
         64'h03000000_00000030,
         64'h30303030_30303440,
         64'h6f697067_01000000,
@@ -253,11 +255,11 @@ module bootrom (
         64'h00000000_67000000,
         64'h10000000_03000000,
         64'h00007fe3_023e1800,
-        64'hf3010000_06000000,
+        64'hf9010000_06000000,
         64'h03000000_00000000,
-        64'h03000000_52010000,
+        64'h03000000_58010000,
         64'h08000000_03000000,
-        64'h03000000_41010000,
+        64'h03000000_47010000,
         64'h04000000_03000000,
         64'h006b726f_7774656e,
         64'h5b000000_08000000,
@@ -269,11 +271,11 @@ module bootrom (
         64'h40687465_2d637369,
         64'h72776f6c_01000000,
         64'h02000000_02000000,
-        64'he8010000_00000000,
+        64'hee010000_00000000,
         64'h03000000_e40c0000,
-        64'he40c0000_d9010000,
+        64'he40c0000_df010000,
         64'h08000000_03000000,
-        64'h20bcbe00_c7010000,
+        64'h20bcbe00_cd010000,
         64'h04000000_03000000,
         64'h00000000_67000000,
         64'h04000000_03000000,
@@ -282,24 +284,24 @@ module bootrom (
         64'h1b000000_0d000000,
         64'h03000000_00000030,
         64'h40636d6d_01000000,
-        64'h04000000_b8010000,
+        64'h04000000_be010000,
         64'h04000000_03000000,
-        64'h08000000_a1010000,
+        64'h08000000_a7010000,
         64'h04000000_03000000,
-        64'h01000000_90010000,
+        64'h01000000_96010000,
         64'h04000000_03000000,
-        64'h01000000_80010000,
+        64'h01000000_86010000,
         64'h04000000_03000000,
         64'h00377865_746e696b,
-        64'h74010000_08000000,
+        64'h7a010000_08000000,
         64'h03000000_00100000,
         64'h00000000_00000020,
         64'h00000000_67000000,
         64'h10000000_03000000,
         64'h02000000_02000000,
-        64'h52010000_08000000,
+        64'h58010000_08000000,
         64'h03000000_03000000,
-        64'h41010000_04000000,
+        64'h47010000_04000000,
         64'h03000000_00000000,
         64'h0f000000_04000000,
         64'h03000000_01000000,
@@ -315,16 +317,16 @@ module bootrom (
         64'h30303032_40697073,
         64'h2d737078_01000000,
         64'h02000000_04000000,
-        64'h67010000_04000000,
+        64'h6d010000_04000000,
         64'h03000000_02000000,
-        64'h5d010000_04000000,
+        64'h63010000_04000000,
         64'h03000000_01000000,
-        64'h52010000_04000000,
+        64'h58010000_04000000,
         64'h03000000_03000000,
-        64'h41010000_04000000,
+        64'h47010000_04000000,
         64'h03000000_00c20100,
-        64'h33010000_04000000,
-        64'h03000000_80c3c901,
+        64'h39010000_04000000,
+        64'h03000000_80f0fa02,
         64'h4b000000_04000000,
         64'h03000000_00100000,
         64'h00000000_00000010,
@@ -336,13 +338,13 @@ module bootrom (
         64'h30303030_30303140,
         64'h74726175_01000000,
         64'h02000000_006c6f72,
-        64'h746e6f63_0b010000,
+        64'h746e6f63_11010000,
         64'h08000000_03000000,
         64'h00100000_00000000,
         64'h00000000_00000000,
         64'h67000000_10000000,
         64'h03000000_ffff0000,
-        64'h02000000_f7000000,
+        64'h02000000_fd000000,
         64'h08000000_03000000,
         64'h00333130_2d677562,
         64'h65642c76_63736972,
@@ -351,18 +353,20 @@ module bootrom (
         64'h72656c6c_6f72746e,
         64'h6f632d67_75626564,
         64'h01000000_02000000,
+        64'h03000000_bb000000,
+        64'h04000000_03000000,
         64'h03000000_b5000000,
         64'h04000000_03000000,
-        64'h03000000_28010000,
+        64'h03000000_2e010000,
         64'h04000000_03000000,
-        64'h07000000_15010000,
+        64'h07000000_1b010000,
         64'h04000000_03000000,
         64'h00000004_00000000,
         64'h0000000c_00000000,
         64'h67000000_10000000,
         64'h03000000_09000000,
         64'h02000000_0b000000,
-        64'h02000000_f7000000,
+        64'h02000000_fd000000,
         64'h10000000_03000000,
         64'ha0000000_00000000,
         64'h03000000_00306369,
@@ -378,14 +382,14 @@ module bootrom (
         64'h6f632d74_70757272,
         64'h65746e69_01000000,
         64'h02000000_006c6f72,
-        64'h746e6f63_0b010000,
+        64'h746e6f63_11010000,
         64'h08000000_03000000,
         64'h00000c00_00000000,
         64'h00000002_00000000,
         64'h67000000_10000000,
         64'h03000000_07000000,
         64'h02000000_03000000,
-        64'h02000000_f7000000,
+        64'h02000000_fd000000,
         64'h10000000_03000000,
         64'h00000000_30746e69,
         64'h6c632c76_63736972,
@@ -393,7 +397,7 @@ module bootrom (
         64'h03000000_00000030,
         64'h30303030_30324074,
         64'h6e696c63_01000000,
-        64'hf0000000_00000000,
+        64'hf6000000_00000000,
         64'h03000000_00007375,
         64'h622d656c_706d6973,
         64'h00636f73_2d657261,
@@ -406,13 +410,13 @@ module bootrom (
         64'h04000000_03000000,
         64'h00636f73_01000000,
         64'h02000000_02000000,
-        64'hd9000000_00000000,
+        64'hdf000000_00000000,
         64'h03000000_00000074,
         64'h61656274_72616568,
-        64'hc3000000_0a000000,
+        64'hc9000000_0a000000,
         64'h03000000_00000000,
         64'h01000000_01000000,
-        64'hbd000000_0c000000,
+        64'hc3000000_0c000000,
         64'h03000000_00000064,
         64'h656c2d74_61656274,
         64'h72616568_01000000,
@@ -431,6 +435,8 @@ module bootrom (
         64'h38407972_6f6d656d,
         64'h01000000_02000000,
         64'h02000000_02000000,
+        64'h02000000_bb000000,
+        64'h04000000_03000000,
         64'h02000000_b5000000,
         64'h04000000_03000000,
         64'h00006374_6e692d75,
@@ -461,11 +467,11 @@ module bootrom (
         64'h67000000_04000000,
         64'h03000000_00757063,
         64'h5b000000_04000000,
-        64'h03000000_80c3c901,
+        64'h03000000_80f0fa02,
         64'h4b000000_04000000,
         64'h03000000_00000030,
         64'h40757063_01000000,
-        64'h40787d01_38000000,
+        64'hc0e1e400_38000000,
         64'h04000000_03000000,
         64'h00000000_0f000000,
         64'h04000000_03000000,
@@ -494,11 +500,11 @@ module bootrom (
         64'h00000000_01000000,
         64'h00000000_00000000,
         64'h00000000_00000000,
-        64'hd0080000_d2020000,
+        64'h00090000_d8020000,
         64'h00000000_10000000,
         64'h11000000_28000000,
-        64'h08090000_38000000,
-        64'hda0b0000_edfe0dd0,
+        64'h38090000_38000000,
+        64'h100c0000_edfe0dd0,
         64'h00000000_00000000,
         64'h00000000_00000000,
         64'h00000000_00000000,
@@ -544,92 +550,92 @@ module bootrom (
         64'h01f41413_0010041b,
         64'he911d23f_f0ef057e,
         64'h65a14505_edcff0ef,
-        64'hd5050513_00001517,
-        64'hea4ff0ef_e4063805,
+        64'hd8050513_00001517,
+        64'hea4ff0ef_e4060805,
         64'h05132005_85931141,
-        64'h01c9c537_65f1bbb5,
-        64'hf00ff0ef_06450513,
-        64'h00001517_b3f5dbe5,
+        64'h02faf537_65f1bbb5,
+        64'hf00ff0ef_09450513,
+        64'h00001517_b3f5dee5,
         64'h05130000_1517f98f,
         64'hf0ef8526_f1cff0ef,
-        64'hec050513_00001517,
-        64'hf28ff0ef_eb450513,
+        64'hef050513_00001517,
+        64'hf28ff0ef_ee450513,
         64'h00001517_c50d84aa,
         64'hc33ff0ef_8552865a,
         64'h020aa583_f44ff0ef,
-        64'h09050513_00001517,
+        64'h0c050513_00001517,
         64'hf57993e3_08048493,
-        64'hf58ff0ef_2985e0e5,
+        64'hf58ff0ef_2985e3e5,
         64'h05130000_1517ff2c,
         64'h1be382ff_f0ef0905,
         64'h00094503_f74ff0ef,
-        64'h0b050513_00001517,
+        64'h0e050513_00001517,
         64'h803ff0ef_7088f86f,
-        64'hf0ef0b25_05130000,
+        64'hf0ef0e25_05130000,
         64'h1517815f_f0ef6c88,
-        64'hf98ff0ef_0b450513,
+        64'hf98ff0ef_0e450513,
         64'h00001517_827ff0ef,
         64'h07048c13_02848913,
-        64'h6888fb2f_f0ef0be5,
+        64'h6888fb2f_f0ef0ee5,
         64'h05130000_1517ff2c,
         64'h1be3887f_f0ef0905,
         64'h00094503_01090c13,
-        64'hfd0ff0ef_0bc50513,
+        64'hfd0ff0ef_0ec50513,
         64'h00001517_fe991be3,
         64'h8a5ff0ef_09050009,
         64'h4503ff04_8913feef,
-        64'hf0ef0ba5_05130000,
+        64'hf0ef0ea5_05130000,
         64'h15178bff_f0ef0ff9,
-        64'hf513803f_f0ef0b65,
+        64'hf513803f_f0ef0e65,
         64'h05130000_1517b5fd,
-        64'hec050513_00001517,
+        64'hef050513_00001517,
         64'h89bff0ef_854e81ff,
-        64'hf0effc25_05130000,
-        64'h151782bf_f0effb65,
+        64'hf0efff25_05130000,
+        64'h151782bf_f0effe65,
         64'h05130000_1517c50d,
         64'h080489aa_8a8ad39f,
         64'hf0ef850a_46057101,
         64'h04892583_84dff0ef,
-        64'hf0050513_00001517,
+        64'hf3050513_00001517,
         64'h89bff0ef_455685ff,
-        64'hf0ef0f25_05130000,
+        64'hf0ef1225_05130000,
         64'h15178adf_f0ef4546,
-        64'h871ff0ef_0e450513,
+        64'h871ff0ef_11450513,
         64'h00001517_8ffff0ef,
-        64'h6526883f_f0ef0d65,
+        64'h6526883f_f0ef1065,
         64'h05130000_1517911f,
         64'hf0ef7502_895ff0ef,
-        64'h0d850513_00001517,
+        64'h10850513_00001517,
         64'h923ff0ef_65628a7f,
-        64'hf0ef0d25_05130000,
+        64'hf0ef1025_05130000,
         64'h15178f5f_f0ef4552,
-        64'h8b9ff0ef_0d450513,
+        64'h8b9ff0ef_10450513,
         64'h00001517_907ff0ef,
-        64'h45428cbf_f0ef0d65,
+        64'h45428cbf_f0ef1065,
         64'h05130000_1517919f,
         64'hf0ef4532_8ddff0ef,
-        64'h0d850513_00001517,
+        64'h10850513_00001517,
         64'h92bff0ef_45228eff,
-        64'hf0ef0da5_05130000,
+        64'hf0ef10a5_05130000,
         64'h151797df_f0ef4b91,
-        64'h6502903f_f0ef0de5,
+        64'h6502903f_f0ef10e5,
         64'h05130000_151790ff,
-        64'hf0ef0ca5_05130000,
+        64'hf0ef0fa5_05130000,
         64'h1517bf61_54f991ff,
-        64'hf0effd25_05130000,
+        64'hf0ef0025_05130000,
         64'h15179adf_f0ef8526,
-        64'h931ff0ef_0d450513,
+        64'h931ff0ef_10450513,
         64'h00001517_93dff0ef,
-        64'h0c850513_00001517,
+        64'h0f850513_00001517,
         64'hc90584aa_890ae49f,
         64'hf0ef850a_45854605,
-        64'h710195bf_f0ef0ce5,
+        64'h710195bf_f0ef0fe5,
         64'h05130000_15178082,
         64'h61616c02_6ba26b42,
         64'h6ae27a02_79a27942,
         64'h74e26406_852660a6,
         64'hfb040113_54fd987f,
-        64'hf0ef0d25_05130000,
+        64'hf0ef1025_05130000,
         64'h1517c51d_df3ff0ef,
         64'h8b2e8a2a_0880e062,
         64'he45eec56_f44ef84a,
@@ -638,7 +644,7 @@ module bootrom (
         64'h80826169_6baa6b4a,
         64'h6aea7a0a_79aa794a,
         64'h74ea640e_60ae8522,
-        64'h547d9d3f_f0ef0f65,
+        64'h547d9d3f_f0ef1265,
         64'h05130000_1517c59f,
         64'hf0efc5df_f0efc61f,
         64'hf0efc65f_f0efc69f,
@@ -647,7 +653,7 @@ module bootrom (
         64'hc7bff0ef_c87ff0ef,
         64'h45314581_46054401,
         64'hf93046e3_19fda17f,
-        64'hf0ef15a5_05130000,
+        64'hf0ef18a5_05130000,
         64'h1517e799_0359e7b3,
         64'h07241a63_29019041,
         64'h14428c49_cafff0ef,
@@ -694,13 +700,13 @@ module bootrom (
         64'h57f9efbf_f0efc911,
         64'h57fdeb7f_f0effc6d,
         64'he03ff0ef_347d4429,
-        64'hb91ff0ef_29c50513,
+        64'hb91ff0ef_2cc50513,
         64'h00001517_c89ff0ef,
         64'he022e406_11418082,
         64'h61050015_351364a2,
         64'h644260e2_0004051b,
         64'hfc940ce3_e37ff0ef,
-        64'heb3ff0ef_2c450513,
+        64'heb3ff0ef_2f450513,
         64'h00001517_85aa842a,
         64'he53ff0ef_02900513,
         64'h400005b7_07700613,
@@ -708,7 +714,7 @@ module bootrom (
         64'hec06e426_11018082,
         64'h01410015_3513157d,
         64'h640260a2_0004051b,
-        64'hef3ff0ef_2fe50513,
+        64'hef3ff0ef_32e50513,
         64'h85a20000_1517e89f,
         64'hf0ef842a_e97ff0ef,
         64'he022e406_03700513,
@@ -727,20 +733,20 @@ module bootrom (
         64'h06131101_bfcd4501,
         64'h80826105_690264a2,
         64'h644260e2_4505f89f,
-        64'hf0ef4585_38c50513,
+        64'hf0ef4585_3bc50513,
         64'h00001517_fe9915e3,
         64'hc00df25f_f0ef892a,
         64'h347df35f_f0ef4501,
         64'h45810950_06134485,
         64'h71040413_e04aec06,
         64'he4266409_e8221101,
-        64'hcd1ff06f_61053865,
+        64'hcd1ff06f_61053b65,
         64'h05130000_151760e2,
         64'h6442da7f_f0ef852e,
-        64'h65a2cebf_f0ef3ce5,
+        64'h65a2cebf_f0ef3fe5,
         64'h05130000_1517cf7f,
         64'hf0ef8522_cfdff0ef,
-        64'he42eec06_3d450513,
+        64'he42eec06_40450513,
         64'h00001517_842ae822,
         64'h11018082_614564e2,
         64'h740270a2_f47d147d,
@@ -777,9 +783,9 @@ module bootrom (
         64'hd3b84719_dbb86442,
         64'h60e20ff4_7513577d,
         64'h200007b7_e25ff0ef,
-        64'h4d850513_00001517,
+        64'h50850513_00001517,
         64'heb3ff0ef_91011502,
-        64'h4088e3bf_f0ef4f65,
+        64'h4088e3bf_f0ef5265,
         64'h05130000_1517e395,
         64'h8b852401_53fc57e0,
         64'hff658b05_06478493,
@@ -788,24 +794,24 @@ module bootrom (
         64'h00010640_0793d7a8,
         64'hdbb85779_e426e822,
         64'hec062000_07b71101,
-        64'he81ff06f_61055265,
+        64'he81ff06f_61055565,
         64'h05130000_151764a2,
         64'h60e26442_d03c4799,
-        64'he99ff0ef_54c50513,
+        64'he99ff0ef_57c50513,
         64'h00001517_f27ff0ef,
         64'h91010204_95132481,
-        64'heb1ff0ef_54450513,
+        64'heb1ff0ef_57450513,
         64'h00001517_5064d03c,
         64'h16600793_ec5ff0ef,
-        64'h57850513_00001517,
+        64'h5a850513_00001517,
         64'hf53ff0ef_91010204,
         64'h95132481_eddff0ef,
-        64'h57050513_00001517,
+        64'h5a050513_00001517,
         64'h5064d03c_10400793,
         64'h20000437_fff537fd,
         64'h000147a9_c3b84729,
         64'h200007b7_f05ff0ef,
-        64'he426e822_ec065905,
+        64'he426e822_ec065c05,
         64'h05131101_00001517,
         64'h80824108_8082c10c,
         64'h80826105_60e2ecff,
diff --git a/fpga/src/bootrom/src/main.c b/fpga/src/bootrom/src/main.c
index 27c1b24acbf6a031607a99108120659c5953858b..316792b2819107bf0594d52bef9079427a94023e 100644
--- a/fpga/src/bootrom/src/main.c
+++ b/fpga/src/bootrom/src/main.c
@@ -5,7 +5,7 @@
 
 int main()
 {
-    init_uart(30000000, 115200);
+    init_uart(50000000, 115200);
     print_uart("Hello World!\r\n");
 
     int res = gpt_find_boot_partition((uint8_t *)0x80000000UL, 2 * 16384);
diff --git a/fpga/src/bootrom/startup.S b/fpga/src/bootrom/startup.S
index 76a49801def987af4ac449eaee0e6806cfb2a197..508f2a51e3aa653199574c43b0a8da378c196778 100644
--- a/fpga/src/bootrom/startup.S
+++ b/fpga/src/bootrom/startup.S
@@ -1,6 +1,6 @@
 # start sequence of the bootloader
-# 
-# 
+#
+#
 #include <smp.h>
 #define DRAM_BASE 0x80000000
 
diff --git a/fpga/src/genesysii.svh b/fpga/src/genesysii.svh
index 8f73d26c7129680855602fac9299be17165b765d..4c72931ad9c6dc18a29dc81d27232dae3257ece7 100644
--- a/fpga/src/genesysii.svh
+++ b/fpga/src/genesysii.svh
@@ -12,3 +12,13 @@
 // Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
 
 `define GENESYSII
+
+`define PITON_FPGA_SYNTH
+`define ARIANE_DATA_WIDTH 64
+
+// Instantiate protocl checker
+// `define PROTOCOL_CHECKER
+
+// Use OpenPiton Caches
+`define PITON_ARIANE
+`define AXI64_CACHE_PORTS
\ No newline at end of file
diff --git a/fpga/xilinx/ariane_xlnx_ip.yml b/fpga/xilinx/ariane_xlnx_ip.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2b3c0c1e5185e765f4b03eb72ba9566145c47e68
--- /dev/null
+++ b/fpga/xilinx/ariane_xlnx_ip.yml
@@ -0,0 +1,92 @@
+xlnx_axi_dwidth_converter:
+  ip: axi_dwidth_converter
+  vendor: xilinx.com
+  config:
+    si_data_width: 64
+    si_id_width: 5
+    mi_data_width: 32
+
+xlnx_axi_clock_converter:
+  ip: axi_clock_converter
+  vendor: xilinx.com
+  config:
+    width: 64
+    data_width: 64
+    id_width: 5
+
+xlnx_axi_gpio:
+  ip: axi_gpio
+  vendor: xilinx.com
+  config:
+    c_gpio_width: 8
+    c_gpio2_width:  8
+    c_is_dual: 1
+    c_all_inputs_2: 1
+    c_interrupt_present: 0
+
+xlnx_axi_quad_spi:
+  ip: axi_quad_spi
+  vendor: xilinx.com
+  config:
+    c_use_startup: 0
+    c_sck_ratio: 4
+    c_fifo_depth: 256
+    c_type_of_axi4_interface: 1
+    c_s_axi4_id_width: 0
+
+xlnx_clk_gen:
+  ip: clk_wiz
+  vendor: xilinx.com
+  config:
+    prim_in_freq: 200
+    num_out_clks: 4
+    clkout2_used: true
+    clkout3_used: true
+    clkout4_used: true
+    clkout1_requested_out_freq: 50
+    clkout2_requested_out_freq: 125
+    clkout3_requested_out_freq: 125
+    clkout3_requested_phase: 90
+    clkout4_requested_out_freq: 50
+    clkin1_jitter_ps: 50
+
+xlnx_ila:
+  ip: ila
+  vendor: xilinx.com
+  config:
+    c_num_of_probes: 8
+    c_probe3_width: 4
+    c_probe6_width: 4
+    c_data_depth: 16384
+    c_input_pipe_stages: 1
+
+xlnx_mig_7_ddr3:
+  ip: mig_7series
+  vendor: xilinx.com
+  config:
+    xml_input_file: mig_a.prj
+    reset_board_interface: Custom
+    mig_dont_touch_param: Custom
+    board_mig_param: Custom
+
+xlnx_ila:
+  ip: xlnx_ila
+  vendor: xilinx.com
+  config:
+    addr_width: 64
+    data_width: 64
+    id_width: 5
+    awuser_width: 1
+    aruser_width: 1
+    ruser_width: 1
+    wuser_width: 1
+    buser_width: 1
+    max_aw_waits: 1024
+    max_ar_waits: 1024
+    max_w_waits: 1024
+    max_r_waits: 1024
+    max_b_waits: 1024
+    max_continuous_wtransfers_waits: 1024
+    max_wlast_to_awvalid_waits: 1024
+    max_write_to_bvalid_waits: 1024
+    max_continuous_rtransfers_waits: 1024
\ No newline at end of file
diff --git a/fpga/xilinx/xlnx_axi_clock_converter/tcl/run.tcl b/fpga/xilinx/xlnx_axi_clock_converter/tcl/run.tcl
index 8c14214ae20fd7a4b252876574600aca4f154fd3..ba0551e7f361e1005d2588464133b688a27b7c7f 100644
--- a/fpga/xilinx/xlnx_axi_clock_converter/tcl/run.tcl
+++ b/fpga/xilinx/xlnx_axi_clock_converter/tcl/run.tcl
@@ -3,7 +3,7 @@ set boardName  $::env(XILINX_BOARD)
 
 set ipName xlnx_axi_clock_converter
 
-create_project $ipName . -part $partNumber
+create_project $ipName . -force -part $partNumber
 set_property board_part $boardName [current_project]
 
 create_ip -name axi_clock_converter -vendor xilinx.com -library ip -module_name $ipName
diff --git a/fpga/xilinx/xlnx_axi_dwidth_converter/tcl/run.tcl b/fpga/xilinx/xlnx_axi_dwidth_converter/tcl/run.tcl
index 39fcaff850eeba96d7122fa14af3f52960b1f1a7..dab9f4627711ed929dee0b592321187a613f9372 100644
--- a/fpga/xilinx/xlnx_axi_dwidth_converter/tcl/run.tcl
+++ b/fpga/xilinx/xlnx_axi_dwidth_converter/tcl/run.tcl
@@ -3,7 +3,7 @@ set boardName  $::env(XILINX_BOARD)
 
 set ipName xlnx_axi_dwidth_converter
 
-create_project $ipName . -part $partNumber
+create_project $ipName . -force -part $partNumber
 set_property board_part $boardName [current_project]
 
 create_ip -name axi_dwidth_converter -vendor xilinx.com -library ip -module_name $ipName
diff --git a/fpga/xilinx/xlnx_axi_gpio/tcl/run.tcl b/fpga/xilinx/xlnx_axi_gpio/tcl/run.tcl
index 7ec5415e45560e3ecb32e5cd502653916fe387ab..6f8bad9f44226f4ad93c34f97718ae6fd749e0aa 100644
--- a/fpga/xilinx/xlnx_axi_gpio/tcl/run.tcl
+++ b/fpga/xilinx/xlnx_axi_gpio/tcl/run.tcl
@@ -3,7 +3,7 @@ set boardName  $::env(XILINX_BOARD)
 
 set ipName xlnx_axi_gpio
 
-create_project $ipName . -part $partNumber
+create_project $ipName . -force -part $partNumber
 set_property board_part $boardName [current_project]
 
 create_ip -name axi_gpio -vendor xilinx.com -library ip -module_name $ipName
diff --git a/fpga/xilinx/xlnx_clk_gen/tcl/run.tcl b/fpga/xilinx/xlnx_clk_gen/tcl/run.tcl
index 82e564d7d3098bc9ab55d769ca57d293deb6c363..e1fba9daea50b09f19961b6ce659ef048d7b442d 100644
--- a/fpga/xilinx/xlnx_clk_gen/tcl/run.tcl
+++ b/fpga/xilinx/xlnx_clk_gen/tcl/run.tcl
@@ -3,7 +3,7 @@ set boardName  $::env(XILINX_BOARD)
 
 set ipName xlnx_clk_gen
 
-create_project $ipName . -part $partNumber
+create_project $ipName . -force -part $partNumber
 set_property board_part $boardName [current_project]
 
 create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName
@@ -13,10 +13,11 @@ set_property -dict [list CONFIG.PRIM_IN_FREQ {200.000} \
                         CONFIG.CLKOUT2_USED {true} \
                         CONFIG.CLKOUT3_USED {true} \
                         CONFIG.CLKOUT4_USED {true} \
-                        CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {30} \
+                        CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {50} \
                         CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {125} \
                         CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {125} \
                         CONFIG.CLKOUT3_REQUESTED_PHASE {90.000} \
+                        CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {50} \
                         CONFIG.CLKIN1_JITTER_PS {50.0} \
                        ] [get_ips $ipName]
 
diff --git a/fpga/xilinx/xlnx_ila/tcl/run.tcl b/fpga/xilinx/xlnx_ila/tcl/run.tcl
index 640b248353eb87cdc85a3feed87f6672d6fad3e3..9aff7b113abdf9f8c6919de60f38c49f64b59bbe 100644
--- a/fpga/xilinx/xlnx_ila/tcl/run.tcl
+++ b/fpga/xilinx/xlnx_ila/tcl/run.tcl
@@ -3,11 +3,16 @@ set boardName  $::env(XILINX_BOARD)
 
 set ipName xlnx_ila
 
-create_project $ipName . -part $partNumber
+create_project $ipName . -force -part $partNumber
 set_property board_part $boardName [current_project]
 
 create_ip -name ila -vendor xilinx.com -library ip -module_name $ipName
-set_property -dict [list CONFIG.C_PROBE6_WIDTH {4} CONFIG.C_PROBE3_WIDTH {4} CONFIG.C_DATA_DEPTH {16384} CONFIG.C_NUM_OF_PROBES {8} CONFIG.C_INPUT_PIPE_STAGES {1}] [get_ips $ipName]
+set_property -dict [list  CONFIG.C_NUM_OF_PROBES {8} \
+                          CONFIG.C_PROBE3_WIDTH {4} \
+                          CONFIG.C_PROBE6_WIDTH {4} \
+                          CONFIG.C_DATA_DEPTH {16384}  \
+                          CONFIG.C_INPUT_PIPE_STAGES {1} \
+                    ] [get_ips $ipName]
 
 
 generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci]
diff --git a/fpga/xilinx/xlnx_mig_7_ddr3/tcl/run.tcl b/fpga/xilinx/xlnx_mig_7_ddr3/tcl/run.tcl
index db0887620e744c7cfc87e98567aaf737d1eb1f94..324be30155755ee8916ada70fe19e65150d3d41c 100644
--- a/fpga/xilinx/xlnx_mig_7_ddr3/tcl/run.tcl
+++ b/fpga/xilinx/xlnx_mig_7_ddr3/tcl/run.tcl
@@ -3,7 +3,7 @@ set boardName  $::env(XILINX_BOARD)
 
 set ipName xlnx_mig_7_ddr3
 
-create_project $ipName . -part $partNumber
+create_project $ipName . -force -part $partNumber
 set_property board_part $boardName [current_project]
 
 create_ip -name mig_7series -vendor xilinx.com -library ip -module_name $ipName
diff --git a/fpga/xilinx/xlnx_protocol_checker/Makefile b/fpga/xilinx/xlnx_protocol_checker/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..409144b2e75dff4550547a0ad186623ec4b1a576
--- /dev/null
+++ b/fpga/xilinx/xlnx_protocol_checker/Makefile
@@ -0,0 +1,2 @@
+PROJECT:=xlnx_protocol_checker
+include ../common.mk
\ No newline at end of file
diff --git a/fpga/xilinx/xlnx_protocol_checker/tcl/run.tcl b/fpga/xilinx/xlnx_protocol_checker/tcl/run.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..143d9fdb61b726d0da5a7a7f3f63260c6db8a1ce
--- /dev/null
+++ b/fpga/xilinx/xlnx_protocol_checker/tcl/run.tcl
@@ -0,0 +1,35 @@
+set partNumber $::env(XILINX_PART)
+set boardName  $::env(XILINX_BOARD)
+
+set ipName xlnx_protocol_checker
+
+create_project $ipName . -force -part $partNumber
+set_property board_part $boardName [current_project]
+
+create_ip -name axi_protocol_checker -vendor xilinx.com -library ip -version 2.0 -module_name $ipName
+
+set_property -dict [list  CONFIG.ADDR_WIDTH {64} \
+                          CONFIG.DATA_WIDTH {64} \
+                          CONFIG.ID_WIDTH {5} \
+                          CONFIG.AWUSER_WIDTH {1} \
+                          CONFIG.ARUSER_WIDTH {1} \
+                          CONFIG.RUSER_WIDTH {1} \
+                          CONFIG.WUSER_WIDTH {1} \
+                          CONFIG.BUSER_WIDTH {1} \
+                          CONFIG.MAX_AW_WAITS {1024} \
+                          CONFIG.MAX_AR_WAITS {1024} \
+                          CONFIG.MAX_W_WAITS {1024} \
+                          CONFIG.MAX_R_WAITS {1024} \
+                          CONFIG.MAX_B_WAITS {1024} \
+                          CONFIG.MAX_CONTINUOUS_WTRANSFERS_WAITS {1024} \
+                          CONFIG.MAX_WLAST_TO_AWVALID_WAITS {1024} \
+                          CONFIG.MAX_WRITE_TO_BVALID_WAITS {1024} \
+                          CONFIG.MAX_CONTINUOUS_RTRANSFERS_WAITS {1024} \
+                    ] [get_ips $ipName]
+
+
+generate_target {instantiation_template} [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci]
+generate_target all [get_files  ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci]
+create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci]
+launch_run -jobs 8 ${ipName}_synth_1
+wait_on_run ${ipName}_synth_1
\ No newline at end of file
diff --git a/include/ariane_axi_pkg.sv b/include/ariane_axi_pkg.sv
index d06c90b5eadcd7f17046759f173cac15f2f9e6c4..c06b2c47fb767edec2f7ed248433794290deb7a3 100644
--- a/include/ariane_axi_pkg.sv
+++ b/include/ariane_axi_pkg.sv
@@ -22,12 +22,15 @@ package ariane_axi;
 
     // 4 is recommended by AXI standard, so lets stick to it, do not change
     localparam IdWidth   = 4;
+    localparam IdWidthSlave = IdWidth + $clog2(ariane_soc::NrSlaves);
+
     localparam UserWidth = 1;
     localparam AddrWidth = 64;
     localparam DataWidth = 64;
     localparam StrbWidth = DataWidth / 8;
 
     typedef logic [IdWidth-1:0]   id_t;
+    typedef logic [IdWidth-1:0]   id_slv_t;
     typedef logic [AddrWidth-1:0] addr_t;
     typedef logic [DataWidth-1:0] data_t;
     typedef logic [StrbWidth-1:0] strb_t;
@@ -48,7 +51,22 @@ package ariane_axi;
         axi_pkg::atop_t   atop;
     } aw_chan_t;
 
-    // W Channel
+    // AW Channel - Slave
+    typedef struct packed {
+        id_slv_t          id;
+        addr_t            addr;
+        axi_pkg::len_t    len;
+        axi_pkg::size_t   size;
+        axi_pkg::burst_t  burst;
+        logic             lock;
+        axi_pkg::cache_t  cache;
+        axi_pkg::prot_t   prot;
+        axi_pkg::qos_t    qos;
+        axi_pkg::region_t region;
+        axi_pkg::atop_t   atop;
+    } aw_chan_slv_t;
+
+    // W Channel - AXI4 doesn't define a wid
     typedef struct packed {
         data_t data;
         strb_t strb;
@@ -61,9 +79,15 @@ package ariane_axi;
         axi_pkg::resp_t resp;
     } b_chan_t;
 
+    // B Channel - Slave
+    typedef struct packed {
+        id_slv_t        id;
+        axi_pkg::resp_t resp;
+    } b_chan_slv_t;
+
     // AR Channel
     typedef struct packed {
-        id_t              id;
+        id_t             id;
         addr_t            addr;
         axi_pkg::len_t    len;
         axi_pkg::size_t   size;
@@ -75,6 +99,20 @@ package ariane_axi;
         axi_pkg::region_t region;
     } ar_chan_t;
 
+    // AR Channel - Slave
+    typedef struct packed {
+        id_slv_t          id;
+        addr_t            addr;
+        axi_pkg::len_t    len;
+        axi_pkg::size_t   size;
+        axi_pkg::burst_t  burst;
+        logic             lock;
+        axi_pkg::cache_t  cache;
+        axi_pkg::prot_t   prot;
+        axi_pkg::qos_t    qos;
+        axi_pkg::region_t region;
+    } ar_chan_slv_t;
+
     // R Channel
     typedef struct packed {
         id_t            id;
@@ -83,6 +121,15 @@ package ariane_axi;
         logic           last;
     } r_chan_t;
 
+    // R Channel - Slave
+    typedef struct packed {
+        id_slv_t        id;
+        data_t          data;
+        axi_pkg::resp_t resp;
+        logic           last;
+    } r_chan_slv_t;
+
+    // Request/Response structs
     typedef struct packed {
         aw_chan_t aw;
         logic     aw_valid;
@@ -104,4 +151,25 @@ package ariane_axi;
         r_chan_t  r;
     } resp_t;
 
+    typedef struct packed {
+        aw_chan_slv_t aw;
+        logic         aw_valid;
+        w_chan_t      w;
+        logic         w_valid;
+        logic         b_ready;
+        ar_chan_slv_t ar;
+        logic         ar_valid;
+        logic         r_ready;
+    } req_slv_t;
+
+    typedef struct packed {
+        logic         aw_ready;
+        logic         ar_ready;
+        logic         w_ready;
+        logic         b_valid;
+        b_chan_slv_t  b;
+        logic         r_valid;
+        r_chan_slv_t  r;
+    } resp_slv_t;
+
 endpackage
diff --git a/include/ariane_pkg.sv b/include/ariane_pkg.sv
index 556d651a215440578fc2554f648f39aaecff236b..f874b393f965a6f2cc328851c29357be396eae2f 100644
--- a/include/ariane_pkg.sv
+++ b/include/ariane_pkg.sv
@@ -63,19 +63,19 @@ package ariane_pkg;
 
 
 `ifdef PITON_ARIANE
-`ifdef AXI64_CACHE_PORTS
+    `ifdef AXI64_CACHE_PORTS
     // Floating-point extensions configuration
-    localparam bit RVF = 1'b1; // Is F extension enabled
-    localparam bit RVD = 1'b1; // Is D extension enabled
-`else 
+    localparam bit RVF = 1'b0; // Is F extension enabled
+    localparam bit RVD = 1'b0; // Is D extension enabled
+    `else
     // Floating-point extensions configuration
     localparam bit RVF = 1'b0; // Is F extension enabled
     localparam bit RVD = 1'b0; // Is D extension enabled
-`endif
-`else 
+    `endif
+`else
     // Floating-point extensions configuration
-    localparam bit RVF = 1'b1; // Is F extension enabled
-    localparam bit RVD = 1'b1; // Is D extension enabled
+    localparam bit RVF = 1'b0; // Is F extension enabled
+    localparam bit RVD = 1'b0; // Is D extension enabled
 `endif
     localparam bit RVA = 1'b1; // Is A extension enabled
 
@@ -152,14 +152,19 @@ package ariane_pkg;
     // where coherence is not necessary this can improve performance. This needs to be switched on
     // when more than one core is in a system
     localparam logic INVALIDATE_ON_FLUSH = 1'b1;
+`ifdef SPIKE_TANDEM
     // enable performance cycle counter, if set to zero mcycle will be incremented
     // with instret (non RISC-V conformal)
-    localparam bit ENABLE_CYCLE_COUNT = 1'b1;
+    localparam bit ENABLE_CYCLE_COUNT = 1'b0;
     // mark WIF as nop
-    localparam bit ENABLE_WFI = 1'b1;
+    localparam bit ENABLE_WFI = 1'b0;
     // Spike zeros tval on all exception except memory faults
+    localparam bit ZERO_TVAL = 1'b1;
+`else
+    localparam bit ENABLE_CYCLE_COUNT = 1'b1;
+    localparam bit ENABLE_WFI = 1'b1;
     localparam bit ZERO_TVAL = 1'b0;
-
+`endif
     // read mask for SSTATUS over MMSTATUS
     localparam logic [63:0] SMODE_STATUS_READ_MASK = riscv::SSTATUS_UIE
                                                    | riscv::SSTATUS_SIE
diff --git a/src/ariane.sv b/src/ariane.sv
index d47624ab6fbccaaa6dd15080d6bdd4d45caed489..d14cec9f60a0e2dfa9167480877826991a2023ed 100644
--- a/src/ariane.sv
+++ b/src/ariane.sv
@@ -48,7 +48,6 @@ module ariane #(
   // Timer facilities
   input  logic                         time_irq_i,   // timer interrupt in (async)
   input  logic                         debug_req_i,  // debug request (async)
-
 `ifdef AXI64_CACHE_PORTS
   // memory side, AXI Master
   output ariane_axi::req_t             axi_req_o,
@@ -588,9 +587,9 @@ module ariane #(
 `ifdef PITON_ARIANE
   // this is a cache subsystem that is compatible with OpenPiton
   serpent_cache_subsystem #(
-`ifdef AXI64_CACHE_PORTS    
+`ifdef AXI64_CACHE_PORTS
     .AxiIdWidth           ( AxiIdWidth    ),
-`endif    
+`endif
     .CachedAddrBeg        ( CachedAddrBeg ),
     .CachedAddrEnd        ( CachedAddrEnd ),
     .SwapEndianess        ( SwapEndianess )
diff --git a/src/axi_riscv_atomics b/src/axi_riscv_atomics
index aacd82ffddb7cd8c5ae735542f29c36cbeb95129..550881f12e22dfae405612fc1df6368f4c003e68 160000
--- a/src/axi_riscv_atomics
+++ b/src/axi_riscv_atomics
@@ -1 +1 @@
-Subproject commit aacd82ffddb7cd8c5ae735542f29c36cbeb95129
+Subproject commit 550881f12e22dfae405612fc1df6368f4c003e68
diff --git a/src/cache_subsystem/miss_handler.sv b/src/cache_subsystem/miss_handler.sv
index c875ce4a792eb8f156f12945a134c94aafa1fc6a..095f78aa5a580b3dcf11cf7a9d17494924164d02 100644
--- a/src/cache_subsystem/miss_handler.sv
+++ b/src/cache_subsystem/miss_handler.sv
@@ -187,6 +187,7 @@ module miss_handler #(
                     if (!serve_amo_q) begin
                         state_d = FLUSH_REQ_STATUS;
                         serve_amo_d = 1'b1;
+                        cnt_d = '0;
                     // 2. Do the AMO
                     end else begin
                         state_d = AMO_LOAD;
diff --git a/src/cache_subsystem/serpent_axi_adapter.sv b/src/cache_subsystem/serpent_axi_adapter.sv
index a05d73ef05a874802a5b72e5bb87e14779482b80..f9d7735204a9df3a7fb0bb89b33cde0c86ea7ca2 100644
--- a/src/cache_subsystem/serpent_axi_adapter.sv
+++ b/src/cache_subsystem/serpent_axi_adapter.sv
@@ -49,7 +49,7 @@ module serpent_axi_adapter #(
 localparam AxiNumWords = ariane_pkg::ICACHE_LINE_WIDTH/64;
 
 ///////////////////////////////////////////////////////
-// request path 
+// request path
 ///////////////////////////////////////////////////////
 
 icache_req_t icache_data;
@@ -74,6 +74,8 @@ logic [AxiNumWords-1:0][7:0]  axi_wr_be;
 logic [5:0] axi_wr_atop;
 logic invalidate;
 logic [2:0] amo_off_d, amo_off_q;
+// AMO generates r beat
+logic amo_gen_r_d, amo_gen_r_q;
 
 logic [serpent_cache_pkg::CACHE_ID_WIDTH-1:0] icache_rtrn_tid_d, icache_rtrn_tid_q;
 logic [serpent_cache_pkg::CACHE_ID_WIDTH-1:0] dcache_rtrn_tid_d, dcache_rtrn_tid_q;
@@ -87,10 +89,10 @@ assign icache_data_ack_o  = icache_data_req_i & ~icache_data_full;
 assign dcache_data_ack_o  = dcache_data_req_i & ~dcache_data_full;
 
 // arbiter
-assign arb_req           = {~(dcache_data_empty | 
-                              dcache_wr_full    | 
-                              dcache_rd_full), 
-                            ~(icache_data_empty | 
+assign arb_req           = {~(dcache_data_empty |
+                              dcache_wr_full    |
+                              dcache_rd_full),
+                            ~(icache_data_empty |
                               icache_rd_full)};
 
 assign arb_gnt           = axi_rd_gnt | axi_wr_gnt;
@@ -99,14 +101,14 @@ rrarbiter #(
   .NUM_REQ(2),
   .LOCK_IN(1)
 ) i_rrarbiter (
-  .clk_i  ( clk_i                   ),
-  .rst_ni ( rst_ni                  ),
-  .flush_i( '0                      ),
-  .en_i   ( arb_gnt                 ),
-  .req_i  ( arb_req                 ),
-  .ack_o  ( arb_ack                 ),
-  .vld_o  (                         ),
-  .idx_o  ( arb_idx                 )
+  .clk_i  ( clk_i   ),
+  .rst_ni ( rst_ni  ),
+  .flush_i( '0      ),
+  .en_i   ( arb_gnt ),
+  .req_i  ( arb_req ),
+  .ack_o  ( arb_ack ),
+  .vld_o  (         ),
+  .idx_o  ( arb_idx )
 );
 
 // request side
@@ -122,6 +124,7 @@ always_comb begin : p_axi_req
   axi_wr_lock  = '0;
   axi_wr_atop  = '0;
   amo_off_d    = '0;
+  amo_gen_r_d  = amo_gen_r_q;
 
   // read channel
   axi_rd_id_in = arb_idx;
@@ -135,14 +138,14 @@ always_comb begin : p_axi_req
     axi_rd_size  = dcache_data.size[1:0];
     if (dcache_data.size[2]) begin
       axi_rd_blen = ariane_pkg::DCACHE_LINE_WIDTH/64-1;
-    end  
+    end
   end else begin
     axi_rd_addr  = icache_data.paddr;
     axi_rd_size  = 2'b11;// always request 64bit words in case of ifill
     if (~icache_data.nc) begin
       axi_rd_blen = ariane_pkg::ICACHE_LINE_WIDTH/64-1;
-    end  
-  end 
+    end
+  end
 
   // signal that an invalidation message
   // needs to be generated
@@ -152,10 +155,10 @@ always_comb begin : p_axi_req
   if (|arb_req) begin
     if (arb_idx == 0) begin
       //////////////////////////////////////
-      // IMISS  
+      // IMISS
       axi_rd_req   = 1'b1;
       //////////////////////////////////////
-    end else begin  
+    end else begin
       unique case (dcache_data.rtype)
         //////////////////////////////////////
         serpent_cache_pkg::DCACHE_LOAD_REQ: begin
@@ -168,18 +171,18 @@ always_comb begin : p_axi_req
         end
         //////////////////////////////////////
         serpent_cache_pkg::DCACHE_ATOMIC_REQ: begin
-          // default  
+          // default
           // push back an invalidation here.
           // since we only keep one read tx in flight, and since
-          // the dcache drains all writes/reads before executing 
+          // the dcache drains all writes/reads before executing
           // an atomic, this is safe.
           invalidate   = arb_gnt;
           axi_wr_req   = 1'b1;
           axi_wr_be    = serpent_cache_pkg::toByteEnable8(dcache_data.paddr[2:0], dcache_data.size[1:0]);
-          
-          // need to use a separate ID here, so concat an additional bit 
+          amo_gen_r_d  = 1'b1;
+          // need to use a separate ID here, so concat an additional bit
           axi_wr_id_in[1] = 1'b1;
-          
+
           unique case (dcache_data.amo_op)
             AMO_LR: begin
               axi_rd_lock     = 1'b1;
@@ -191,35 +194,36 @@ always_comb begin : p_axi_req
             end
             AMO_SC: begin
               axi_wr_lock  = 1'b1;
+              amo_gen_r_d  = 1'b0;
               // needed to properly encode success
               unique case (dcache_data.size[1:0])
                 2'b00: amo_off_d    = dcache_data.paddr[2:0];
                 2'b01: amo_off_d    = {dcache_data.paddr[2:1], 1'b0};
                 2'b10: amo_off_d    = {dcache_data.paddr[2],   2'b00};
                 2'b11: amo_off_d    = '0;
-              endcase    
-            end  
+              endcase
+            end
             // RISC-V atops have a load semantic
             AMO_SWAP: axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ATOMICSWAP};
             AMO_ADD:  axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_ADD};
-            AMO_AND:  begin 
-              // in this case we need to invert the data to get a "CLR" 
+            AMO_AND:  begin
+              // in this case we need to invert the data to get a "CLR"
               axi_wr_data  = ~dcache_data.data;
               axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_CLR};
-            end  
+            end
             AMO_OR:   axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SET};
             AMO_XOR:  axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_EOR};
             AMO_MAX:  axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMAX};
             AMO_MAXU: axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMAX};
-            AMO_MIN:  axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMIN}; 
-            AMO_MINU: axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMIN}; 
-          endcase  
+            AMO_MIN:  axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_SMIN};
+            AMO_MINU: axi_wr_atop  = {axi_pkg::ATOP_ATOMICLOAD, axi_pkg::ATOP_LITTLE_END, axi_pkg::ATOP_UMIN};
+          endcase
         end
       //////////////////////////////////////
       endcase
-    end 
-  end  
-end  
+    end
+  end
+end
 
 fifo_v2 #(
      .dtype       (  icache_req_t            ),
@@ -264,10 +268,9 @@ fifo_v2 #(
 logic icache_rtrn_rd_en, dcache_rtrn_rd_en;
 logic icache_rtrn_vld_d, icache_rtrn_vld_q, dcache_rtrn_vld_d, dcache_rtrn_vld_q;
 
-
 fifo_v3 #(
-  .DATA_WIDTH(serpent_cache_pkg::CACHE_ID_WIDTH), 
-  .DEPTH ( MetaFifoDepth )
+  .DATA_WIDTH ( serpent_cache_pkg::CACHE_ID_WIDTH ),
+  .DEPTH      ( MetaFifoDepth                     )
 ) i_rd_icache_id (
   .clk_i      ( clk_i                   ),
   .rst_ni     ( rst_ni                  ),
@@ -276,15 +279,15 @@ fifo_v3 #(
   .full_o     ( icache_rd_full          ),
   .empty_o    ( icache_rd_empty         ),
   .usage_o    (                         ),
-  .data_i     ( icache_data.tid         ), 
+  .data_i     ( icache_data.tid         ),
   .push_i     ( arb_ack[0] & axi_rd_gnt ),
-  .data_o     ( icache_rtrn_tid_d       ), 
+  .data_o     ( icache_rtrn_tid_d       ),
   .pop_i      ( icache_rtrn_vld_d       )
 );
 
 fifo_v3 #(
-  .DATA_WIDTH(serpent_cache_pkg::CACHE_ID_WIDTH), 
-  .DEPTH ( MetaFifoDepth )
+  .DATA_WIDTH ( serpent_cache_pkg::CACHE_ID_WIDTH ),
+  .DEPTH      ( MetaFifoDepth                     )
 ) i_rd_dcache_id (
   .clk_i      ( clk_i                   ),
   .rst_ni     ( rst_ni                  ),
@@ -293,15 +296,15 @@ fifo_v3 #(
   .full_o     ( dcache_rd_full          ),
   .empty_o    ( dcache_rd_empty         ),
   .usage_o    (                         ),
-  .data_i     ( dcache_data.tid         ), 
+  .data_i     ( dcache_data.tid         ),
   .push_i     ( arb_ack[1] & axi_rd_gnt ),
-  .data_o     ( dcache_rtrn_rd_tid      ), 
+  .data_o     ( dcache_rtrn_rd_tid      ),
   .pop_i      ( dcache_rd_pop           )
 );
 
 fifo_v3 #(
-  .DATA_WIDTH(serpent_cache_pkg::CACHE_ID_WIDTH), 
-  .DEPTH ( MetaFifoDepth )
+  .DATA_WIDTH ( serpent_cache_pkg::CACHE_ID_WIDTH ),
+  .DEPTH      ( MetaFifoDepth                     )
 ) i_wr_dcache_id (
   .clk_i      ( clk_i                   ),
   .rst_ni     ( rst_ni                  ),
@@ -310,9 +313,9 @@ fifo_v3 #(
   .full_o     ( dcache_wr_full          ),
   .empty_o    ( dcache_wr_empty         ),
   .usage_o    (                         ),
-  .data_i     ( dcache_data.tid         ), 
+  .data_i     ( dcache_data.tid         ),
   .push_i     ( arb_ack[1] & axi_wr_gnt ),
-  .data_o     ( dcache_rtrn_wr_tid      ), 
+  .data_o     ( dcache_rtrn_wr_tid      ),
   .pop_i      ( dcache_wr_pop           )
 );
 
@@ -320,7 +323,7 @@ fifo_v3 #(
 assign dcache_rtrn_tid_d = (dcache_wr_pop) ? dcache_rtrn_wr_tid : dcache_rtrn_rd_tid;
 
 ///////////////////////////////////////////////////////
-// return path 
+// return path
 ///////////////////////////////////////////////////////
 
 // buffer write responses
@@ -329,9 +332,9 @@ assign axi_wr_rdy          = ~b_full;
 assign b_push              = axi_wr_valid & axi_wr_rdy;
 
 fifo_v3 #(
-  .DATA_WIDTH(AxiIdWidth+1), 
-  .DEPTH        ( MetaFifoDepth ),
-  .FALL_THROUGH ( 1'b1       )
+  .DATA_WIDTH   ( AxiIdWidth + 1 ),
+  .DEPTH        ( MetaFifoDepth  ),
+  .FALL_THROUGH ( 1'b1           )
 ) i_b_fifo (
   .clk_i      ( clk_i      ),
   .rst_ni     ( rst_ni     ),
@@ -340,10 +343,10 @@ fifo_v3 #(
   .full_o     ( b_full     ),
   .empty_o    ( b_empty    ),
   .usage_o    (            ),
-  .data_i     ( {axi_wr_exokay, axi_wr_id_out} ), 
-  .push_i     ( b_push     ),
-  .data_o     ( {wr_exokay, wr_id_out}         ), 
-  .pop_i      ( b_pop      )
+  .data_i     ( {axi_wr_exokay, axi_wr_id_out} ),
+  .push_i     ( b_push                         ),
+  .data_o     ( {wr_exokay, wr_id_out}         ),
+  .pop_i      ( b_pop                          )
 );
 
 // buffer read responses in shift regs
@@ -356,12 +359,12 @@ logic dcache_sc_rtrn, axi_rd_last;
 
 always_comb begin : p_axi_rtrn_shift
   // output directly from regs
-  icache_rtrn_o              = '0;  
+  icache_rtrn_o              = '0;
   icache_rtrn_o.rtype        = serpent_cache_pkg::ICACHE_IFILL_ACK;
   icache_rtrn_o.tid          = icache_rtrn_tid_q;
   icache_rtrn_o.data         = icache_rd_shift_q;
   icache_rtrn_vld_o          = icache_rtrn_vld_q;
-  
+
   dcache_rtrn_o              = '0;
   dcache_rtrn_o.rtype        = dcache_rtrn_type_q;
   dcache_rtrn_o.inv          = dcache_rtrn_inv_q;
@@ -396,7 +399,7 @@ always_comb begin : p_axi_rtrn_shift
     dcache_rd_shift_d[0] = '0;
     dcache_rd_shift_d[0][amo_off_q*8] = (wr_exokay) ? '0 : 1'b1;
   end
-end  
+end
 
 // decode virtual read channels of icache
 always_comb begin : p_axi_rtrn_decode
@@ -407,7 +410,7 @@ always_comb begin : p_axi_rtrn_decode
   icache_rtrn_rd_en = 1'b0;
   icache_rtrn_vld_d = 1'b0;
 
-  // decode virtual icache channel, 
+  // decode virtual icache channel,
   // this is independent on dcache decoding below
   if (axi_rd_valid && axi_rd_id_out == 0 && axi_rd_rdy) begin
     icache_rtrn_rd_en = 1'b1;
@@ -422,55 +425,55 @@ always_comb begin : p_axi_rtrn_decode
   dcache_rtrn_type_d  = serpent_cache_pkg::DCACHE_LOAD_ACK;
   b_pop               = 1'b0;
   dcache_sc_rtrn      = 1'b0;
-    
+
   //////////////////////////////////////
-  // dcache needs some special treatment 
+  // dcache needs some special treatment
   // for arbitration and decoding of atomics
   //////////////////////////////////////
   // this is safe, there is no other read tx in flight than this atomic.
-  // note that this self invalidation is handled in this way due to the 
-  // write-through cache architecture, which is aligned with the openpiton 
+  // note that this self invalidation is handled in this way due to the
+  // write-through cache architecture, which is aligned with the openpiton
   // cache subsystem.
   if (invalidate) begin
       dcache_rtrn_type_d     = serpent_cache_pkg::DCACHE_INV_REQ;
       dcache_rtrn_vld_d      = 1'b1;
 
       dcache_rtrn_inv_d.all  = 1'b1;
-      dcache_rtrn_inv_d.idx  = dcache_data.paddr[ariane_pkg::DCACHE_INDEX_WIDTH]; 
+      dcache_rtrn_inv_d.idx  = dcache_data.paddr[ariane_pkg::DCACHE_INDEX_WIDTH-1:0];
   //////////////////////////////////////
   // read responses
-  // note that in case of atomics, the dcache sequentializes requests and 
+  // note that in case of atomics, the dcache sequentializes requests and
   // guarantees that there are no other pending transactions in flight
   end else if (axi_rd_valid && axi_rd_id_out[0] && axi_rd_rdy) begin
     dcache_rtrn_rd_en        = 1'b1;
     dcache_rtrn_vld_d        = axi_rd_last;
-    
+
     // if this was an atomic op
     if (axi_rd_id_out[1]) begin
       dcache_rtrn_type_d     = serpent_cache_pkg::DCACHE_ATOMIC_ACK;
-      
+
       // check if transaction was issued over write channel and pop that ID
       if (~dcache_wr_empty) begin
         dcache_wr_pop          = axi_rd_last;
-      // if this is not the case, there MUST be an id in the read channel (LR) 
+      // if this is not the case, there MUST be an id in the read channel (LR)
       end else begin
         dcache_rd_pop          = axi_rd_last;
-      end  
+      end
     end else begin
       dcache_rd_pop          = axi_rd_last;
-    end 
-  //////////////////////////////////////  
+    end
+  //////////////////////////////////////
   // write responses, check b fifo
   end else if (~b_empty) begin
-    b_pop               = 1'b1; 
+    b_pop               = 1'b1;
 
-    // this was an atomic 
+    // this was an atomic
     if (wr_id_out[1]) begin
       dcache_rtrn_type_d = serpent_cache_pkg::DCACHE_ATOMIC_ACK;
 
-      // silently discard b response if there is no corresponding entry in the
-      // write meta data queue (this is the case for all atomic loads and LRs)
-      if (~dcache_wr_empty) begin
+      // silently discard b response if we already popped the fifo
+      // with a R beat (iff the amo transaction generated an R beat)
+      if (~amo_gen_r_q) begin
         dcache_rtrn_vld_d  = 1'b1;
         dcache_wr_pop      = 1'b1;
         dcache_sc_rtrn     = 1'b1;
@@ -480,7 +483,7 @@ always_comb begin : p_axi_rtrn_decode
       dcache_rtrn_type_d = serpent_cache_pkg::DCACHE_STORE_ACK;
       dcache_rtrn_vld_d  = 1'b1;
       dcache_wr_pop      = 1'b1;
-    end  
+    end
   end
   //////////////////////////////////////
 end
@@ -498,7 +501,7 @@ end
 // assign dcache_rtrn_o.inv.all  = '0;
 
 always_ff @(posedge clk_i) begin : p_rd_buf
-  if(~rst_ni) begin
+  if (~rst_ni) begin
     icache_first_q     <= 1'b1;
     dcache_first_q     <= 1'b1;
     icache_rd_shift_q  <= '0;
@@ -508,8 +511,9 @@ always_ff @(posedge clk_i) begin : p_rd_buf
     icache_rtrn_tid_q  <= '0;
     dcache_rtrn_tid_q  <= '0;
     dcache_rtrn_type_q <= serpent_cache_pkg::DCACHE_LOAD_ACK;
-    dcache_rtrn_inv_q  <= '0; 
+    dcache_rtrn_inv_q  <= '0;
     amo_off_q          <= '0;
+    amo_gen_r_q        <= 1'b0;
   end else begin
     icache_first_q     <= icache_first_d;
     dcache_first_q     <= dcache_first_d;
@@ -522,6 +526,7 @@ always_ff @(posedge clk_i) begin : p_rd_buf
     dcache_rtrn_type_q <= dcache_rtrn_type_d;
     dcache_rtrn_inv_q  <= dcache_rtrn_inv_d;
     amo_off_q          <= amo_off_d;
+    amo_gen_r_q        <= amo_gen_r_d;
   end
 end
 
@@ -548,7 +553,7 @@ axi_shim #(
   .rd_valid_o      ( axi_rd_valid      ),
   .rd_data_o       ( axi_rd_data       ),
   .rd_id_o         ( axi_rd_id_out     ),
-  .rd_exokay_o     ( axi_rd_exokay     ),    
+  .rd_exokay_o     ( axi_rd_exokay     ),
   .wr_req_i        ( axi_wr_req        ),
   .wr_gnt_o        ( axi_wr_gnt        ),
   .wr_addr_i       ( axi_wr_addr       ),
diff --git a/src/cache_subsystem/serpent_dcache_ctrl.sv b/src/cache_subsystem/serpent_dcache_ctrl.sv
index fd4e80b7175971ccb8d0385a336ecc54d98460e2..c86d89cfb91d9c16860fe83249d543a671580936 100644
--- a/src/cache_subsystem/serpent_dcache_ctrl.sv
+++ b/src/cache_subsystem/serpent_dcache_ctrl.sv
@@ -85,8 +85,8 @@ module serpent_dcache_ctrl #(
     assign miss_paddr_o          = {address_tag_q, address_idx_q, address_off_q};
     assign miss_size_o           = (miss_nc_o) ? data_size_q : 3'b111;
 
-    assign miss_nc_o = (address_tag_q <  (CachedAddrBeg>>DCACHE_INDEX_WIDTH)) || 
-                       (address_tag_q >= (CachedAddrEnd>>DCACHE_INDEX_WIDTH)) || 
+    assign miss_nc_o = (address_tag_q <  (CachedAddrBeg>>DCACHE_INDEX_WIDTH)) ||
+                       (address_tag_q >= (CachedAddrEnd>>DCACHE_INDEX_WIDTH)) ||
                        (!cache_en_i);
 
     assign miss_we_o    = '0;
@@ -207,7 +207,7 @@ module serpent_dcache_ctrl #(
                 miss_req_o = 1'b1;
                 if(miss_ack_i) begin
                   state_d = KILL_MISS;
-                end  
+                end
             end
             //////////////////////////////////
             // killed miss,
diff --git a/src/cache_subsystem/std_icache.sv b/src/cache_subsystem/std_icache.sv
index 5cc6ad1f1189dd0fa2472cec57ac785a03d39fbd..458069c6fa18d3274cf9bedac9d9f607927e0de5 100644
--- a/src/cache_subsystem/std_icache.sv
+++ b/src/cache_subsystem/std_icache.sv
@@ -158,7 +158,7 @@ module std_icache (
     assign axi_req_o.b_ready   = 1'b0;
 
     // set protection flag, MSB -> instruction fetch, LSB -> privileged access or not
-    assign axi_req_o.ar.prot   = {1'b1, 1'b0, (priv_lvl_i == riscv::PRIV_LVL_M)};
+    assign axi_req_o.ar.prot   = '0;
     assign axi_req_o.ar.region = '0;
     assign axi_req_o.ar.len    = (2**NR_AXI_REFILLS) - 1;
     assign axi_req_o.ar.size   = 3'b011;
diff --git a/src/util/sram.sv b/src/util/sram.sv
index 3ed089885ae091565066cd90497d6c1074002f17..1f321d80261814a97f6f0d1746ccb562ff77daee 100644
--- a/src/util/sram.sv
+++ b/src/util/sram.sv
@@ -58,7 +58,12 @@ generate
           .ADDR_WIDTH($clog2(NUM_WORDS)),
           .DATA_DEPTH(NUM_WORDS),
           .OUT_REGS (0),
+// initialize to zero if we want to co-simulate with Spike
+`ifdef SPIKE_TANDEM
+          .SIM_INIT (1)
+`else
           .SIM_INIT (2)
+`endif
         ) i_ram (
            .Clk_CI    ( clk_i                     ),
            .Rst_RBI   ( rst_ni                    ),
diff --git a/tb/ariane_peripherals.sv b/tb/ariane_peripherals.sv
index 359922eb5c02d9cc05df944e1688f5ca0a9072e8..ce488c0beb6222c92ab55a25e4c13838fe9473e3 100644
--- a/tb/ariane_peripherals.sv
+++ b/tb/ariane_peripherals.sv
@@ -251,7 +251,7 @@ module ariane_peripherals #(
             .PRDATA  ( uart_prdata     ),
             .PREADY  ( uart_pready     ),
             .PSLVERR ( uart_pslverr    ),
-            .INT     ( irq_sources[2]  ),
+            .INT     ( irq_sources[0]  ),
             .OUT1N   (                 ), // keep open
             .OUT2N   (                 ), // keep open
             .RTSN    (                 ), // no flow control
@@ -264,6 +264,7 @@ module ariane_peripherals #(
             .SOUT    ( tx_o            )
         );
     end else begin
+        assign irq_sources[0] = 1'b0;
         /* pragma translate_off */
         `ifndef VERILATOR
         mock_uart i_mock_uart (
diff --git a/tb/ariane_soc_pkg.sv b/tb/ariane_soc_pkg.sv
index 2077331bb457f7e08a4f16bb087c4765ccd13fe8..aa6764657ab3c384a22a4c2d05a5d002e740f429 100644
--- a/tb/ariane_soc_pkg.sv
+++ b/tb/ariane_soc_pkg.sv
@@ -17,8 +17,9 @@ package ariane_soc;
     localparam NumSources = 3;
     localparam PLICIdWidth = 3;
     localparam ParameterBitwidth = PLICIdWidth;
+    localparam NrSlaves = 2; // actually masters, but slaves on the crossbar
 
-  typedef enum int unsigned {
+    typedef enum int unsigned {
         DRAM     = 0,
         GPIO     = 1,
         Ethernet = 2,
diff --git a/tb/ariane_tb.sv b/tb/ariane_tb.sv
index 8a74d92c1c722bb20d671b2e0fce4d371d956c20..c1be3680232648acf4dc593bc709eb98f832d817 100644
--- a/tb/ariane_tb.sv
+++ b/tb/ariane_tb.sv
@@ -57,6 +57,25 @@ module ariane_tb;
         .exit_o
     );
 
+`ifdef SPIKE_TANDEM
+    spike #(
+        .Size ( NUM_WORDS * 8 )
+    ) i_spike (
+        .clk_i,
+        .rst_ni,
+        .clint_tick_i   ( rtc_i                               ),
+        .commit_instr_i ( dut.i_ariane.commit_instr_id_commit ),
+        .commit_ack_i   ( dut.i_ariane.commit_ack             ),
+        .exception_i    ( dut.i_ariane.ex_commit              ),
+        .waddr_i        ( dut.i_ariane.waddr_commit_id        ),
+        .wdata_i        ( dut.i_ariane.wdata_commit_id        ),
+        .priv_lvl_i     ( dut.i_ariane.priv_lvl               )
+    );
+    initial begin
+        $display("Running binary in tandem mode");
+    end
+`endif
+
     // Clock process
     initial begin
         clk_i = 1'b0;
diff --git a/tb/ariane_testharness.sv b/tb/ariane_testharness.sv
index 21b9f6403594aa762f6df3d89ad9ceb08161e48c..386922f2ed09168a155a69c3bf4771e49db25bca 100644
--- a/tb/ariane_testharness.sv
+++ b/tb/ariane_testharness.sv
@@ -14,7 +14,6 @@
 //              Instantiates an AXI-Bus and memories
 
 module ariane_testharness #(
-    parameter int unsigned AXI_ID_WIDTH      = 4,
     parameter int unsigned AXI_USER_WIDTH    = 1,
     parameter int unsigned AXI_ADDRESS_WIDTH = 64,
     parameter int unsigned AXI_DATA_WIDTH    = 64,
@@ -70,22 +69,18 @@ module ariane_testharness #(
 
     assign test_en = 1'b0;
 
-    localparam NB_SLAVE = 2;
-
-    localparam AXI_ID_WIDTH_SLAVES = AXI_ID_WIDTH + $clog2(NB_SLAVE);
-
-    AXI_BUS #(
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH    ),
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH      ),
-        .AXI_USER_WIDTH ( AXI_USER_WIDTH    )
-    ) slave[NB_SLAVE-1:0]();
-
     AXI_BUS #(
         .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH   ),
         .AXI_DATA_WIDTH ( AXI_DATA_WIDTH      ),
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES ),
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidth ),
         .AXI_USER_WIDTH ( AXI_USER_WIDTH      )
+    ) slave[ariane_soc::NrSlaves-1:0]();
+
+    AXI_BUS #(
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           )
     ) master[ariane_soc::NB_PERIPHERALS-1:0]();
 
     rstgen i_rstgen_main (
@@ -231,10 +226,10 @@ module ariane_testharness #(
     );
 
     axi2mem #(
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES   ),
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH     ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH        ),
-        .AXI_USER_WIDTH ( AXI_USER_WIDTH        )
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           )
     ) i_dm_axi2mem (
         .clk_i      ( clk_i                     ),
         .rst_ni     ( rst_ni                    ),
@@ -286,10 +281,10 @@ module ariane_testharness #(
     logic [AXI_DATA_WIDTH-1:0]    rom_rdata;
 
     axi2mem #(
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES ),
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH   ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH      ),
-        .AXI_USER_WIDTH ( AXI_USER_WIDTH      )
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           )
     ) i_axi2rom (
         .clk_i  ( clk_i                   ),
         .rst_ni ( ndmreset_n              ),
@@ -313,10 +308,10 @@ module ariane_testharness #(
     // Memory + Exclusive Access
     // ------------------------------
     AXI_BUS #(
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH   ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH      ),
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES ),
-        .AXI_USER_WIDTH ( AXI_USER_WIDTH      )
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           )
     ) dram();
 
     logic                         req;
@@ -327,10 +322,10 @@ module ariane_testharness #(
     logic [AXI_DATA_WIDTH-1:0]    rdata;
 
     axi_riscv_atomics_wrap #(
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH   ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH      ),
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES ),
-        .AXI_USER_WIDTH ( AXI_USER_WIDTH      ),
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           ),
         .AXI_MAX_WRITE_TXNS ( 1  ),
         .RISCV_WORD_WIDTH   ( 64 )
     ) i_axi_riscv_atomics (
@@ -340,21 +335,159 @@ module ariane_testharness #(
         .mst    ( dram                     )
     );
 
+    AXI_BUS #(
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           )
+    ) dram_delayed();
+
+    ariane_axi::aw_chan_slv_t aw_chan_i;
+    ariane_axi::w_chan_t      w_chan_i;
+    ariane_axi::b_chan_slv_t  b_chan_o;
+    ariane_axi::ar_chan_slv_t ar_chan_i;
+    ariane_axi::r_chan_slv_t  r_chan_o;
+    ariane_axi::aw_chan_slv_t aw_chan_o;
+    ariane_axi::w_chan_t      w_chan_o;
+    ariane_axi::b_chan_slv_t  b_chan_i;
+    ariane_axi::ar_chan_slv_t ar_chan_o;
+    ariane_axi::r_chan_slv_t  r_chan_i;
+
+    axi_delayer #(
+        .aw_t              ( ariane_axi::aw_chan_slv_t ),
+        .w_t               ( ariane_axi::w_chan_t      ),
+        .b_t               ( ariane_axi::b_chan_slv_t  ),
+        .ar_t              ( ariane_axi::ar_chan_slv_t ),
+        .r_t               ( ariane_axi::r_chan_slv_t  ),
+        .StallRandomOutput ( StallRandomOutput         ),
+        .StallRandomInput  ( StallRandomInput          ),
+        .FixedDelayInput   ( 0                         ),
+        .FixedDelayOutput  ( 0                         )
+    ) i_axi_delayer (
+        .clk_i      ( clk_i                 ),
+        .rst_ni     ( ndmreset_n            ),
+        .aw_valid_i ( dram.aw_valid         ),
+        .aw_chan_i  ( aw_chan_i             ),
+        .aw_ready_o ( dram.aw_ready         ),
+        .w_valid_i  ( dram.w_valid          ),
+        .w_chan_i   ( w_chan_i              ),
+        .w_ready_o  ( dram.w_ready          ),
+        .b_valid_o  ( dram.b_valid          ),
+        .b_chan_o   ( b_chan_o              ),
+        .b_ready_i  ( dram.b_ready          ),
+        .ar_valid_i ( dram.ar_valid         ),
+        .ar_chan_i  ( ar_chan_i             ),
+        .ar_ready_o ( dram.ar_ready         ),
+        .r_valid_o  ( dram.r_valid          ),
+        .r_chan_o   ( r_chan_o              ),
+        .r_ready_i  ( dram.r_ready          ),
+        .aw_valid_o ( dram_delayed.aw_valid ),
+        .aw_chan_o  ( aw_chan_o             ),
+        .aw_ready_i ( dram_delayed.aw_ready ),
+        .w_valid_o  ( dram_delayed.w_valid  ),
+        .w_chan_o   ( w_chan_o              ),
+        .w_ready_i  ( dram_delayed.w_ready  ),
+        .b_valid_i  ( dram_delayed.b_valid  ),
+        .b_chan_i   ( b_chan_i              ),
+        .b_ready_o  ( dram_delayed.b_ready  ),
+        .ar_valid_o ( dram_delayed.ar_valid ),
+        .ar_chan_o  ( ar_chan_o             ),
+        .ar_ready_i ( dram_delayed.ar_ready ),
+        .r_valid_i  ( dram_delayed.r_valid  ),
+        .r_chan_i   ( r_chan_i              ),
+        .r_ready_o  ( dram_delayed.r_ready  )
+    );
+
+    assign aw_chan_i.atop = dram.aw_atop;
+    assign aw_chan_i.id = dram.aw_id;
+    assign aw_chan_i.addr = dram.aw_addr;
+    assign aw_chan_i.len = dram.aw_len;
+    assign aw_chan_i.size = dram.aw_size;
+    assign aw_chan_i.burst = dram.aw_burst;
+    assign aw_chan_i.lock = dram.aw_lock;
+    assign aw_chan_i.cache = dram.aw_cache;
+    assign aw_chan_i.prot = dram.aw_prot;
+    assign aw_chan_i.qos = dram.aw_qos;
+    assign aw_chan_i.region = dram.aw_region;
+
+    assign ar_chan_i.id = dram.ar_id;
+    assign ar_chan_i.addr = dram.ar_addr;
+    assign ar_chan_i.len = dram.ar_len;
+    assign ar_chan_i.size = dram.ar_size;
+    assign ar_chan_i.burst = dram.ar_burst;
+    assign ar_chan_i.lock = dram.ar_lock;
+    assign ar_chan_i.cache = dram.ar_cache;
+    assign ar_chan_i.prot = dram.ar_prot;
+    assign ar_chan_i.qos = dram.ar_qos;
+    assign ar_chan_i.region = dram.ar_region;
+
+    assign w_chan_i.data = dram.w_data;
+    assign w_chan_i.strb = dram.w_strb;
+    assign w_chan_i.last = dram.w_last;
+
+    assign dram.r_id = r_chan_o.id;
+    assign dram.r_data = r_chan_o.data;
+    assign dram.r_resp = r_chan_o.resp;
+    assign dram.r_last = r_chan_o.last;
+
+    assign dram.b_id = b_chan_o.id;
+    assign dram.b_resp = b_chan_o.resp;
+
+    assign dram_delayed.aw_id = aw_chan_o.id;
+    assign dram_delayed.aw_addr = aw_chan_o.addr;
+    assign dram_delayed.aw_len = aw_chan_o.len;
+    assign dram_delayed.aw_size = aw_chan_o.size;
+    assign dram_delayed.aw_burst = aw_chan_o.burst;
+    assign dram_delayed.aw_lock = aw_chan_o.lock;
+    assign dram_delayed.aw_cache = aw_chan_o.cache;
+    assign dram_delayed.aw_prot = aw_chan_o.prot;
+    assign dram_delayed.aw_qos = aw_chan_o.qos;
+    assign dram_delayed.aw_atop = aw_chan_o.atop;
+    assign dram_delayed.aw_region = aw_chan_o.region;
+    assign dram_delayed.aw_user = '0;
+
+    assign dram_delayed.ar_id = ar_chan_o.id;
+    assign dram_delayed.ar_addr = ar_chan_o.addr;
+    assign dram_delayed.ar_len = ar_chan_o.len;
+    assign dram_delayed.ar_size = ar_chan_o.size;
+    assign dram_delayed.ar_burst = ar_chan_o.burst;
+    assign dram_delayed.ar_lock = ar_chan_o.lock;
+    assign dram_delayed.ar_cache = ar_chan_o.cache;
+    assign dram_delayed.ar_prot = ar_chan_o.prot;
+    assign dram_delayed.ar_qos = ar_chan_o.qos;
+    assign dram_delayed.ar_region = ar_chan_o.region;
+    assign dram_delayed.ar_user = '0;
+
+    assign dram_delayed.w_data = w_chan_o.data;
+    assign dram_delayed.w_strb = w_chan_o.strb;
+    assign dram_delayed.w_last = w_chan_o.last;
+    assign dram_delayed.w_user = '0;
+
+    assign r_chan_i.id = dram_delayed.r_id;
+    assign r_chan_i.data = dram_delayed.r_data;
+    assign r_chan_i.resp = dram_delayed.r_resp;
+    assign r_chan_i.last = dram_delayed.r_last;
+    assign dram.r_user = '0;
+
+    assign b_chan_i.id = dram_delayed.b_id;
+    assign b_chan_i.resp = dram_delayed.b_resp;
+    assign dram.b_user = '0;
+
     axi2mem #(
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES ),
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH   ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH      ),
-        .AXI_USER_WIDTH ( AXI_USER_WIDTH      )
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_USER_WIDTH ( AXI_USER_WIDTH           )
     ) i_axi2mem (
-        .clk_i  ( clk_i      ),
-        .rst_ni ( ndmreset_n ),
-        .slave  ( dram       ),
-        .req_o  ( req        ),
-        .we_o   ( we         ),
-        .addr_o ( addr       ),
-        .be_o   ( be         ),
-        .data_o ( wdata      ),
-        .data_i ( rdata      )
+        .clk_i  ( clk_i        ),
+        .rst_ni ( ndmreset_n   ),
+        .slave  ( dram_delayed ),
+        .req_o  ( req          ),
+        .we_o   ( we           ),
+        .addr_o ( addr         ),
+        .be_o   ( be           ),
+        .data_o ( wdata        ),
+        .data_i ( rdata        )
     );
 
     sram #(
@@ -375,13 +508,13 @@ module ariane_testharness #(
     // AXI Xbar
     // ---------------
     axi_node_intf_wrap #(
-        .NB_SLAVE           ( NB_SLAVE                   ),
+        .NB_SLAVE           ( ariane_soc::NrSlaves       ),
         .NB_MASTER          ( ariane_soc::NB_PERIPHERALS ),
         .NB_REGION          ( ariane_soc::NrRegion       ),
         .AXI_ADDR_WIDTH     ( AXI_ADDRESS_WIDTH          ),
         .AXI_DATA_WIDTH     ( AXI_DATA_WIDTH             ),
         .AXI_USER_WIDTH     ( AXI_USER_WIDTH             ),
-        .AXI_ID_WIDTH       ( AXI_ID_WIDTH               )
+        .AXI_ID_WIDTH       ( ariane_axi::IdWidth        )
         // .MASTER_SLICE_DEPTH ( 0                          ),
         // .SLAVE_SLICE_DEPTH  ( 0                          )
     ) i_axi_xbar (
@@ -425,10 +558,10 @@ module ariane_testharness #(
     ariane_axi::resp_t   axi_clint_resp;
 
     clint #(
-        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH   ),
-        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH      ),
-        .AXI_ID_WIDTH   ( AXI_ID_WIDTH_SLAVES ),
-        .NR_CORES       ( 1                   )
+        .AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH        ),
+        .AXI_DATA_WIDTH ( AXI_DATA_WIDTH           ),
+        .AXI_ID_WIDTH   ( ariane_axi::IdWidthSlave ),
+        .NR_CORES       ( 1                        )
     ) i_clint (
         .clk_i       ( clk_i          ),
         .rst_ni      ( ndmreset_n     ),
@@ -453,12 +586,21 @@ module ariane_testharness #(
     logic [1:0] irqs;
 
     ariane_peripherals #(
-      .AxiAddrWidth ( AXI_ADDRESS_WIDTH   ),
-      .AxiDataWidth ( AXI_DATA_WIDTH      ),
-      .AxiIdWidth   ( AXI_ID_WIDTH_SLAVES ),
-      .InclUART     ( 1'b0                ),
-      .InclSPI      ( 1'b0                ),
-      .InclEthernet ( 1'b0                )
+      .AxiAddrWidth ( AXI_ADDRESS_WIDTH        ),
+      .AxiDataWidth ( AXI_DATA_WIDTH           ),
+      .AxiIdWidth   ( ariane_axi::IdWidthSlave ),
+`ifndef VERILATOR
+    // disable UART when using Spike, as we need to rely on the mockuart
+    `ifdef SPIKE_TANDEM
+      .InclUART     ( 1'b0                     ),
+    `else
+      .InclUART     ( 1'b1                     ),
+    `endif
+`else
+      .InclUART     ( 1'b0                     ),
+`endif
+      .InclSPI      ( 1'b0                     ),
+      .InclEthernet ( 1'b0                     )
     ) i_ariane_peripherals (
       .clk_i     ( clk_i                        ),
       .rst_ni    ( ndmreset_n                   ),
@@ -496,7 +638,7 @@ module ariane_testharness #(
 
     ariane #(
 `ifdef PITON_ARIANE
-        .AxiIdWidth    ( AXI_ID_WIDTH                                    ),
+        .AxiIdWidth    ( ariane_axi::IdWidth                             ),
         .SwapEndianess ( 0                                               ),
         .CachedAddrEnd ( (ariane_soc::DRAMBase + ariane_soc::DRAMLength) ),
 `endif
@@ -510,7 +652,12 @@ module ariane_testharness #(
         .irq_i                ( irqs                ),
         .ipi_i                ( ipi                 ),
         .time_irq_i           ( timer_irq           ),
+// Disable Debug when simulating with Spike
+`ifdef SPIKE_TANDEM
+        .debug_req_i          ( 1'b0                ),
+`else
         .debug_req_i          ( debug_req_core      ),
+`endif
         .axi_req_o            ( axi_ariane_req      ),
         .axi_resp_i           ( axi_ariane_resp     )
     );
@@ -521,4 +668,86 @@ module ariane_testharness #(
       .master(slave[0])
     );
 
+    // -------------
+    // Simulation Helper Functions
+    // -------------
+    // check for response errors
+    always_comb begin
+        if (axi_ariane_req.r_ready &&
+            axi_ariane_resp.r_valid &&
+            axi_ariane_resp.r.resp inside {axi_pkg::RESP_DECERR, axi_pkg::RESP_SLVERR}) begin
+            $warning("R Response Errored");
+        end
+        if (axi_ariane_req.b_ready &&
+            axi_ariane_resp.b_valid &&
+            axi_ariane_resp.b.resp inside {axi_pkg::RESP_DECERR, axi_pkg::RESP_SLVERR}) begin
+            $warning("B Response Errored");
+        end
+    end
+
+`ifdef AXI_SVA
+    // AXI 4 Assertion IP integration - You will need to get your own copy of this IP if you want
+    // to use it
+    Axi4PC #(
+        .DATA_WIDTH(ariane_axi::DataWidth),
+        .WID_WIDTH(ariane_axi::IdWidthSlave),
+        .RID_WIDTH(ariane_axi::IdWidthSlave),
+        .AWUSER_WIDTH(ariane_axi::UserWidth),
+        .WUSER_WIDTH(ariane_axi::UserWidth),
+        .BUSER_WIDTH(ariane_axi::UserWidth),
+        .ARUSER_WIDTH(ariane_axi::UserWidth),
+        .RUSER_WIDTH(ariane_axi::UserWidth),
+        .ADDR_WIDTH(ariane_axi::AddrWidth)
+    ) i_Axi4PC (
+        .ACLK(clk_i),
+        .ARESETn(ndmreset_n),
+        .AWID(dram.aw_id),
+        .AWADDR(dram.aw_addr),
+        .AWLEN(dram.aw_len),
+        .AWSIZE(dram.aw_size),
+        .AWBURST(dram.aw_burst),
+        .AWLOCK(dram.aw_lock),
+        .AWCACHE(dram.aw_cache),
+        .AWPROT(dram.aw_prot),
+        .AWQOS(dram.aw_qos),
+        .AWREGION(dram.aw_region),
+        .AWUSER(dram.aw_user),
+        .AWVALID(dram.aw_valid),
+        .AWREADY(dram.aw_ready),
+        .WLAST(dram.w_last),
+        .WDATA(dram.w_data),
+        .WSTRB(dram.w_strb),
+        .WUSER(dram.w_user),
+        .WVALID(dram.w_valid),
+        .WREADY(dram.w_ready),
+        .BID(dram.b_id),
+        .BRESP(dram.b_resp),
+        .BUSER(dram.b_user),
+        .BVALID(dram.b_valid),
+        .BREADY(dram.b_ready),
+        .ARID(dram.ar_id),
+        .ARADDR(dram.ar_addr),
+        .ARLEN(dram.ar_len),
+        .ARSIZE(dram.ar_size),
+        .ARBURST(dram.ar_burst),
+        .ARLOCK(dram.ar_lock),
+        .ARCACHE(dram.ar_cache),
+        .ARPROT(dram.ar_prot),
+        .ARQOS(dram.ar_qos),
+        .ARREGION(dram.ar_region),
+        .ARUSER(dram.ar_user),
+        .ARVALID(dram.ar_valid),
+        .ARREADY(dram.ar_ready),
+        .RID(dram.r_id),
+        .RLAST(dram.r_last),
+        .RDATA(dram.r_data),
+        .RRESP(dram.r_resp),
+        .RUSER(dram.r_user),
+        .RVALID(dram.r_valid),
+        .RREADY(dram.r_ready),
+        .CACTIVE('0),
+        .CSYSREQ('0),
+        .CSYSACK('0)
+    );
+`endif
 endmodule
diff --git a/tb/common/spike.sv b/tb/common/spike.sv
new file mode 100644
index 0000000000000000000000000000000000000000..4ced4fecfb8dc2754f24de44a2f4f1f9f2f75cbb
--- /dev/null
+++ b/tb/common/spike.sv
@@ -0,0 +1,119 @@
+// Copyright 2018 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License.  You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+//
+// Author: Florian Zaruba, ETH Zurich
+// Date: 3/11/2018
+// Description: Wrapped Spike Model for Tandem Verification
+
+import uvm_pkg::*;
+
+`include "uvm_macros.svh"
+
+import "DPI-C" function int spike_create(string filename, longint unsigned dram_base, int unsigned size);
+import "DPI-C" function void spike_tick(output riscv::commit_log_t commit_log);
+import "DPI-C" function void clint_tick();
+
+module spike #(
+    parameter longint unsigned DramBase = 'h8000_0000,
+    parameter int unsigned     Size     = 64 * 1024 * 1024 // 64 Mega Byte
+)(
+    input logic       clk_i,
+    input logic       rst_ni,
+    input logic       clint_tick_i,
+    input ariane_pkg::scoreboard_entry_t [ariane_pkg::NR_COMMIT_PORTS-1:0] commit_instr_i,
+    input logic [ariane_pkg::NR_COMMIT_PORTS-1:0]                          commit_ack_i,
+    input ariane_pkg::exception_t                                          exception_i,
+    input logic [ariane_pkg::NR_COMMIT_PORTS-1:0][4:0]                     waddr_i,
+    input logic [ariane_pkg::NR_COMMIT_PORTS-1:0][63:0]                    wdata_i,
+    input riscv::priv_lvl_t                                                priv_lvl_i
+);
+    static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst();
+
+    string binary = "";
+
+    logic fake_clk;
+
+    logic clint_tick_q, clint_tick_qq, clint_tick_qqq, clint_tick_qqqq;
+
+    initial begin
+        void'(uvcl.get_arg_value("+PRELOAD=", binary));
+        assert(binary != "") else $error("We need a preloaded binary for tandem verification");
+        void'(spike_create(binary, DramBase, Size));
+    end
+
+    riscv::commit_log_t commit_log;
+    logic [31:0] instr;
+
+    always_ff @(posedge clk_i) begin
+        if (rst_ni) begin
+
+            for (int i = 0; i < ariane_pkg::NR_COMMIT_PORTS; i++) begin
+                if (commit_instr_i[i].valid && commit_ack_i[i]) begin
+                    spike_tick(commit_log);
+                    instr = (commit_log.instr[1:0] != 2'b11) ? {16'b0, commit_log.instr[15:0]} : commit_log.instr;
+                    // $display("\x1B[32m%h %h\x1B[0m", commit_log.pc, instr);
+                    // $display("%p", commit_log);
+                    // $display("\x1B[37m%h %h\x1B[0m", commit_instr_i[i].pc, commit_instr_i[i].ex.tval[31:0]);
+                    assert (commit_log.pc === commit_instr_i[i].pc) else begin
+                        $warning("\x1B[33m[Tandem] PCs Mismatch\x1B[0m");
+                        // $stop;
+                    end
+                    assert (commit_log.was_exception === exception_i.valid) else begin
+                        $warning("\x1B[33m[Tandem] Exception not detected\x1B[0m");
+                        // $stop;
+                        $display("Spike: %p", commit_log);
+                        $display("Ariane: %p", commit_instr_i[i]);
+                    end
+                    if (!exception_i.valid) begin
+                        assert (commit_log.priv === priv_lvl_i) else begin
+                            $warning("\x1B[33m[Tandem] Privilege level mismatches\x1B[0m");
+                            // $stop;
+                            $display("\x1B[37m %2d == %2d @ PC %h\x1B[0m", priv_lvl_i, commit_log.priv, commit_log.pc);
+                        end
+                        assert (instr === commit_instr_i[i].ex.tval) else begin
+                            $warning("\x1B[33m[Tandem] Decoded instructions mismatch\x1B[0m");
+                            // $stop;
+                            $display("\x1B[37m%h === %h @ PC %h\x1B[0m", commit_instr_i[i].ex.tval, instr, commit_log.pc);
+                        end
+                        // TODO(zarubaf): Adapt for floating point instructions
+                        if (commit_instr_i[i].rd != 0) begin
+                            // check the return value
+                            // $display("\x1B[37m%h === %h\x1B[0m", commit_instr_i[i].rd, commit_log.rd);
+                            assert (waddr_i[i] === commit_log.rd) else begin
+                                $warning("\x1B[33m[Tandem] Destination register mismatches\x1B[0m");
+                                // $stop;
+                            end
+                            assert (wdata_i[i] === commit_log.data) else begin
+                                $warning("\x1B[33m[Tandem] Write back data mismatches\x1B[0m");
+                                $display("\x1B[37m%h === %h @ PC %h\x1B[0m", wdata_i[i], commit_log.data, commit_log.pc);
+                            end
+                        end
+                    end
+                end
+            end
+        end
+    end
+
+    // we want to schedule the timer increment at the end of this cycle
+    assign #1ps fake_clk = clk_i;
+
+    always_ff @(posedge fake_clk) begin
+        clint_tick_q <= clint_tick_i;
+        clint_tick_qq <= clint_tick_q;
+        clint_tick_qqq <= clint_tick_qq;
+        clint_tick_qqqq <= clint_tick_qqq;
+    end
+
+    always_ff @(posedge clint_tick_qqqq) begin
+        if (rst_ni) begin
+            void'(clint_tick());
+        end
+    end
+endmodule
diff --git a/tb/dpi/sim_spike.cc b/tb/dpi/sim_spike.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f82f0905d50e71272875b81e761ff1143e019437
--- /dev/null
+++ b/tb/dpi/sim_spike.cc
@@ -0,0 +1,135 @@
+// See LICENSE for license details.
+
+#include "sim_spike.h"
+#include "mmu.h"
+#include "dts.h"
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <climits>
+#include <cstdlib>
+#include <cassert>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <inttypes.h>
+
+sim_spike_t::sim_spike_t(const char* isa, size_t nprocs,
+             std::vector<std::pair<reg_t, mem_t*>> mems,
+             const std::vector<std::string>& args)
+  : mems(mems), procs(std::max(nprocs, size_t(1))),
+  current_step(0), current_proc(0), debug(false), log(true),
+    histogram_enabled(false), dtb_enabled(true), remote_bitbang(NULL)
+{
+
+  for (auto& x : mems)
+    bus.add_device(x.first, x.second);
+
+  debug_mmu = new mmu_t(this, NULL);
+
+  for (size_t i = 0; i < procs.size(); i++) {
+    procs[i] = new processor_t(isa, this, i, false);
+  }
+
+  clint.reset(new clint_t(procs));
+  // we need to bring the clint to a reproducible default value
+  clint.get()->reset();
+  bus.add_device(CLINT_BASE, clint.get());
+  uart.reset(new uart_t());
+  bus.add_device(UART_BASE, uart.get());
+  make_bootrom();
+  set_procs_debug(true);
+}
+
+sim_spike_t::~sim_spike_t()
+{
+  for (size_t i = 0; i < procs.size(); i++)
+    delete procs[i];
+  delete debug_mmu;
+}
+
+commit_log_t sim_spike_t::tick(size_t n)
+{
+  commit_log_t commit_log;
+
+  reg_t pc = procs[0]->get_state()->pc;
+  auto& reg = procs[0]->get_state()->log_reg_write;
+  // execute instruction
+  procs[0]->step(n);
+  int priv = procs[0]->get_state()->last_inst_priv;
+  int xlen = procs[0]->get_state()->last_inst_xlen;
+  int flen = procs[0]->get_state()->last_inst_flen;
+
+  commit_log.priv = priv;
+  commit_log.pc = pc;
+  commit_log.is_fp = reg.addr & 1;
+  commit_log.rd = reg.addr >> 1;
+  commit_log.data = reg.data.v[0];
+  commit_log.instr = procs[0]->get_state()->last_insn;
+  commit_log.was_exception = procs[0]->get_state()->was_exception;
+
+  return commit_log;
+}
+
+void sim_spike_t::clint_tick() {
+  clint->increment(1);
+}
+
+void sim_spike_t::set_debug(bool value)
+{
+  debug = value;
+}
+
+void sim_spike_t::set_log(bool value)
+{
+  log = value;
+}
+
+void sim_spike_t::set_histogram(bool value)
+{
+  histogram_enabled = value;
+  for (size_t i = 0; i < procs.size(); i++) {
+    procs[i]->set_histogram(histogram_enabled);
+  }
+}
+
+void sim_spike_t::set_procs_debug(bool value)
+{
+  for (size_t i=0; i< procs.size(); i++)
+    procs[i]->set_debug(value);
+}
+
+bool sim_spike_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  if (addr + len < addr)
+    return false;
+  return bus.load(addr, len, bytes);
+}
+
+bool sim_spike_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  if (addr + len < addr)
+    return false;
+  return bus.store(addr, len, bytes);
+}
+
+void sim_spike_t::make_bootrom()
+{
+  start_pc = 0x80000000;
+
+  #include "bootrom.h"
+
+  std::vector<char> rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec));
+
+  boot_rom.reset(new rom_device_t(rom));
+  bus.add_device(DEFAULT_RSTVEC, boot_rom.get());
+}
+
+char* sim_spike_t::addr_to_mem(reg_t addr) {
+  auto desc = bus.find_device(addr);
+  if (auto mem = dynamic_cast<mem_t*>(desc.second))
+    if (addr - desc.first < mem->size())
+      return mem->contents() + (addr - desc.first);
+  return NULL;
+}
\ No newline at end of file
diff --git a/tb/dpi/sim_spike.h b/tb/dpi/sim_spike.h
new file mode 100644
index 0000000000000000000000000000000000000000..0619166a2fa0cf67e06c98169ca1e89cdbb01767
--- /dev/null
+++ b/tb/dpi/sim_spike.h
@@ -0,0 +1,95 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_SPIKE_H
+#define _RISCV_SPIKE_H
+
+#include "processor.h"
+#include "devices.h"
+#include "debug_module.h"
+#include "simif.h"
+#include <fesvr/htif.h>
+#include <fesvr/context.h>
+#include <vector>
+#include <string>
+#include <memory>
+#include <thread>
+
+class mmu_t;
+class remote_bitbang_t;
+
+typedef struct
+{
+  char     priv;
+  uint64_t pc;
+  char     is_fp;
+  char     rd;
+  uint64_t data;
+  uint32_t instr;
+  char     was_exception;
+} commit_log_t;
+
+// this class encapsulates the processors and memory in a RISC-V machine.
+class sim_spike_t : public simif_t
+{
+public:
+  sim_spike_t(const char* isa, size_t _nprocs,
+        std::vector<std::pair<reg_t, mem_t*>> mems,
+        const std::vector<std::string>& args);
+  ~sim_spike_t();
+
+  int init_sim();
+  void producer_thread();
+  void clint_tick();
+  commit_log_t tick(size_t n); // step through simulation
+  void set_debug(bool value);
+  void set_log(bool value);
+  void set_histogram(bool value);
+  void set_procs_debug(bool value);
+  void set_dtb_enabled(bool value) {
+    this->dtb_enabled = value;
+  }
+  void set_remote_bitbang(remote_bitbang_t* remote_bitbang) {
+    this->remote_bitbang = remote_bitbang;
+  }
+  const char* get_dts() { return dts.c_str(); }
+  processor_t* get_core(size_t i) { return procs.at(i); }
+  unsigned nprocs() const { return procs.size(); }
+
+private:
+  std::vector<std::pair<reg_t, mem_t*>> mems;
+  mmu_t* debug_mmu;  // debug port into main memory
+  std::vector<processor_t*> procs;
+  reg_t start_pc;
+  std::string dts;
+  std::unique_ptr<rom_device_t> boot_rom;
+  std::unique_ptr<clint_t> clint;
+  std::unique_ptr<uart_t> uart;
+  bus_t bus;
+  std::thread t1;
+
+  processor_t* get_core(const std::string& i);
+  static const size_t INTERLEAVE = 5000;
+  static const size_t INSNS_PER_RTC_TICK = 100; // 10 MHz clock for 1 BIPS core
+  static const size_t CPU_HZ = 1000000000; // 1GHz CPU
+  size_t current_step;
+  size_t current_proc;
+  bool debug;
+  bool log;
+  bool histogram_enabled; // provide a histogram of PCs
+  bool dtb_enabled;
+  remote_bitbang_t* remote_bitbang;
+
+  // memory-mapped I/O routines
+  char* addr_to_mem(reg_t addr);
+  bool mmio_load(reg_t addr, size_t len, uint8_t* bytes);
+  bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes);
+  void proc_reset(unsigned id) {};
+
+  void make_bootrom();
+
+public:
+
+};
+
+
+#endif
\ No newline at end of file
diff --git a/tb/dpi/spike.cc b/tb/dpi/spike.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fda0684481e58140c1579dc4e2a2bf326260b959
--- /dev/null
+++ b/tb/dpi/spike.cc
@@ -0,0 +1,133 @@
+#include <fesvr/elf.h>
+#include <fesvr/memif.h>
+
+#include "sim_spike.h"
+#include "msim_helper.h"
+
+#include <vpi_user.h>
+#include "svdpi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+#include <string>
+#include <memory>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <assert.h>
+#include <unistd.h>
+#include <map>
+#include <iostream>
+
+sim_spike_t* sim;
+std::vector<std::pair<reg_t, mem_t*>> mem;
+commit_log_t commit_log_val;
+
+#define SHT_PROGBITS 0x1
+#define SHT_GROUP 0x11
+
+void write_spike_mem (reg_t address, size_t len, uint8_t* buf) {
+    memcpy(mem[0].second->contents() + (address & ~(1 << 31)), buf,len);
+}
+
+void read_elf(const char* filename) {
+    int fd = open(filename, O_RDONLY);
+    struct stat s;
+    assert(fd != -1);
+    if (fstat(fd, &s) < 0)
+    abort();
+    size_t size = s.st_size;
+
+    char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+    assert(buf != MAP_FAILED);
+    close(fd);
+
+    assert(size >= sizeof(Elf64_Ehdr));
+    const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf;
+    assert(IS_ELF32(*eh64) || IS_ELF64(*eh64));
+
+    std::vector<uint8_t> zeros;
+
+    #define LOAD_ELF(ehdr_t, phdr_t, shdr_t, sym_t) do { \
+    ehdr_t* eh = (ehdr_t*)buf; \
+    phdr_t* ph = (phdr_t*)(buf + eh->e_phoff); \
+    assert(size >= eh->e_phoff + eh->e_phnum*sizeof(*ph)); \
+    for (unsigned i = 0; i < eh->e_phnum; i++) { \
+      if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { \
+        if (ph[i].p_filesz) { \
+          assert(size >= ph[i].p_offset + ph[i].p_filesz); \
+          write_spike_mem(ph[i].p_paddr, ph[i].p_filesz, (uint8_t*)buf + ph[i].p_offset); \
+        } \
+        zeros.resize(ph[i].p_memsz - ph[i].p_filesz); \
+      } \
+    } \
+    shdr_t* sh = (shdr_t*)(buf + eh->e_shoff); \
+    assert(size >= eh->e_shoff + eh->e_shnum*sizeof(*sh)); \
+    assert(eh->e_shstrndx < eh->e_shnum); \
+    assert(size >= sh[eh->e_shstrndx].sh_offset + sh[eh->e_shstrndx].sh_size); \
+    char *shstrtab = buf + sh[eh->e_shstrndx].sh_offset; \
+    unsigned strtabidx = 0, symtabidx = 0; \
+    for (unsigned i = 0; i < eh->e_shnum; i++) { \
+      unsigned max_len = sh[eh->e_shstrndx].sh_size - sh[i].sh_name; \
+      if ((sh[i].sh_type & SHT_GROUP) && strcmp(shstrtab + sh[i].sh_name, ".strtab") != 0 && strcmp(shstrtab + sh[i].sh_name, ".shstrtab") != 0) \
+      assert(strnlen(shstrtab + sh[i].sh_name, max_len) < max_len); \
+      if (sh[i].sh_type & SHT_PROGBITS) continue; \
+      if (strcmp(shstrtab + sh[i].sh_name, ".strtab") == 0) \
+        strtabidx = i; \
+      if (strcmp(shstrtab + sh[i].sh_name, ".symtab") == 0) \
+        symtabidx = i; \
+    } \
+    if (strtabidx && symtabidx) { \
+      char* strtab = buf + sh[strtabidx].sh_offset; \
+      sym_t* sym = (sym_t*)(buf + sh[symtabidx].sh_offset); \
+      for (unsigned i = 0; i < sh[symtabidx].sh_size/sizeof(sym_t); i++) { \
+        unsigned max_len = sh[strtabidx].sh_size - sym[i].st_name; \
+        assert(sym[i].st_name < sh[strtabidx].  sh_size); \
+        assert(strnlen(strtab + sym[i].st_name, max_len) < max_len); \
+      } \
+    } \
+    } while(0)
+
+  if (IS_ELF32(*eh64))
+    LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym);
+  else
+    LOAD_ELF(Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Sym);
+
+  munmap(buf, size);
+}
+
+extern "C" void spike_create(const char* filename, uint64_t dram_base, unsigned int size)
+{
+
+    mem = std::vector<std::pair<reg_t, mem_t*>>(1, std::make_pair(reg_t(dram_base), new mem_t(size)));
+    // zero out memory
+    memset(mem[0].second->contents(), 0, size_t(size));
+
+    read_elf(filename);
+
+    if (!sim) {
+      std::vector<std::string> htif_args = sanitize_args();
+
+      sim = new sim_spike_t("rv64imac", 1, mem, htif_args);
+    }
+}
+
+// advance Spike and get the retired instruction
+extern "C" void spike_tick(commit_log_t* commit_log)
+{
+  commit_log_val = sim->tick(1);
+  commit_log->priv = commit_log_val.priv;
+  commit_log->pc = commit_log_val.pc;
+  commit_log->is_fp = commit_log_val.is_fp;
+  commit_log->rd = commit_log_val.rd;
+  commit_log->data = commit_log_val.data;
+  commit_log->instr = commit_log_val.instr;
+  commit_log->was_exception = commit_log_val.was_exception;
+}
+
+extern "C" void clint_tick()
+{
+  sim->clint_tick();
+}
\ No newline at end of file
diff --git a/tb/riscv-isa-sim/.gitignore b/tb/riscv-isa-sim/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..725115102292e1d751fbbee6dca1d6eeb3c3de9d
--- /dev/null
+++ b/tb/riscv-isa-sim/.gitignore
@@ -0,0 +1,8 @@
+build/
+install/
+*.gch
+autom4te.cache/
+.*.swp
+*.o
+*.d
+.gdb_history
diff --git a/tb/riscv-isa-sim/LICENSE b/tb/riscv-isa-sim/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..34f576ba819ce4b37747be1fda2ba6196b63f98d
--- /dev/null
+++ b/tb/riscv-isa-sim/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2010-2017, The Regents of the University of California
+(Regents).  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the Regents nor the
+   names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
+OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
diff --git a/tb/riscv-isa-sim/Makefile.in b/tb/riscv-isa-sim/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..c09fc505881b393afd7ac1f34b03a513d7ab50f6
--- /dev/null
+++ b/tb/riscv-isa-sim/Makefile.in
@@ -0,0 +1,491 @@
+#=========================================================================
+# Toplevel Makefile for the Modular C++ Build System
+#=========================================================================
+# Please read the documenation in 'mcppbs-doc.txt' for more details on
+# how the Modular C++ Build System works. For most projects, a developer
+# will not need to make any changes to this makefile. The key targets
+# are as follows:
+#
+#  - default   : build all libraries and programs
+#  - check     : build and run all unit tests
+#  - install   : install headers, project library, and some programs
+#  - clean     : remove all generated content (except autoconf files)
+#  - dist      : make a source tarball
+#  - distcheck : make a source tarball, untar it, check it, clean it
+#  - distclean : remove everything
+#
+
+#-------------------------------------------------------------------------
+# Basic setup
+#-------------------------------------------------------------------------
+
+# Remove all default implicit rules since they can cause subtle bugs
+# and they just make things run slower
+.SUFFIXES:
+% : %,v
+% : RCS/%,v
+% : RCS/%
+% : s.%
+% : SCCS/s.%
+
+# Default is to build the prereqs of the all target (defined at bottom)
+default : all
+.PHONY : default
+
+project_name := @PACKAGE_TARNAME@
+src_dir      := @srcdir@
+scripts_dir  := $(src_dir)/scripts
+
+# If the version information is not in the configure script, then we
+# assume that we are in a working directory. We use the vcs-version.sh
+# script in the scripts directory to generate an appropriate version
+# string. Currently the way things are setup we have to run this script
+# everytime we run make so the script needs to be as fast as possible.
+
+ifeq (@PACKAGE_VERSION@,?)
+  project_ver:=$(shell $(scripts_dir)/vcs-version.sh $(src_dir))
+else
+  project_ver:=@PACKAGE_VERSION@
+endif
+
+# Installation directories
+
+prefix       := @prefix@
+enable_stow  := @enable_stow@
+
+ifeq ($(enable_stow),yes)
+  stow_pkg_dir := $(prefix)/pkgs
+  INSTALLDIR ?= $(DESTDIR)$(stow_pkg_dir)/$(project_name)-$(project_ver)
+else
+  INSTALLDIR ?= $(DESTDIR)$(prefix)
+endif
+
+install_hdrs_dir := $(INSTALLDIR)/include/$(project_name)
+install_libs_dir := $(INSTALLDIR)/lib
+install_exes_dir := $(INSTALLDIR)/bin
+
+#-------------------------------------------------------------------------
+# List of subprojects
+#-------------------------------------------------------------------------
+
+sprojs         := @subprojects@
+sprojs_enabled := @subprojects_enabled@
+
+sprojs_include := -I. -I$(src_dir) $(addprefix -I$(src_dir)/, $(sprojs_enabled))
+VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled))
+
+#-------------------------------------------------------------------------
+# Programs and flags 
+#-------------------------------------------------------------------------
+
+# C++ compiler
+#  - CPPFLAGS : flags for the preprocessor (eg. -I,-D)
+#  - CXXFLAGS : flags for C++ compiler (eg. -Wall,-g,-O3)
+
+CC            := @CC@
+CXX           := @CXX@
+CFLAGS        += @CFLAGS@ -DPREFIX=\"$(prefix)\"
+CPPFLAGS      += @CPPFLAGS@
+CXXFLAGS      += @CXXFLAGS@ -DPREFIX=\"$(prefix)\"
+COMPILE       := $(CXX) -fPIC -MMD -MP $(CPPFLAGS) $(CXXFLAGS) \
+                 $(sprojs_include)
+COMPILE_C     := $(CC) -fPIC -MMD -MP $(CPPFLAGS) $(CFLAGS) \
+                 $(sprojs_include)
+# Linker
+#  - LDFLAGS : Flags for the linker (eg. -L)
+#  - LIBS    : Library flags (eg. -l)
+
+comma := ,
+LD            := $(CXX)
+LDFLAGS       := @LDFLAGS@
+LIBS          := @LIBS@
+LINK          := $(LD) -L. $(LDFLAGS) -Wl,-rpath,$(install_libs_dir) $(patsubst -L%,-Wl$(comma)-rpath$(comma)%,$(filter -L%,$(LDFLAGS)))
+
+# Library creation
+
+AR            := @AR@
+RANLIB        := @RANLIB@
+
+# Host simulator
+
+RUN           := @RUN@
+RUNFLAGS      := @RUNFLAGS@
+
+# Installation
+
+MKINSTALLDIRS := $(scripts_dir)/mk-install-dirs.sh
+INSTALL       := @INSTALL@
+INSTALL_HDR   := $(INSTALL) -m 444
+INSTALL_LIB   := $(INSTALL) -m 644
+INSTALL_EXE   := $(INSTALL) -m 555
+STOW          := @stow@
+
+# Tests
+bintests = $(src_dir)/tests/ebreak.py
+
+#-------------------------------------------------------------------------
+# Include subproject makefile fragments
+#-------------------------------------------------------------------------
+
+sprojs_mk = $(addsuffix .mk, $(sprojs_enabled))
+
+-include $(sprojs_mk)
+
+dist_junk += $(sprojs_mk)
+
+#-------------------------------------------------------------------------
+# Reverse list helper function
+#-------------------------------------------------------------------------
+# This function is used by the subproject template to reverse the list
+# of dependencies. It uses recursion to perform the reversal.
+# 
+# Arguments:
+#  $(1)   : space separated input list
+#  retval : input list in reverse order
+#
+
+reverse_list = $(call reverse_list_h,$(1),)
+define reverse_list_h
+  $(if $(strip $(1)),                        \
+    $(call reverse_list_h,                   \
+           $(wordlist 2,$(words $(1)),$(1)), \
+           $(firstword $(1)) $(2)),          \
+    $(2))
+endef
+
+#-------------------------------------------------------------------------
+# Template for per subproject rules
+#-------------------------------------------------------------------------
+# The template is instantiated for each of the subprojects. It relies on
+# subprojects defining a certain set of make variables which are all
+# prefixed with the subproject name. Since subproject names can have
+# dashes in them (and the make variables are assumed to only use
+# underscores) the template takes two arguments - one with the regular 
+# subproject name and one with dashes replaced with underscores.
+#
+# Arguments:
+#  $(1) : real subproject name (ie with dashes)
+#  $(2) : normalized subproject name (ie dashes replaced with underscores)
+#
+
+define subproject_template
+
+# In some (rare) cases, a subproject might not have any actual object
+# files. It might only include header files or program sources. To keep
+# things consistent we still want a library for this subproject, so in
+# this spectial case we create a dummy source file and thus the build
+# system will create a library for this subproject with just the
+# corresponding dummy object file.
+
+ifeq ($$(strip $$($(2)_srcs) $$($(2)_c_srcs)),)
+$(2)_srcs += _$(1).cc
+$(2)_junk += _$(1).cc
+endif
+
+_$(1).cc :
+	echo "int _$(2)( int arg ) { return arg; }" > $$@
+
+# Build the object files for this subproject
+
+$(2)_pch := $$(patsubst %.h, %.h.gch, $$($(2)_precompiled_hdrs))
+$(2)_objs := $$(patsubst %.cc, %.o, $$($(2)_srcs))
+$(2)_c_objs := $$(patsubst %.c, %.o, $$($(2)_c_srcs))
+$(2)_deps := $$(patsubst %.o, %.d, $$($(2)_objs))
+$(2)_deps += $$(patsubst %.o, %.d, $$($(2)_c_objs))
+$(2)_deps += $$(patsubst %.h, %.h.d, $$($(2)_precompiled_hdrs))
+$$($(2)_pch) : %.h.gch : %.h
+	$(COMPILE) -x c++-header $$< -o $$@
+# If using clang, don't depend (and thus don't build) precompiled headers
+$$($(2)_objs) : %.o : %.cc $$($(2)_gen_hdrs) $(if $(filter-out clang,$(CC)),$$($(2)_pch))
+	$(COMPILE) -c $$<
+$$($(2)_c_objs) : %.o : %.c $$($(2)_gen_hdrs)
+	$(COMPILE_C) -c $$<
+
+$(2)_junk += $$($(2)_pch) $$($(2)_objs) $$($(2)_c_objs) $$($(2)_deps) \
+  $$($(2)_gen_hdrs)
+
+# Reverse the dependency list so that a given subproject only depends on
+# subprojects listed to its right. This is the correct order for linking
+# the list of subproject libraries.
+
+$(2)_reverse_deps   := $$(call reverse_list,$$($(2)_subproject_deps))
+
+# Build a library for this subproject
+
+$(2)_lib_libs       := $$($(2)_reverse_deps)
+$(2)_lib_libnames   := $$(patsubst %, lib%.so, $$($(2)_lib_libs))
+$(2)_lib_libarg     := $$(patsubst %, -l%, $$($(2)_lib_libs))
+
+lib$(1).so : $$($(2)_objs) $$($(2)_c_objs) $$($(2)_lib_libnames)
+	$(LINK) -shared -o $$@ $(if $(filter Darwin,$(shell uname -s)),-install_name $(install_libs_dir)/$$@) $$^ $$($(2)_lib_libarg) $(LIBS)
+
+$(2)_junk += lib$(1).so
+
+# Build unit tests
+
+$(2)_test_objs      := $$(patsubst %.cc, %.o, $$($(2)_test_srcs))
+$(2)_test_deps      := $$(patsubst %.o, %.d, $$($(2)_test_objs))
+$(2)_test_exes      := $$(patsubst %.t.cc, %-utst, $$($(2)_test_srcs))
+$(2)_test_outs      := $$(patsubst %, %.out, $$($(2)_test_exes))
+$(2)_test_libs      := $(1) $$($(2)_reverse_deps) utst
+$(2)_test_libnames  := $$(patsubst %, lib%.so, $$($(2)_test_libs))
+$(2)_test_libarg    := $$(patsubst %, -l%, $$($(2)_test_libs))
+
+$$($(2)_test_objs) : %.o : %.cc
+	$(COMPILE) -c $$<
+
+$$($(2)_test_exes) : %-utst : %.t.o $$($(2)_test_libnames)
+	$(LINK) -o $$@ $$< $$($(2)_test_libarg) $(LIBS)
+
+$(2)_deps += $$($(2)_test_deps)
+$(2)_junk += \
+	$$($(2)_test_objs) $$($(2)_test_deps) \
+  $$($(2)_test_exes) *.junk-dat
+
+# Run unit tests
+
+$$($(2)_test_outs) : %.out : %
+	$(RUN) $(RUNFLAGS) ./$$< default | tee $$@
+
+$(2)_junk += $$($(2)_test_outs)
+
+# Build programs
+
+$(2)_prog_objs      := $$(patsubst %.cc, %.o, $$($(2)_prog_srcs))
+$(2)_prog_deps      := $$(patsubst %.o, %.d, $$($(2)_prog_objs))
+$(2)_prog_exes      := $$(patsubst %.cc, %, $$($(2)_prog_srcs))
+$(2)_prog_libs      := $(1) $$($(2)_reverse_deps)
+$(2)_prog_libnames  := $$(patsubst %, lib%.so, $$($(2)_prog_libs))
+$(2)_prog_libarg    := $$(patsubst %, -l%, $$($(2)_prog_libs))
+
+$$($(2)_prog_objs) : %.o : %.cc
+	$(COMPILE) -c $$<
+
+$$($(2)_prog_exes) : % : %.o $$($(2)_prog_libnames)
+	$(LINK) -o $$@ $$< $$($(2)_prog_libarg) $(LIBS)
+
+$(2)_deps += $$($(2)_prog_deps)
+$(2)_junk += $$($(2)_prog_objs) $$($(2)_prog_deps) $$($(2)_prog_exes)
+
+# Build programs which will be installed
+
+$(2)_install_prog_objs := $$(patsubst %.cc, %.o, $$($(2)_install_prog_srcs))
+$(2)_install_prog_deps := $$(patsubst %.o, %.d, $$($(2)_install_prog_objs))
+$(2)_install_prog_exes := $$(patsubst %.cc, %, $$($(2)_install_prog_srcs))
+
+$$($(2)_install_prog_objs) : %.o : %.cc $$($(2)_gen_hdrs)
+	$(COMPILE) -c $$<
+
+$$($(2)_install_prog_exes) : % : %.o $$($(2)_prog_libnames)
+	$(LINK) -o $$@ $$< $$($(2)_prog_libarg) $(LIBS)
+
+$(2)_deps += $$($(2)_install_prog_deps)
+$(2)_junk += \
+  $$($(2)_install_prog_objs) $$($(2)_install_prog_deps) \
+  $$($(2)_install_prog_exes)
+
+# Subproject specific targets
+
+all-$(1) : lib$(1).so $$($(2)_install_prog_exes)
+
+check-$(1) : $$($(2)_test_outs)
+	echo; grep -h -e'Unit Tests' -e'FAILED' -e'Segementation' $$^; echo
+
+clean-$(1) :
+	rm -rf $$($(2)_junk)
+
+.PHONY : all-$(1) check-$(1) clean-$(1)
+
+# Update running variables
+
+libs += lib$(1).so
+objs += $$($(2)_objs)
+srcs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_srcs)) 
+hdrs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_hdrs)) $$($(2)_gen_hdrs)
+junk += $$($(2)_junk)
+deps += $$($(2)_deps)
+
+test_outs += $$($(2)_test_outs)
+
+install_hdrs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_hdrs)) $$($(2)_gen_hdrs)
+install_libs += lib$(1).so
+install_exes += $$($(2)_install_prog_exes)
+install_pcs  += riscv-$(1).pc
+
+endef
+
+# Iterate over the subprojects and call the template for each one
+
+$(foreach sproj,$(sprojs_enabled), \
+  $(eval $(call subproject_template,$(sproj),$(subst -,_,$(sproj)))))
+
+#-------------------------------------------------------------------------
+# Autodependency files
+#-------------------------------------------------------------------------
+
+-include $(deps)
+
+deps : $(deps)
+.PHONY : deps
+
+#-------------------------------------------------------------------------
+# Check
+#-------------------------------------------------------------------------
+
+bintest_outs = $(bintests:=.out)
+junk += $(bintest_outs)
+%.out: % all
+	./$* < /dev/null 2>&1 | tee $@
+
+check-cpp : $(test_outs)
+	@echo
+	! grep -h -e'Unit Tests' -e'FAILED' -e'Segmentation' $^ < /dev/null
+	@echo
+
+check-bin : $(bintest_outs)
+	! tail -n 1 $^ < /dev/null 2>&1 | grep FAILED
+
+check : check-cpp check-bin
+
+.PHONY : check
+
+#-------------------------------------------------------------------------
+# Installation
+#-------------------------------------------------------------------------
+
+install-hdrs : $(install_hdrs) config.h
+	$(MKINSTALLDIRS) $(install_hdrs_dir)
+	for file in $^; \
+  do \
+    $(INSTALL_HDR) $$file $(install_hdrs_dir); \
+  done
+
+install-libs : $(install_libs)
+	$(MKINSTALLDIRS) $(install_libs_dir)
+	for file in $^; \
+  do \
+    $(INSTALL_LIB) $$file $(install_libs_dir); \
+  done
+
+install-exes : $(install_exes)
+	$(MKINSTALLDIRS) $(install_exes_dir)
+	for file in $^; \
+  do \
+    $(INSTALL_EXE) $$file $(install_exes_dir); \
+  done
+
+install-pc : $(install_pcs)
+	$(MKINSTALLDIRS) $(install_libs_dir)/pkgconfig/
+	for file in $^; \
+  do \
+    $(INSTALL_HDR) $$file $(install_libs_dir)/pkgconfig/; \
+  done
+
+install : install-hdrs install-libs install-exes install-pc
+ifeq ($(enable_stow),yes)
+	$(MKINSTALLDIRS) $(stow_pkg_dir)
+	cd $(stow_pkg_dir) && \
+    $(STOW) --delete $(project_name)-* && \
+    $(STOW) $(project_name)-$(project_ver)
+endif
+
+.PHONY : install install-hdrs install-libs install-exes
+
+#-------------------------------------------------------------------------
+# Regenerate configure information
+#-------------------------------------------------------------------------
+
+config.status : $(src_dir)/configure
+	./config.status --recheck
+
+sprojs_mk_in = \
+  $(join $(addprefix $(src_dir)/, $(sprojs_enabled)), \
+         $(patsubst  %, /%.mk.in, $(sprojs_enabled)))
+
+Makefile : $(src_dir)/Makefile.in $(sprojs_mk_in) config.status
+	./config.status
+
+dist_junk += config.status config.h Makefile config.log
+
+#-------------------------------------------------------------------------
+# Distribution
+#-------------------------------------------------------------------------
+# The distribution tarball is named project-ver.tar.gz and it includes
+# both enabled and disabled subprojects. 
+
+dist_files = \
+  $(sprojs) \
+  README \
+  style-guide.txt \
+  mcppbs-uguide.txt \
+  scripts \
+  configure.ac \
+  aclocal.m4 \
+  configure \
+  config.h.in \
+  Makefile.in \
+
+dist_dir := $(project_name)-$(project_ver)
+dist_tgz := $(project_name)-$(project_ver).tar.gz
+
+# Notice that when we make the distribution we rewrite the configure.ac
+# script with the current version and we rerun autoconf in the new
+# source directory so that the distribution will have the proper version
+# information. We also rewrite the "Version : " line in the README.
+
+dist :
+	rm -rf $(dist_dir)
+	mkdir $(dist_dir)
+	tar -C $(src_dir) -cf - $(dist_files) | tar -C $(dist_dir) -xpf -
+	sed -i.bak 's/^\(# Version :\).*/\1 $(project_ver)/' $(dist_dir)/README
+	sed -i.bak 's/\( proj_version,\).*/\1 [$(project_ver)])/' $(dist_dir)/configure.ac
+	cd $(dist_dir) && \
+    autoconf && autoheader && \
+    rm -rf autom4te.cache configure.ac.bak README.bak
+	tar -czvf $(dist_tgz) $(dist_dir)
+	rm -rf $(dist_dir)
+
+# You can use the distcheck target to try untarring the distribution and
+# then running configure, make, make check, and make distclean. A
+# "directory is not empty" error means distclean is not removing
+# everything.
+
+distcheck : dist
+	rm -rf $(dist_dir)
+	tar -xzvf $(dist_tgz)
+	mkdir -p $(dist_dir)/build
+	cd $(dist_dir)/build; ../configure; make; make check; make distclean
+	rm -rf $(dist_dir)
+
+junk += $(project_name)-*.tar.gz
+
+.PHONY : dist distcheck
+
+#-------------------------------------------------------------------------
+# Default
+#-------------------------------------------------------------------------
+
+all : $(install_hdrs) $(install_libs) $(install_exes)
+.PHONY : all
+
+#-------------------------------------------------------------------------
+# Makefile debugging
+#-------------------------------------------------------------------------
+# This handy rule will display the contents of any make variable by
+# using the target debug-<varname>. So for example, make debug-junk will
+# display the contents of the junk variable.
+
+debug-% :
+	@echo $* = $($*)
+
+#-------------------------------------------------------------------------
+# Clean up junk
+#-------------------------------------------------------------------------
+
+clean :
+	rm -rf *~ \#* $(junk)
+
+distclean :
+	rm -rf *~ \#* $(junk) $(dist_junk)
+
+.PHONY : clean distclean
diff --git a/tb/riscv-isa-sim/README.md b/tb/riscv-isa-sim/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..018c7d3eadfe823050eb18862d14c6fa5aa0b9fb
--- /dev/null
+++ b/tb/riscv-isa-sim/README.md
@@ -0,0 +1,223 @@
+Spike RISC-V ISA Simulator
+============================
+
+About
+-------------
+
+Spike, the RISC-V ISA Simulator, implements a functional model of one or more
+RISC-V processors.
+
+Spike is named after the golden spike used to celebrate the completion of the
+US transcontinental railway.
+
+Build Steps
+---------------
+
+We assume that the RISCV environment variable is set to the RISC-V tools
+install path, and that the riscv-fesvr package is installed there.
+
+    $ apt-get install device-tree-compiler
+    $ mkdir build
+    $ cd build
+    $ ../configure --prefix=$RISCV --with-fesvr=$RISCV
+    $ make
+    $ [sudo] make install
+
+Compiling and Running a Simple C Program
+-------------------------------------------
+
+Install spike (see Build Steps), riscv-gnu-toolchain, and riscv-pk.
+
+Write a short C program and name it hello.c.  Then, compile it into a RISC-V
+ELF binary named hello:
+
+    $ riscv64-unknown-elf-gcc -o hello hello.c
+
+Now you can simulate the program atop the proxy kernel:
+
+    $ spike pk hello
+
+Simulating a New Instruction
+------------------------------------
+
+Adding an instruction to the simulator requires two steps:
+
+  1.  Describe the instruction's functional behavior in the file
+      riscv/insns/<new_instruction_name>.h.  Examine other instructions
+      in that directory as a starting point.
+
+  2.  Add the opcode and opcode mask to riscv/opcodes.h.  Alternatively,
+      add it to the riscv-opcodes package, and it will do so for you:
+
+         $ cd ../riscv-opcodes
+         $ vi opcodes       // add a line for the new instruction
+         $ make install
+
+  3.  Rebuild the simulator.
+
+Interactive Debug Mode
+---------------------------
+
+To invoke interactive debug mode, launch spike with -d:
+
+    $ spike -d pk hello
+
+To see the contents of an integer register (0 is for core 0):
+
+    : reg 0 a0
+
+To see the contents of a floating point register:
+
+    : fregs 0 ft0
+
+or:
+
+    : fregd 0 ft0
+
+depending upon whether you wish to print the register as single- or double-precision.
+
+To see the contents of a memory location (physical address in hex):
+
+    : mem 2020
+
+To see the contents of memory with a virtual address (0 for core 0):
+
+    : mem 0 2020
+
+You can advance by one instruction by pressing <enter>. You can also
+execute until a desired equality is reached:
+
+    : until pc 0 2020                   (stop when pc=2020)
+    : until mem 2020 50a9907311096993   (stop when mem[2020]=50a9907311096993)
+
+Alternatively, you can execute as long as an equality is true:
+
+    : while mem 2020 50a9907311096993
+
+You can continue execution indefinitely by:
+
+    : r
+
+At any point during execution (even without -d), you can enter the
+interactive debug mode with `<control>-<c>`.
+
+To end the simulation from the debug prompt, press `<control>-<c>` or:
+
+    : q
+
+Debugging With Gdb
+------------------
+
+An alternative to interactive debug mode is to attach using gdb. Because spike
+tries to be like real hardware, you also need OpenOCD to do that. OpenOCD
+doesn't currently know about address translation, so it's not possible to
+easily debug programs that are run under `pk`. We'll use the following test
+program:
+```
+$ cat rot13.c 
+char text[] = "Vafgehpgvba frgf jnag gb or serr!";
+
+// Don't use the stack, because sp isn't set up.
+volatile int wait = 1;
+
+int main()
+{
+    while (wait)
+        ;
+
+    // Doesn't actually go on the stack, because there are lots of GPRs.
+    int i = 0;
+    while (text[i]) {
+        char lower = text[i] | 32;
+        if (lower >= 'a' && lower <= 'm')
+            text[i] += 13;
+        else if (lower > 'm' && lower <= 'z')
+            text[i] -= 13;
+        i++;
+    }
+
+    while (!wait)
+        ;
+}
+$ cat spike.lds 
+OUTPUT_ARCH( "riscv" )
+
+SECTIONS
+{
+  . = 0x10010000;
+  .text : { *(.text) }
+  .data : { *(.data) }
+}
+$ riscv64-unknown-elf-gcc -g -Og -o rot13-64.o -c rot13.c
+$ riscv64-unknown-elf-gcc -g -Og -T spike.lds -nostartfiles -o rot13-64 rot13-64.o
+```
+
+To debug this program, first run spike telling it to listen for OpenOCD:
+```
+$ spike --rbb-port=9824 -m0x10000000:0x20000 rot13-64
+Listening for remote bitbang connection on port 9824.
+```
+
+In a separate shell run OpenOCD with the appropriate configuration file:
+```
+$ cat spike.cfg 
+interface remote_bitbang
+remote_bitbang_host localhost
+remote_bitbang_port 9824
+
+set _CHIPNAME riscv
+jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
+
+set _TARGETNAME $_CHIPNAME.cpu
+target create $_TARGETNAME riscv -chain-position $_TARGETNAME
+
+gdb_report_data_abort enable
+
+init
+halt
+$ openocd -f spike.cfg
+Open On-Chip Debugger 0.10.0-dev-00002-gc3b344d (2017-06-08-12:14)
+...
+riscv.cpu: target state: halted
+```
+
+In yet another shell, start your gdb debug session:
+```
+tnewsome@compy-vm:~/SiFive/spike-test$ riscv64-unknown-elf-gdb rot13-64
+GNU gdb (GDB) 7.12.50.20170505-git
+Copyright (C) 2016 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
+and "show warranty" for details.
+This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf".
+Type "show configuration" for configuration details.
+For bug reporting instructions, please see:
+<http://www.gnu.org/software/gdb/bugs/>.
+Find the GDB manual and other documentation resources online at:
+<http://www.gnu.org/software/gdb/documentation/>.
+For help, type "help".
+Type "apropos word" to search for commands related to "word"...
+Reading symbols from rot13-64...done.
+(gdb) target remote localhost:3333
+Remote debugging using localhost:3333
+0x000000001001000a in main () at rot13.c:8
+8           while (wait)
+(gdb) print wait
+$1 = 1
+(gdb) print wait=0
+$2 = 0
+(gdb) print text
+$3 = "Vafgehpgvba frgf jnag gb or serr!"
+(gdb) b 23
+Breakpoint 1 at 0x10010064: file rot13.c, line 23.
+(gdb) c
+Continuing.
+
+Breakpoint 1, main () at rot13.c:23
+23          while (!wait)
+(gdb) print wait
+$4 = 0
+(gdb) print text
+...
+```
diff --git a/tb/riscv-isa-sim/aclocal.m4 b/tb/riscv-isa-sim/aclocal.m4
new file mode 100644
index 0000000000000000000000000000000000000000..15353f2c954500c1650f582336429f2b6bf00e5a
--- /dev/null
+++ b/tb/riscv-isa-sim/aclocal.m4
@@ -0,0 +1,345 @@
+#=========================================================================
+# Local Autoconf Macros
+#=========================================================================
+# This file contains the macros for the Modular C++ Build System and
+# additional autoconf macros which developers can use in their
+# configure.ac scripts. Please read the documentation in
+# 'mcppbs-doc.txt' for more details on how the Modular C++ Build System
+# works. The documenation for each macro should include information
+# about the author, date, and copyright.
+
+#-------------------------------------------------------------------------
+# MCPPBS_PROG_INSTALL
+#-------------------------------------------------------------------------
+# This macro will add an --enable-stow command line option to the
+# configure script. When enabled, this macro will first check to see if
+# the stow program is available and if so it will set the $stow shell
+# variable to the binary name and the $enable_stow shell variable to
+# "yes". These variables can be used in a makefile to conditionally use
+# stow for installation. 
+#
+# This macro uses two environment variables to help setup default stow
+# locations. The $STOW_PREFIX is used for stowing native built packages.
+# The packages are staged in $STOW_PREFIX/pkgs and then symlinks are
+# created from within $STOW_PREFIX into the pkgs subdirectory. If you
+# only do native builds then this is all you need to set. If you don't
+# set $STOW_PREFIX then the default is just the normal default prefix
+# which is almost always /usr/local.
+#
+# For non-native builds we probably want to install the packages in a
+# different location which includes the host architecture name as part
+# of the prefix. For these kind of builds, we can specify the $STOW_ROOT
+# environment variable and the effective prefix will be
+# $STOW_ROOT/${host_alias} where ${host_alias} is specified on the
+# configure command line with "--host".
+#
+# Here is an example setup:
+#
+#  STOW_ROOT="$HOME/install"
+#  STOW_ARCH="i386-macosx10.4"
+#  STOW_PREFIX="${STOW_ROOT}/${STOW_ARCH}"
+#
+
+AC_DEFUN([MCPPBS_PROG_INSTALL],
+[
+
+  # Configure command line option
+
+  AC_ARG_ENABLE(stow,
+    AS_HELP_STRING(--enable-stow,[Enable stow-based install]),
+      [enable_stow="yes"],[enable_stow="no"])
+
+  AC_SUBST([enable_stow])
+   
+  # Environment variables
+
+  AC_ARG_VAR([STOW_ROOT],   [Root for non-native stow-based installs])
+  AC_ARG_VAR([STOW_PREFIX], [Prefix for stow-based installs])
+
+  # Check for install script
+
+  AC_PROG_INSTALL
+
+  # Deterimine if native build and set prefix appropriately
+  
+  AS_IF([ test ${enable_stow} = "yes" ],
+  [
+    AC_CHECK_PROGS([stow],[stow],[no])  
+    AS_IF([ test ${stow} = "no" ],
+    [
+      AC_MSG_ERROR([Cannot use --enable-stow since stow is not available])
+    ])
+
+    # Check if native or non-native build
+
+    AS_IF([ test "${build}" = "${host}" ],
+    [
+
+      # build == host so this is a native build. Make sure --prefix not
+      # set and $STOW_PREFIX is set, then set prefix=$STOW_PREFIX.
+
+      AS_IF([ test "${prefix}" = "NONE" && test -n "${STOW_PREFIX}" ],
+      [
+        prefix="${STOW_PREFIX}"
+        AC_MSG_NOTICE([Using \$STOW_PREFIX from environment])
+        AC_MSG_NOTICE([prefix=${prefix}])
+      ])
+
+    ],[
+
+      # build != host so this is a non-native build. Make sure --prefix
+      # not set and $STOW_ROOT is set, then set
+      # prefix=$STOW_ROOT/${host_alias}.
+
+      AS_IF([ test "${prefix}" = "NONE" && test -n "${STOW_ROOT}" ],
+      [
+        prefix="${STOW_ROOT}/${host_alias}"
+        AC_MSG_NOTICE([Using \$STOW_ROOT from environment])
+        AC_MSG_NOTICE([prefix=${prefix}])
+      ])
+
+    ])
+      
+  ])
+
+])
+
+#-------------------------------------------------------------------------
+# MCPPBS_PROG_RUN
+# -------------------------------------------------------------------------
+# If we are doing a non-native build then we look for an isa simulator
+# to use for running tests. We set the RUN substitution variable to be
+# empty for native builds or to the name of the isa simulator for
+# non-native builds. Thus a makefile can run compiled programs
+# regardless if we are doing a native or non-native build like this:
+# 
+#  $(RUN) $(RUNFLAGS) ./test-program
+#
+
+AC_DEFUN([MCPPBS_PROG_RUN],
+[
+  AS_IF([ test "${build}" != "${host}" ],
+  [
+    AC_CHECK_TOOLS([RUN],[isa-run run],[no])
+    AS_IF([ test ${RUN} = "no" ],
+    [
+      AC_MSG_ERROR([Cannot find simulator for target ${target_alias}])
+    ])
+  ],[
+    RUN=""
+  ])
+  AC_SUBST([RUN])
+  AC_SUBST([RUNFLAGS])
+])
+
+#-------------------------------------------------------------------------
+# MCPPBS_SUBPROJECTS([ sproj1, sproj2, ... ])
+#-------------------------------------------------------------------------
+# The developer should call this macro with a list of the subprojects
+# which make up this project. One should order the list such that any
+# given subproject only depends on subprojects listed before it. The
+# subproject names can also include an * suffix which indicates that
+# this is an optional subproject. Optional subprojects are only included
+# as part of the project build if enabled on the configure command line
+# with a --enable-<subproject> flag. The user can also specify that all
+# optional subprojects should be included in the build with the
+# --enable-optional-subprojects flag.
+#
+# Subproject names can also include a ** suffix which indicates that it
+# is an optional subproject, but there is a group with the same name.
+# Thus the --enable-<sproj> command line option will enable not just the
+# subproject sproj but all of the subprojects which are in the group.
+# There is no error checking to make sure that if you use the ** suffix
+# you actually define a group so be careful.
+#
+# Both required and optional subprojects should have a 'subproject.ac'
+# file. The script's filename should be the abbreivated subproject name
+# (assuming the subproject name is sproj then we would use 'sproj.ac')
+# The MCPPBS_SUBPROJECTS macro includes the 'subproject.ac' files for
+# enabled subprojects. Whitespace and newlines are allowed within the
+# list.
+#
+# Author : Christopher Batten
+# Date   : September 10, 2008
+
+AC_DEFUN([MCPPBS_SUBPROJECTS],
+[
+
+  # Add command line argument to enable all optional subprojects 
+
+  AC_ARG_ENABLE(optional-subprojects,
+    AS_HELP_STRING([--enable-optional-subprojects],
+      [Enable all optional subprojects]))
+
+  # Loop through the subprojects given in the macro argument
+
+  m4_foreach([MCPPBS_SPROJ],[$1],
+  [
+  
+    # Determine if this is a required or an optional subproject
+
+    m4_define([MCPPBS_IS_REQ],
+      m4_bmatch(MCPPBS_SPROJ,[\*+],[false],[true]))
+
+    # Determine if there is a group with the same name
+
+    m4_define([MCPPBS_IS_GROUP],
+      m4_bmatch(MCPPBS_SPROJ,[\*\*],[true],[false]))
+
+    # Create variations of the subproject name suitable for use as a CPP
+    # enabled define, a shell enabled variable, and a shell function
+
+    m4_define([MCPPBS_SPROJ_NORM],
+      m4_normalize(m4_bpatsubsts(MCPPBS_SPROJ,[*],[])))
+
+    m4_define([MCPPBS_SPROJ_DEFINE],
+      m4_toupper(m4_bpatsubst(MCPPBS_SPROJ_NORM[]_ENABLED,[-],[_])))
+
+    m4_define([MCPPBS_SPROJ_FUNC],
+      m4_bpatsubst(_mpbp_[]MCPPBS_SPROJ_NORM[]_configure,[-],[_]))
+
+    m4_define([MCPPBS_SPROJ_UNDERSCORES],
+      m4_bpatsubsts(MCPPBS_SPROJ,[-],[_]))
+
+    m4_define([MCPPBS_SPROJ_SHVAR],
+      m4_bpatsubst(enable_[]MCPPBS_SPROJ_NORM[]_sproj,[-],[_]))
+    
+    # Add subproject to our running list
+
+    subprojects="$subprojects MCPPBS_SPROJ_NORM"
+
+    # Process the subproject appropriately. If enabled add it to the
+    # $enabled_subprojects running shell variable, set a
+    # SUBPROJECT_ENABLED C define, and include the appropriate
+    # 'subproject.ac'.
+
+    m4_if(MCPPBS_IS_REQ,[true],
+    [
+      AC_MSG_NOTICE([configuring default subproject : MCPPBS_SPROJ_NORM])
+      AC_CONFIG_FILES(MCPPBS_SPROJ_NORM[].mk:MCPPBS_SPROJ_NORM[]/MCPPBS_SPROJ_NORM[].mk.in)
+      MCPPBS_SPROJ_SHVAR="yes"
+      subprojects_enabled="$subprojects_enabled MCPPBS_SPROJ_NORM"
+      AC_DEFINE(MCPPBS_SPROJ_DEFINE,,
+        [Define if subproject MCPPBS_SPROJ_NORM is enabled])
+      m4_include(MCPPBS_SPROJ_NORM[]/MCPPBS_SPROJ_NORM[].ac) 
+    ],[
+
+      # For optional subprojects we capture the 'subproject.ac' as a
+      # shell function so that in the MCPPBS_GROUP macro we can just
+      # call this shell function instead of reading in 'subproject.ac'
+      # again.
+
+      MCPPBS_SPROJ_FUNC ()
+      { 
+        AC_MSG_NOTICE([configuring optional subproject : MCPPBS_SPROJ_NORM])
+        AC_CONFIG_FILES(MCPPBS_SPROJ_NORM[].mk:MCPPBS_SPROJ_NORM[]/MCPPBS_SPROJ_NORM[].mk.in)
+        MCPPBS_SPROJ_SHVAR="yes"
+        subprojects_enabled="$subprojects_enabled MCPPBS_SPROJ_NORM"
+        AC_DEFINE(MCPPBS_SPROJ_DEFINE,,
+          [Define if subproject MCPPBS_SPROJ_NORM is enabled])
+        m4_include(MCPPBS_SPROJ_NORM[]/MCPPBS_SPROJ_NORM[].ac) 
+      };
+
+      # Optional subprojects add --enable-subproject command line
+      # options, _if_ the subproject name is not also a group name.
+
+      m4_if(MCPPBS_IS_GROUP,[false],
+      [
+        AC_ARG_ENABLE(MCPPBS_SPROJ_NORM,
+          AS_HELP_STRING(--enable-MCPPBS_SPROJ_NORM,
+            [Subproject MCPPBS_SPROJ_NORM]),
+          [MCPPBS_SPROJ_SHVAR="yes"],[MCPPBS_SPROJ_SHVAR="no"])
+
+        AS_IF([test "$MCPPBS_SPROJ_SHVAR" = "yes"],
+        [
+          eval "MCPPBS_SPROJ_FUNC"
+        ],[ 
+          AC_MSG_NOTICE([processing optional subproject : MCPPBS_SPROJ_NORM])
+        ])
+
+     ],[
+
+       # If the subproject name is also a group name then we need to
+       # make sure that we set the shell variable for that subproject to
+       # no so that the group code knows we haven't run it yet.
+
+       AC_MSG_NOTICE([processing optional subproject : MCPPBS_SPROJ_NORM])
+       MCPPBS_SPROJ_SHVAR="no"
+
+     ])
+
+     # Always execute the subproject configure code if we are enabling
+     # all subprojects.
+
+     AS_IF([    test "$enable_optional_subprojects" = "yes" \
+             && test "$MCPPBS_SPROJ_SHVAR" = "no"  ],
+     [
+       eval "MCPPBS_SPROJ_FUNC"
+     ])
+
+    ])
+
+  ])
+
+  # Output make variables  
+
+  AC_SUBST([subprojects])
+  AC_SUBST([subprojects_enabled])
+
+])
+
+#-------------------------------------------------------------------------
+# MCPPBS_GROUP( [group-name], [ sproj1, sproj2, ... ] )
+#-------------------------------------------------------------------------
+# This macro creates a subproject group with the given group-name. When
+# a user specifies --enable-<group-name> the listed subprojects will be
+# enabled. Groups can have the same name as a subproject and in that
+# case whenever a user specifies --enable-<subproject> the subprojects
+# listed in the corresponding group will also be enabled. Groups are
+# useful for specifying related subprojects which are usually enabled
+# together, as well as for specifying that a specific optional
+# subproject has dependencies on other optional subprojects.
+#
+# Author : Christopher Batten
+# Date   : September 10, 2008
+
+AC_DEFUN([MCPPBS_GROUP],
+[
+
+  m4_define([MCPPBS_GROUP_NORM],
+    m4_normalize([$1]))
+
+  m4_define([MCPPBS_GROUP_SHVAR],
+    m4_bpatsubst(enable_[]MCPPBS_GROUP_NORM[]_group,[-],[_]))
+                
+  AC_ARG_ENABLE(MCPPBS_GROUP_NORM,
+    AS_HELP_STRING(--enable-MCPPBS_GROUP_NORM,
+      [Group MCPPBS_GROUP_NORM: $2]),
+    [MCPPBS_GROUP_SHVAR="yes"],[MCPPBS_GROUP_SHVAR="no"])
+
+  AS_IF([test "$MCPPBS_GROUP_SHVAR" = "yes" ],
+  [ 
+    AC_MSG_NOTICE([configuring optional group : MCPPBS_GROUP_NORM])
+  ])
+
+  m4_foreach([MCPPBS_SPROJ],[$2],
+  [    
+
+    m4_define([MCPPBS_SPROJ_NORM],
+      m4_normalize(MCPPBS_SPROJ))
+
+    m4_define([MCPPBS_SPROJ_SHVAR],
+      m4_bpatsubst(enable_[]MCPPBS_SPROJ_NORM[]_sproj,[-],[_]))
+
+    m4_define([MCPPBS_SPROJ_FUNC],
+      m4_bpatsubst(_mpbp_[]MCPPBS_SPROJ_NORM[]_configure,[-],[_]))
+
+    AS_IF([    test "$MCPPBS_GROUP_SHVAR" = "yes" \
+            && test "$MCPPBS_SPROJ_SHVAR" = "no" ],
+    [
+      eval "MCPPBS_SPROJ_FUNC"
+    ])
+
+  ])
+
+])
diff --git a/tb/riscv-isa-sim/config.h.in b/tb/riscv-isa-sim/config.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..137f1950054e3e4b709a76233c2aadcee778c7cf
--- /dev/null
+++ b/tb/riscv-isa-sim/config.h.in
@@ -0,0 +1,100 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Default value for --isa switch */
+#undef DEFAULT_ISA
+
+/* Path to the device-tree-compiler */
+#undef DTC
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef DUMMY_ROCC_ENABLED
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `fesvr' library (-lfesvr). */
+#undef HAVE_LIBFESVR
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#undef HAVE_LIBPTHREAD
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef RISCV_ENABLED
+
+/* Enable commit log generation */
+#undef RISCV_ENABLE_COMMITLOG
+
+/* Enable hardware management of PTE accessed and dirty bits */
+#undef RISCV_ENABLE_DIRTY
+
+/* Enable PC histogram generation */
+#undef RISCV_ENABLE_HISTOGRAM
+
+/* Enable hardware support for misaligned loads and stores */
+#undef RISCV_ENABLE_MISALIGNED
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef SOFTFLOAT_ENABLED
+
+/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
+#undef SPIKE_MAIN_ENABLED
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+   significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+#  define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+#  undef WORDS_BIGENDIAN
+# endif
+#endif
diff --git a/tb/riscv-isa-sim/configure b/tb/riscv-isa-sim/configure
new file mode 100755
index 0000000000000000000000000000000000000000..015f63e965a04eabe6cecb4d7f984c0e35345476
--- /dev/null
+++ b/tb/riscv-isa-sim/configure
@@ -0,0 +1,6166 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for RISC-V ISA Simulator ?.
+#
+# Report bugs to <Andrew Waterman>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and Andrew Waterman
+$0: about your system, including any error possibly output
+$0: before this message. Then install a modern shell, or
+$0: manually run the script under such a shell if you do
+$0: have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='RISC-V ISA Simulator'
+PACKAGE_TARNAME='spike'
+PACKAGE_VERSION='?'
+PACKAGE_STRING='RISC-V ISA Simulator ?'
+PACKAGE_BUGREPORT='Andrew Waterman'
+PACKAGE_URL=''
+
+ac_unique_file="riscv/common.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+subprojects_enabled
+subprojects
+stow
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+STOW_PREFIX
+STOW_ROOT
+enable_stow
+EGREP
+GREP
+CXXCPP
+DTC
+RANLIB
+AR
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_stow
+enable_optional_subprojects
+with_isa
+with_fesvr
+enable_commitlog
+enable_histogram
+enable_dirty
+enable_misaligned
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CXXCPP
+STOW_ROOT
+STOW_PREFIX'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir runstatedir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures RISC-V ISA Simulator ? to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/spike]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of RISC-V ISA Simulator ?:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-stow           Enable stow-based install
+  --enable-optional-subprojects
+                          Enable all optional subprojects
+  --enable-commitlog      Enable commit log generation
+  --enable-histogram      Enable PC histogram generation
+  --enable-dirty          Enable hardware management of PTE accessed and dirty
+                          bits
+  --enable-misaligned     Enable hardware support for misaligned loads and
+                          stores
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-isa=RV64IMAFDC   Sets the default RISC-V ISA
+  --with-fesvr            path to your fesvr installation if not in a standard
+                          location
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CXXCPP      C++ preprocessor
+  STOW_ROOT   Root for non-native stow-based installs
+  STOW_PREFIX Prefix for stow-based installs
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <Andrew Waterman>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+RISC-V ISA Simulator configure ?
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_cxx_try_run LINENO
+# ------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_cxx_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_run
+
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_cxx_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_compile
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by RISC-V ISA Simulator $as_me ?, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_aux_dir=
+for ac_dir in scripts "$srcdir"/scripts; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in scripts \"$srcdir\"/scripts" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+#-------------------------------------------------------------------------
+# Checks for programs
+#-------------------------------------------------------------------------
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="${ac_tool_prefix}ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+  ac_ct_AR=$AR
+  # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="ar"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AR" = x; then
+    AR=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+else
+  AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+# Extract the first word of "dtc", so it can be a program name with args.
+set dummy dtc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_DTC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $DTC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_DTC="$DTC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_DTC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_DTC" && ac_cv_path_DTC="no"
+  ;;
+esac
+fi
+DTC=$ac_cv_path_DTC
+if test -n "$DTC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTC" >&5
+$as_echo "$DTC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test x"$DTC" == xno; then :
+  as_fn_error $? "device-tree-compiler not found" "$LINENO" 5
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DTC "$DTC"
+_ACEOF
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if ${ac_cv_prog_CXXCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     as_fn_error $? "Spike requires a little-endian host" "$LINENO" 5;; #(
+   no)
+      ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+#-------------------------------------------------------------------------
+# MCPPBS specific program checks
+#-------------------------------------------------------------------------
+# These macros check to see if we can do a stow-based install and also
+# check for an isa simulator suitable for running the unit test programs
+# via the makefile.
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+
+  # Configure command line option
+
+  # Check whether --enable-stow was given.
+if test "${enable_stow+set}" = set; then :
+  enableval=$enable_stow; enable_stow="yes"
+else
+  enable_stow="no"
+fi
+
+
+
+
+  # Environment variables
+
+
+
+
+  # Check for install script
+
+
+
+  # Deterimine if native build and set prefix appropriately
+
+  if  test ${enable_stow} = "yes" ; then :
+
+    for ac_prog in stow
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_stow+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$stow"; then
+  ac_cv_prog_stow="$stow" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_stow="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+stow=$ac_cv_prog_stow
+if test -n "$stow"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $stow" >&5
+$as_echo "$stow" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$stow" && break
+done
+test -n "$stow" || stow="no"
+
+    if  test ${stow} = "no" ; then :
+
+      as_fn_error $? "Cannot use --enable-stow since stow is not available" "$LINENO" 5
+
+fi
+
+    # Check if native or non-native build
+
+    if  test "${build}" = "${host}" ; then :
+
+
+      # build == host so this is a native build. Make sure --prefix not
+      # set and $STOW_PREFIX is set, then set prefix=$STOW_PREFIX.
+
+      if  test "${prefix}" = "NONE" && test -n "${STOW_PREFIX}" ; then :
+
+        prefix="${STOW_PREFIX}"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Using \$STOW_PREFIX from environment" >&5
+$as_echo "$as_me: Using \$STOW_PREFIX from environment" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: prefix=${prefix}" >&5
+$as_echo "$as_me: prefix=${prefix}" >&6;}
+
+fi
+
+
+else
+
+
+      # build != host so this is a non-native build. Make sure --prefix
+      # not set and $STOW_ROOT is set, then set
+      # prefix=$STOW_ROOT/${host_alias}.
+
+      if  test "${prefix}" = "NONE" && test -n "${STOW_ROOT}" ; then :
+
+        prefix="${STOW_ROOT}/${host_alias}"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Using \$STOW_ROOT from environment" >&5
+$as_echo "$as_me: Using \$STOW_ROOT from environment" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: prefix=${prefix}" >&5
+$as_echo "$as_me: prefix=${prefix}" >&6;}
+
+fi
+
+
+fi
+
+
+fi
+
+
+
+#-------------------------------------------------------------------------
+# Checks for header files
+#-------------------------------------------------------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+
+#-------------------------------------------------------------------------
+# Default compiler flags
+#-------------------------------------------------------------------------
+
+CFLAGS="-Wall -Wno-unused -g -O2"
+
+CXXFLAGS="-Wall -Wno-unused -g -O2 -std=c++11"
+
+
+#-------------------------------------------------------------------------
+# MCPPBS subproject list
+#-------------------------------------------------------------------------
+# Order list so that subprojects only depend on those listed earlier.
+# The '*' suffix indicates an optional subproject. The '**' suffix
+# indicates an optional subproject which is also the name of a group.
+
+
+
+  # Add command line argument to enable all optional subprojects
+
+  # Check whether --enable-optional-subprojects was given.
+if test "${enable_optional_subprojects+set}" = set; then :
+  enableval=$enable_optional_subprojects;
+fi
+
+
+  # Loop through the subprojects given in the macro argument
+
+
+
+    # Determine if this is a required or an optional subproject
+
+
+
+    # Determine if there is a group with the same name
+
+
+
+    # Create variations of the subproject name suitable for use as a CPP
+    # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+    # Add subproject to our running list
+
+    subprojects="$subprojects riscv"
+
+    # Process the subproject appropriately. If enabled add it to the
+    # $enabled_subprojects running shell variable, set a
+    # SUBPROJECT_ENABLED C define, and include the appropriate
+    # 'subproject.ac'.
+
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : riscv" >&5
+$as_echo "$as_me: configuring default subproject : riscv" >&6;}
+      ac_config_files="$ac_config_files riscv.mk:riscv/riscv.mk.in"
+
+      enable_riscv_sproj="yes"
+      subprojects_enabled="$subprojects_enabled riscv"
+
+$as_echo "#define RISCV_ENABLED /**/" >>confdefs.h
+
+      ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+# Check whether --with-isa was given.
+if test "${with_isa+set}" = set; then :
+  withval=$with_isa;
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_ISA "$withval"
+_ACEOF
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_ISA "RV64IMAFDC"
+_ACEOF
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl dld; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dlopen+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+
+  as_fn_error $? "unable to find the dlopen() function" "$LINENO" 5
+
+fi
+
+
+
+# Check whether --with-fesvr was given.
+if test "${with_fesvr+set}" = set; then :
+  withval=$with_fesvr;
+    LDFLAGS="-L$withval/lib $LDFLAGS"
+    CPPFLAGS="-I$withval/include $CPPFLAGS"
+
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfesvr_is_present in -lfesvr" >&5
+$as_echo_n "checking for libfesvr_is_present in -lfesvr... " >&6; }
+if ${ac_cv_lib_fesvr_libfesvr_is_present+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfesvr -pthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char libfesvr_is_present ();
+int
+main ()
+{
+return libfesvr_is_present ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_lib_fesvr_libfesvr_is_present=yes
+else
+  ac_cv_lib_fesvr_libfesvr_is_present=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fesvr_libfesvr_is_present" >&5
+$as_echo "$ac_cv_lib_fesvr_libfesvr_is_present" >&6; }
+if test "x$ac_cv_lib_fesvr_libfesvr_is_present" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBFESVR 1
+_ACEOF
+
+  LIBS="-lfesvr $LIBS"
+
+else
+  as_fn_error $? "libfesvr is required" "$LINENO" 5
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_create+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  ac_cv_lib_pthread_pthread_create=yes
+else
+  ac_cv_lib_pthread_pthread_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+  LIBS="-lpthread $LIBS"
+
+else
+  as_fn_error $? "libpthread is required" "$LINENO" 5
+fi
+
+
+# Check whether --enable-commitlog was given.
+if test "${enable_commitlog+set}" = set; then :
+  enableval=$enable_commitlog;
+fi
+
+if test "x$enable_commitlog" = "xyes"; then :
+
+
+$as_echo "#define RISCV_ENABLE_COMMITLOG /**/" >>confdefs.h
+
+
+fi
+
+# Check whether --enable-histogram was given.
+if test "${enable_histogram+set}" = set; then :
+  enableval=$enable_histogram;
+fi
+
+if test "x$enable_histogram" = "xyes"; then :
+
+
+$as_echo "#define RISCV_ENABLE_HISTOGRAM /**/" >>confdefs.h
+
+
+fi
+
+# Check whether --enable-dirty was given.
+if test "${enable_dirty+set}" = set; then :
+  enableval=$enable_dirty;
+fi
+
+if test "x$enable_dirty" = "xyes"; then :
+
+
+$as_echo "#define RISCV_ENABLE_DIRTY /**/" >>confdefs.h
+
+
+fi
+
+# Check whether --enable-misaligned was given.
+if test "${enable_misaligned+set}" = set; then :
+  enableval=$enable_misaligned;
+fi
+
+if test "x$enable_misaligned" = "xyes"; then :
+
+
+$as_echo "#define RISCV_ENABLE_MISALIGNED /**/" >>confdefs.h
+
+
+fi
+
+
+
+
+
+    # Determine if this is a required or an optional subproject
+
+
+
+    # Determine if there is a group with the same name
+
+
+
+    # Create variations of the subproject name suitable for use as a CPP
+    # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+    # Add subproject to our running list
+
+    subprojects="$subprojects dummy_rocc"
+
+    # Process the subproject appropriately. If enabled add it to the
+    # $enabled_subprojects running shell variable, set a
+    # SUBPROJECT_ENABLED C define, and include the appropriate
+    # 'subproject.ac'.
+
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : dummy_rocc" >&5
+$as_echo "$as_me: configuring default subproject : dummy_rocc" >&6;}
+      ac_config_files="$ac_config_files dummy_rocc.mk:dummy_rocc/dummy_rocc.mk.in"
+
+      enable_dummy_rocc_sproj="yes"
+      subprojects_enabled="$subprojects_enabled dummy_rocc"
+
+$as_echo "#define DUMMY_ROCC_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
+    # Determine if this is a required or an optional subproject
+
+
+
+    # Determine if there is a group with the same name
+
+
+
+    # Create variations of the subproject name suitable for use as a CPP
+    # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+    # Add subproject to our running list
+
+    subprojects="$subprojects softfloat"
+
+    # Process the subproject appropriately. If enabled add it to the
+    # $enabled_subprojects running shell variable, set a
+    # SUBPROJECT_ENABLED C define, and include the appropriate
+    # 'subproject.ac'.
+
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : softfloat" >&5
+$as_echo "$as_me: configuring default subproject : softfloat" >&6;}
+      ac_config_files="$ac_config_files softfloat.mk:softfloat/softfloat.mk.in"
+
+      enable_softfloat_sproj="yes"
+      subprojects_enabled="$subprojects_enabled softfloat"
+
+$as_echo "#define SOFTFLOAT_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
+    # Determine if this is a required or an optional subproject
+
+
+
+    # Determine if there is a group with the same name
+
+
+
+    # Create variations of the subproject name suitable for use as a CPP
+    # enabled define, a shell enabled variable, and a shell function
+
+
+
+
+
+
+
+
+
+
+
+    # Add subproject to our running list
+
+    subprojects="$subprojects spike_main"
+
+    # Process the subproject appropriately. If enabled add it to the
+    # $enabled_subprojects running shell variable, set a
+    # SUBPROJECT_ENABLED C define, and include the appropriate
+    # 'subproject.ac'.
+
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : spike_main" >&5
+$as_echo "$as_me: configuring default subproject : spike_main" >&6;}
+      ac_config_files="$ac_config_files spike_main.mk:spike_main/spike_main.mk.in"
+
+      enable_spike_main_sproj="yes"
+      subprojects_enabled="$subprojects_enabled spike_main"
+
+$as_echo "#define SPIKE_MAIN_ENABLED /**/" >>confdefs.h
+
+
+
+
+
+
+  # Output make variables
+
+
+
+
+
+
+#-------------------------------------------------------------------------
+# MCPPBS subproject groups
+#-------------------------------------------------------------------------
+# If a group has the same name as a subproject then you must add the
+# '**' suffix in the subproject list above. The list of subprojects in a
+# group should be ordered so that subprojets only depend on those listed
+# earlier. Here is an example:
+#
+#  MCPPBS_GROUP( [group-name], [sproja,sprojb,...] )
+#
+
+#-------------------------------------------------------------------------
+# Output
+#-------------------------------------------------------------------------
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_files="$ac_config_files riscv-spike.pc"
+
+ac_config_files="$ac_config_files riscv-riscv.pc"
+
+ac_config_files="$ac_config_files riscv-softfloat.pc"
+
+ac_config_files="$ac_config_files riscv-dummy_rocc.pc"
+
+ac_config_files="$ac_config_files riscv-spike_main.pc"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by RISC-V ISA Simulator $as_me ?, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <Andrew Waterman>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+RISC-V ISA Simulator config.status ?
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "riscv.mk") CONFIG_FILES="$CONFIG_FILES riscv.mk:riscv/riscv.mk.in" ;;
+    "dummy_rocc.mk") CONFIG_FILES="$CONFIG_FILES dummy_rocc.mk:dummy_rocc/dummy_rocc.mk.in" ;;
+    "softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;;
+    "spike_main.mk") CONFIG_FILES="$CONFIG_FILES spike_main.mk:spike_main/spike_main.mk.in" ;;
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "riscv-spike.pc") CONFIG_FILES="$CONFIG_FILES riscv-spike.pc" ;;
+    "riscv-riscv.pc") CONFIG_FILES="$CONFIG_FILES riscv-riscv.pc" ;;
+    "riscv-softfloat.pc") CONFIG_FILES="$CONFIG_FILES riscv-softfloat.pc" ;;
+    "riscv-dummy_rocc.pc") CONFIG_FILES="$CONFIG_FILES riscv-dummy_rocc.pc" ;;
+    "riscv-spike_main.pc") CONFIG_FILES="$CONFIG_FILES riscv-spike_main.pc" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/tb/riscv-isa-sim/configure.ac b/tb/riscv-isa-sim/configure.ac
new file mode 100644
index 0000000000000000000000000000000000000000..e361877da2a50db38b1424b280e7c639bdc611f7
--- /dev/null
+++ b/tb/riscv-isa-sim/configure.ac
@@ -0,0 +1,113 @@
+#=========================================================================
+# Toplevel configure.ac for the Modular C++ Build System
+#=========================================================================
+# Please read the documenation in 'mcppbs-doc.txt' for more details on
+# how the Modular C++ Build System works. For most new projects, a
+# developer will only need to make the following changes:
+#
+#  - change the project metadata listed right below
+#  - update the list of subprojects via the 'MCPPBS_SUBPROJECTS' macro
+#  - possibly add subproject groups if needed to ease configuration
+#  - add more configure checks for platform specific configuration
+#
+
+#-------------------------------------------------------------------------
+# Project metadata
+#-------------------------------------------------------------------------
+
+m4_define( proj_name,         [RISC-V ISA Simulator])
+m4_define( proj_maintainer,   [Andrew Waterman])
+m4_define( proj_abbreviation, [spike])
+
+#-------------------------------------------------------------------------
+# Project version information
+#-------------------------------------------------------------------------
+# Version information is meant to be managed through a version control
+# system's tags and revision numbers. In a working copy the version will
+# not be defined here (you should just use the version control system's
+# mechanisms). When we make a distribution then we can set the version
+# here as formed by the scripts/vcs-version.sh script so that the
+# distribution knows what version it came from. If you are not using
+# version control then it is fine to set this directly.
+
+m4_define( proj_version, [?])
+
+#-------------------------------------------------------------------------
+# Setup
+#-------------------------------------------------------------------------
+
+AC_INIT(proj_name,proj_version,proj_maintainer,proj_abbreviation)
+AC_LANG_CPLUSPLUS
+AC_CONFIG_SRCDIR([riscv/common.h])
+AC_CONFIG_AUX_DIR([scripts])
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+
+#-------------------------------------------------------------------------
+# Checks for programs
+#-------------------------------------------------------------------------
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_CHECK_TOOL([AR],[ar])
+AC_CHECK_TOOL([RANLIB],[ranlib])
+AC_PATH_PROG([DTC],[dtc],[no])
+AS_IF([test x"$DTC" == xno],AC_MSG_ERROR([device-tree-compiler not found]))
+AC_DEFINE_UNQUOTED(DTC, ["$DTC"], [Path to the device-tree-compiler])
+
+AC_C_BIGENDIAN(AC_MSG_ERROR([Spike requires a little-endian host]))
+
+#-------------------------------------------------------------------------
+# MCPPBS specific program checks
+#-------------------------------------------------------------------------
+# These macros check to see if we can do a stow-based install and also
+# check for an isa simulator suitable for running the unit test programs
+# via the makefile.
+
+MCPPBS_PROG_INSTALL
+
+#-------------------------------------------------------------------------
+# Checks for header files
+#-------------------------------------------------------------------------
+
+AC_HEADER_STDC
+
+#-------------------------------------------------------------------------
+# Default compiler flags
+#-------------------------------------------------------------------------
+
+AC_SUBST([CFLAGS],  ["-Wall -Wno-unused -g -O2"])
+AC_SUBST([CXXFLAGS],["-Wall -Wno-unused -g -O2 -std=c++11"])
+
+#-------------------------------------------------------------------------
+# MCPPBS subproject list
+#-------------------------------------------------------------------------
+# Order list so that subprojects only depend on those listed earlier.
+# The '*' suffix indicates an optional subproject. The '**' suffix
+# indicates an optional subproject which is also the name of a group.
+
+MCPPBS_SUBPROJECTS([ riscv, dummy_rocc, softfloat, spike_main ])
+
+#-------------------------------------------------------------------------
+# MCPPBS subproject groups
+#-------------------------------------------------------------------------
+# If a group has the same name as a subproject then you must add the
+# '**' suffix in the subproject list above. The list of subprojects in a
+# group should be ordered so that subprojets only depend on those listed
+# earlier. Here is an example:
+#
+#  MCPPBS_GROUP( [group-name], [sproja,sprojb,...] )
+#
+
+#-------------------------------------------------------------------------
+# Output
+#-------------------------------------------------------------------------
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([riscv-spike.pc])
+AC_CONFIG_FILES([riscv-riscv.pc])
+AC_CONFIG_FILES([riscv-softfloat.pc])
+AC_CONFIG_FILES([riscv-dummy_rocc.pc])
+AC_CONFIG_FILES([riscv-spike_main.pc])
+AC_OUTPUT
diff --git a/tb/riscv-isa-sim/debug_rom/.gitignore b/tb/riscv-isa-sim/debug_rom/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..98bd13e4dd46718c20555faee5827b53011c23cd
--- /dev/null
+++ b/tb/riscv-isa-sim/debug_rom/.gitignore
@@ -0,0 +1,5 @@
+/debug_rom
+/debug_rom32
+/debug_rom64
+/debug_rom32.h
+/debug_rom64.h
diff --git a/tb/riscv-isa-sim/debug_rom/Makefile b/tb/riscv-isa-sim/debug_rom/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c5f2205de3bbf38baba4d600342f2277d409d098
--- /dev/null
+++ b/tb/riscv-isa-sim/debug_rom/Makefile
@@ -0,0 +1,24 @@
+# Recursive make is bad, but in this case we're cross compiling which is a
+# pretty unusual use case.
+
+CC = $(RISCV)/bin/riscv64-unknown-elf-gcc
+OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy
+
+COMPILE = $(CC) -nostdlib -nostartfiles -I.. -Tlink.ld
+
+ELFS = debug_rom
+DEPS = debug_rom.S link.ld ../riscv/debug_rom_defines.h ../riscv/encoding.h
+
+all: $(patsubst %,%.h,$(ELFS))
+
+%.h:	%.raw
+	xxd -i $^ | sed "s/^unsigned/static const unsigned/" > $@
+
+%.raw:	%
+	$(OBJCOPY) -O binary --only-section .text $^ $@
+
+debug_rom:	$(DEPS)
+	$(COMPILE) -o $@ $^
+
+clean:
+	rm -f $(ELFS) debug_rom*.raw debug_rom.h
diff --git a/tb/riscv-isa-sim/debug_rom/debug_rom.S b/tb/riscv-isa-sim/debug_rom/debug_rom.S
new file mode 100755
index 0000000000000000000000000000000000000000..28c7076fda5c17dc2f46d1cf2fead993ba92b6f5
--- /dev/null
+++ b/tb/riscv-isa-sim/debug_rom/debug_rom.S
@@ -0,0 +1,72 @@
+// See LICENSE.SiFive for license details.
+
+#include "riscv/encoding.h"
+#include "riscv/debug_rom_defines.h"
+
+        .option norvc
+        .global entry
+        .global exception
+
+        // Entry location on ebreak, Halt, or Breakpoint
+        // It is the same for all harts. They branch when 
+        // their GO or RESUME bit is set.
+
+entry:
+       jal zero, _entry
+resume:
+       jal zero, _resume
+exception:
+       jal zero, _exception
+
+_entry:
+        // This fence is required because the execution may have written something
+        // into the Abstract Data or Program Buffer registers.
+        fence
+        csrw CSR_DSCRATCH, s0  // Save s0 to allow signaling MHARTID
+
+        // We continue to let the hart know that we are halted in order that
+        // a DM which was reset is still made aware that a hart is halted.
+        // We keep checking both whether there is something the debugger wants
+        // us to do, or whether we should resume.
+entry_loop:
+        csrr s0, CSR_MHARTID
+        sw   s0, DEBUG_ROM_HALTED(zero)
+        lbu  s0, DEBUG_ROM_FLAGS(s0) // 1 byte flag per hart. Only one hart advances here.
+        andi s0, s0, (1 << DEBUG_ROM_FLAG_GO)
+        bnez s0, going
+        csrr s0, CSR_MHARTID
+        lbu  s0, DEBUG_ROM_FLAGS(s0) // multiple harts can resume  here
+        andi s0, s0, (1 << DEBUG_ROM_FLAG_RESUME)
+        bnez s0, resume
+        jal  zero, entry_loop
+
+_exception:
+        sw      zero, DEBUG_ROM_EXCEPTION(zero) // Let debug module know you got an exception.
+        ebreak
+
+going:
+        csrr s0, CSR_DSCRATCH            // Restore s0 here
+        sw zero, DEBUG_ROM_GOING(zero)   // When debug module sees this write, the GO flag is reset.
+        fence
+        fence.i
+        jalr zero, zero, %lo(whereto)    // Debug module will put different instructions and data in the RAM, 
+                                         // so we use fence and fence.i for safety. (rocket-chip doesn't have this
+                                         // because jalr is special there)
+
+_resume:
+        csrr s0, CSR_MHARTID
+        sw   s0, DEBUG_ROM_RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
+        csrr s0, CSR_DSCRATCH   // Restore s0
+        dret
+
+        // END OF ACTUAL "ROM" CONTENTS. BELOW IS JUST FOR LINKER SCRIPT.
+
+.section .whereto
+whereto:
+        nop
+        // Variable "ROM" This is : jal x0 abstract, jal x0 program_buffer,
+        //                or jal x0 resume, as desired.
+        //                Debug Module state machine tracks what is 'desired'.
+        //                We don't need/want to use jalr here because all of the
+        //                Variable ROM contents are set by
+        //                Debug Module before setting the OK_GO byte.
diff --git a/tb/riscv-isa-sim/debug_rom/debug_rom.h b/tb/riscv-isa-sim/debug_rom/debug_rom.h
new file mode 100644
index 0000000000000000000000000000000000000000..d21e1669c715213b087f0a80ec270051bbe29f96
--- /dev/null
+++ b/tb/riscv-isa-sim/debug_rom/debug_rom.h
@@ -0,0 +1,12 @@
+static const unsigned char debug_rom_raw[] = {
+  0x6f, 0x00, 0xc0, 0x00, 0x6f, 0x00, 0x40, 0x05, 0x6f, 0x00, 0x40, 0x03,
+  0x0f, 0x00, 0xf0, 0x0f, 0x73, 0x10, 0x24, 0x7b, 0x73, 0x24, 0x40, 0xf1,
+  0x23, 0x20, 0x80, 0x10, 0x03, 0x44, 0x04, 0x40, 0x13, 0x74, 0x14, 0x00,
+  0x63, 0x10, 0x04, 0x02, 0x73, 0x24, 0x40, 0xf1, 0x03, 0x44, 0x04, 0x40,
+  0x13, 0x74, 0x24, 0x00, 0xe3, 0x18, 0x04, 0xfc, 0x6f, 0xf0, 0xdf, 0xfd,
+  0x23, 0x26, 0x00, 0x10, 0x73, 0x00, 0x10, 0x00, 0x73, 0x24, 0x20, 0x7b,
+  0x23, 0x22, 0x00, 0x10, 0x0f, 0x00, 0xf0, 0x0f, 0x0f, 0x10, 0x00, 0x00,
+  0x67, 0x00, 0x00, 0x30, 0x73, 0x24, 0x40, 0xf1, 0x23, 0x24, 0x80, 0x10,
+  0x73, 0x24, 0x20, 0x7b, 0x73, 0x00, 0x20, 0x7b
+};
+static const unsigned int debug_rom_raw_len = 104;
diff --git a/tb/riscv-isa-sim/debug_rom/link.ld b/tb/riscv-isa-sim/debug_rom/link.ld
new file mode 100644
index 0000000000000000000000000000000000000000..897c42da001d1009bceb3bee32a83b7693d019cd
--- /dev/null
+++ b/tb/riscv-isa-sim/debug_rom/link.ld
@@ -0,0 +1,15 @@
+OUTPUT_ARCH( "riscv" )
+ENTRY( entry )
+SECTIONS
+{
+    .whereto 0x300 :
+    {
+        *(.whereto)
+    }   
+    . = 0x800;
+    .text :
+    {
+        *(.text)
+    }
+    _end = .;
+}
diff --git a/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.ac b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.ac
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.cc b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.cc
new file mode 100644
index 0000000000000000000000000000000000000000..85ab7aa6946ed8b6d6813632632602108f5b88e4
--- /dev/null
+++ b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.cc
@@ -0,0 +1,47 @@
+#include "rocc.h"
+#include "mmu.h"
+#include <cstring>
+
+class dummy_rocc_t : public rocc_t
+{
+ public:
+  const char* name() { return "dummy_rocc"; }
+
+  reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2)
+  {
+    reg_t prev_acc = acc[insn.rs2];
+
+    if (insn.rs2 >= num_acc)
+      illegal_instruction();
+
+    switch (insn.funct)
+    {
+      case 0: // acc <- xs1
+        acc[insn.rs2] = xs1;
+        break;
+      case 1: // xd <- acc (the only real work is the return statement below)
+        break;
+      case 2: // acc[rs2] <- Mem[xs1]
+        acc[insn.rs2] = p->get_mmu()->load_uint64(xs1);
+        break;
+      case 3: // acc[rs2] <- accX + xs1
+        acc[insn.rs2] += xs1;
+        break;
+      default:
+        illegal_instruction();
+    }
+
+    return prev_acc; // in all cases, xd <- previous value of acc[rs2]
+  }
+
+  dummy_rocc_t()
+  {
+    memset(acc, 0, sizeof(acc));
+  }
+
+ private:
+  static const int num_acc = 4;
+  reg_t acc[num_acc];
+};
+
+REGISTER_EXTENSION(dummy_rocc, []() { return new dummy_rocc_t; })
diff --git a/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.mk.in b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.mk.in
new file mode 100644
index 0000000000000000000000000000000000000000..0143ffd1c35c8c78455a56fc93bcc1eef662cc32
--- /dev/null
+++ b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc.mk.in
@@ -0,0 +1,7 @@
+dummy_rocc_subproject_deps = \
+	spike_main \
+	riscv \
+	softfloat \
+
+dummy_rocc_srcs = \
+	dummy_rocc.cc \
diff --git a/tb/riscv-isa-sim/dummy_rocc/dummy_rocc_test.c b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..94de8c041e77e615c1d1ff7f433db5af14421753
--- /dev/null
+++ b/tb/riscv-isa-sim/dummy_rocc/dummy_rocc_test.c
@@ -0,0 +1,29 @@
+// The following is a RISC-V program to test the functionality of the
+// dummy RoCC accelerator.
+// Compile with riscv64-unknown-elf-gcc dummy_rocc_test.c
+// Run with spike --extension=dummy_rocc pk a.out
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+
+int main() {
+  uint64_t x = 123, y = 456, z = 0;
+  // load x into accumulator 2 (funct=0)
+  asm volatile ("custom0 x0, %0, 2, 0" : : "r"(x));
+  // read it back into z (funct=1) to verify it
+  asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z));
+  assert(z == x);
+  // accumulate 456 into it (funct=3)
+  asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y));
+  // verify it
+  asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z));
+  assert(z == x+y);
+  // do it all again, but initialize acc2 via memory this time (funct=2)
+  asm volatile ("custom0 x0, %0, 2, 2" : : "r"(&x));
+  asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y));
+  asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z));
+  assert(z == x+y);
+
+  printf("success!\n");
+}
diff --git a/tb/riscv-isa-sim/riscv-dummy_rocc.pc.in b/tb/riscv-isa-sim/riscv-dummy_rocc.pc.in
new file mode 100644
index 0000000000000000000000000000000000000000..31635f6dadbad755e035fbabd48e1b9dfc295dfb
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv-dummy_rocc.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@prefix@
+libdir=${prefix}/@libdir@
+includedir=${prefix}/@includedir@
+
+Name: riscv-dummy_rocc
+Description: Example RISC-V ROCC accelerator
+Version: git
+Libs: -Wl,-rpath,${libdir} -L${libdir} -ldummy_rocc
+Cflags: -I${includedir}
+URL: http://riscv.org/download.html#tab_spike
diff --git a/tb/riscv-isa-sim/riscv-riscv.pc.in b/tb/riscv-isa-sim/riscv-riscv.pc.in
new file mode 100644
index 0000000000000000000000000000000000000000..5e86b1c448a4a34d79622269eb6b2220a81a1cf5
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv-riscv.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@prefix@
+libdir=${prefix}/@libdir@
+includedir=${prefix}/@includedir@
+
+Name: riscv-riscv
+Description: RISC-V 
+Version: git
+Libs: -Wl,-rpath,${libdir} -L${libdir} -lriscv
+Cflags: -I${includedir}
+URL: http://riscv.org/download.html#tab_spike
diff --git a/tb/riscv-isa-sim/riscv-softfloat.pc.in b/tb/riscv-isa-sim/riscv-softfloat.pc.in
new file mode 100644
index 0000000000000000000000000000000000000000..6b18e884417a13a9429e0eb2b999ebec56e9f44f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv-softfloat.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@prefix@
+libdir=${prefix}/@libdir@
+includedir=${prefix}/@includedir@
+
+Name: riscv-softfloat
+Description: RISC-V softfloat library
+Version: git
+Libs: -Wl,-rpath,${libdir} -L${libdir} -lsoftfloat
+Cflags: -I${includedir}
+URL: http://riscv.org/download.html#tab_spike
diff --git a/tb/riscv-isa-sim/riscv-spike.pc.in b/tb/riscv-isa-sim/riscv-spike.pc.in
new file mode 100644
index 0000000000000000000000000000000000000000..007ad392bdb67ed1f3132ef6a882c544c12a9b4c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv-spike.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@prefix@
+libdir=${prefix}/@libdir@
+includedir=${prefix}/@includedir@
+
+Name: riscv-spike
+Description: RISC-V spike meta library
+Version: git
+Depends: riscv-spike_main riscv-riscv riscv-softfloat
+URL: http://riscv.org/download.html#tab_spike
diff --git a/tb/riscv-isa-sim/riscv-spike_main.pc.in b/tb/riscv-isa-sim/riscv-spike_main.pc.in
new file mode 100644
index 0000000000000000000000000000000000000000..c9b0eccca8c52e01bac9a365aa16725726eda0fb
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv-spike_main.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@prefix@
+libdir=${prefix}/@libdir@
+includedir=${prefix}/@includedir@
+
+Name: riscv-spike_main
+Description: RISC-V ISA simulator library
+Version: git
+Depends: riscv-riscv riscv-softfloat
+Libs: -Wl,-rpath,${libdir} -L${libdir} -lspike_main
+Cflags: -I${includedir}
+URL: http://riscv.org/download.html#tab_spike
diff --git a/tb/riscv-isa-sim/riscv/bootrom.h b/tb/riscv-isa-sim/riscv/bootrom.h
new file mode 120000
index 0000000000000000000000000000000000000000..5f554fe84dbf5e86c9ad4029b014d2693e6bf50c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/bootrom.h
@@ -0,0 +1 @@
+../../../bootrom/bootrom.h
\ No newline at end of file
diff --git a/tb/riscv-isa-sim/riscv/cachesim.cc b/tb/riscv-isa-sim/riscv/cachesim.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6e030d13eb490b83b4a6d4a4f31bbf6789e6f873
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/cachesim.cc
@@ -0,0 +1,185 @@
+// See LICENSE for license details.
+
+#include "cachesim.h"
+#include "common.h"
+#include <cstdlib>
+#include <iostream>
+#include <iomanip>
+
+cache_sim_t::cache_sim_t(size_t _sets, size_t _ways, size_t _linesz, const char* _name)
+: sets(_sets), ways(_ways), linesz(_linesz), name(_name), log(false)
+{
+  init();
+}
+
+static void help()
+{
+  std::cerr << "Cache configurations must be of the form" << std::endl;
+  std::cerr << "  sets:ways:blocksize" << std::endl;
+  std::cerr << "where sets, ways, and blocksize are positive integers, with" << std::endl;
+  std::cerr << "sets and blocksize both powers of two and blocksize at least 8." << std::endl;
+  exit(1);
+}
+
+cache_sim_t* cache_sim_t::construct(const char* config, const char* name)
+{
+  const char* wp = strchr(config, ':');
+  if (!wp++) help();
+  const char* bp = strchr(wp, ':');
+  if (!bp++) help();
+
+  size_t sets = atoi(std::string(config, wp).c_str());
+  size_t ways = atoi(std::string(wp, bp).c_str());
+  size_t linesz = atoi(bp);
+
+  if (ways > 4 /* empirical */ && sets == 1)
+    return new fa_cache_sim_t(ways, linesz, name);
+  return new cache_sim_t(sets, ways, linesz, name);
+}
+
+void cache_sim_t::init()
+{
+  if(sets == 0 || (sets & (sets-1)))
+    help();
+  if(linesz < 8 || (linesz & (linesz-1)))
+    help();
+
+  idx_shift = 0;
+  for (size_t x = linesz; x>1; x >>= 1)
+    idx_shift++;
+
+  tags = new uint64_t[sets*ways]();
+  read_accesses = 0;
+  read_misses = 0;
+  bytes_read = 0;
+  write_accesses = 0;
+  write_misses = 0;
+  bytes_written = 0;
+  writebacks = 0;
+
+  miss_handler = NULL;
+}
+
+cache_sim_t::cache_sim_t(const cache_sim_t& rhs)
+ : sets(rhs.sets), ways(rhs.ways), linesz(rhs.linesz),
+   idx_shift(rhs.idx_shift), name(rhs.name), log(false)
+{
+  tags = new uint64_t[sets*ways];
+  memcpy(tags, rhs.tags, sets*ways*sizeof(uint64_t));
+}
+
+cache_sim_t::~cache_sim_t()
+{
+  print_stats();
+  delete [] tags;
+}
+
+void cache_sim_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;
+}
+
+uint64_t* cache_sim_t::check_tag(uint64_t addr)
+{
+  size_t idx = (addr >> idx_shift) & (sets-1);
+  size_t tag = (addr >> idx_shift) | VALID;
+
+  for (size_t i = 0; i < ways; i++)
+    if (tag == (tags[idx*ways + i] & ~DIRTY))
+      return &tags[idx*ways + i];
+
+  return NULL;
+}
+
+uint64_t cache_sim_t::victimize(uint64_t addr)
+{
+  size_t idx = (addr >> idx_shift) & (sets-1);
+  size_t way = lfsr.next() % ways;
+  uint64_t victim = tags[idx*ways + way];
+  tags[idx*ways + way] = (addr >> idx_shift) | VALID;
+  return victim;
+}
+
+void cache_sim_t::access(uint64_t addr, size_t bytes, bool store)
+{
+  store ? write_accesses++ : read_accesses++;
+  (store ? bytes_written : bytes_read) += bytes;
+
+  uint64_t* hit_way = check_tag(addr);
+  if (likely(hit_way != NULL))
+  {
+    if (store)
+      *hit_way |= DIRTY;
+    return;
+  }
+
+  store ? write_misses++ : read_misses++;
+  if (log)
+  {
+    std::cerr << name << " "
+              << (store ? "write" : "read") << " miss 0x"
+              << std::hex << addr << std::endl;
+  }
+
+  uint64_t victim = victimize(addr);
+
+  if ((victim & (VALID | DIRTY)) == (VALID | DIRTY))
+  {
+    uint64_t dirty_addr = (victim & ~(VALID | DIRTY)) << idx_shift;
+    if (miss_handler)
+      miss_handler->access(dirty_addr, linesz, true);
+    writebacks++;
+  }
+
+  if (miss_handler)
+    miss_handler->access(addr & ~(linesz-1), linesz, false);
+
+  if (store)
+    *check_tag(addr) |= DIRTY;
+}
+
+fa_cache_sim_t::fa_cache_sim_t(size_t ways, size_t linesz, const char* name)
+  : cache_sim_t(1, ways, linesz, name)
+{
+}
+
+uint64_t* fa_cache_sim_t::check_tag(uint64_t addr)
+{
+  auto it = tags.find(addr >> idx_shift);
+  return it == tags.end() ? NULL : &it->second;
+}
+
+uint64_t fa_cache_sim_t::victimize(uint64_t addr)
+{
+  uint64_t old_tag = 0;
+  if (tags.size() == ways)
+  {
+    auto it = tags.begin();
+    std::advance(it, lfsr.next() % ways);
+    old_tag = it->second;
+    tags.erase(it);
+  }
+  tags[addr >> idx_shift] = (addr >> idx_shift) | VALID;
+  return old_tag;
+}
diff --git a/tb/riscv-isa-sim/riscv/cachesim.h b/tb/riscv-isa-sim/riscv/cachesim.h
new file mode 100644
index 0000000000000000000000000000000000000000..259725acfcf7c21902e3502f15a3bb47d5f48191
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/cachesim.h
@@ -0,0 +1,130 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_CACHE_SIM_H
+#define _RISCV_CACHE_SIM_H
+
+#include "memtracer.h"
+#include <cstring>
+#include <string>
+#include <map>
+#include <cstdint>
+
+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 cache_sim_t
+{
+ public:
+  cache_sim_t(size_t sets, size_t ways, size_t linesz, const char* name);
+  cache_sim_t(const cache_sim_t& rhs);
+  virtual ~cache_sim_t();
+
+  void access(uint64_t addr, size_t bytes, bool store);
+  void print_stats();
+  void set_miss_handler(cache_sim_t* mh) { miss_handler = mh; }
+  void set_log(bool _log) { log = _log; }
+
+  static cache_sim_t* construct(const char* config, const char* name);
+
+ protected:
+  static const uint64_t VALID = 1ULL << 63;
+  static const uint64_t DIRTY = 1ULL << 62;
+
+  virtual uint64_t* check_tag(uint64_t addr);
+  virtual uint64_t victimize(uint64_t addr);
+
+  lfsr_t lfsr;
+  cache_sim_t* miss_handler;
+
+  size_t sets;
+  size_t ways;
+  size_t linesz;
+  size_t idx_shift;
+
+  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;
+  bool log;
+
+  void init();
+};
+
+class fa_cache_sim_t : public cache_sim_t
+{
+ public:
+  fa_cache_sim_t(size_t ways, size_t linesz, const char* name);
+  uint64_t* check_tag(uint64_t addr);
+  uint64_t victimize(uint64_t addr);
+ private:
+  static bool cmp(uint64_t a, uint64_t b);
+  std::map<uint64_t, uint64_t> tags;
+};
+
+class cache_memtracer_t : public memtracer_t
+{
+ public:
+  cache_memtracer_t(const char* config, const char* name)
+  {
+    cache = cache_sim_t::construct(config, name);
+  }
+  ~cache_memtracer_t()
+  {
+    delete cache;
+  }
+  void set_miss_handler(cache_sim_t* mh)
+  {
+    cache->set_miss_handler(mh);
+  }
+  void set_log(bool log)
+  {
+    cache->set_log(log);
+  }
+
+ protected:
+  cache_sim_t* cache;
+};
+
+class icache_sim_t : public cache_memtracer_t
+{
+ public:
+  icache_sim_t(const char* config) : cache_memtracer_t(config, "I$") {}
+  bool interested_in_range(uint64_t begin, uint64_t end, access_type type)
+  {
+    return type == FETCH;
+  }
+  void trace(uint64_t addr, size_t bytes, access_type type)
+  {
+    if (type == FETCH) cache->access(addr, bytes, false);
+  }
+};
+
+class dcache_sim_t : public cache_memtracer_t
+{
+ public:
+  dcache_sim_t(const char* config) : cache_memtracer_t(config, "D$") {}
+  bool interested_in_range(uint64_t begin, uint64_t end, access_type type)
+  {
+    return type == LOAD || type == STORE;
+  }
+  void trace(uint64_t addr, size_t bytes, access_type type)
+  {
+    if (type == LOAD || type == STORE) cache->access(addr, bytes, type == STORE);
+  }
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/clint.cc b/tb/riscv-isa-sim/riscv/clint.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8494845241d0fd6b86b6cfb62cf5d9daf1b1adc6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/clint.cc
@@ -0,0 +1,76 @@
+#include "devices.h"
+#include "processor.h"
+
+clint_t::clint_t(std::vector<processor_t*>& procs)
+  : procs(procs), mtimecmp(procs.size())
+{
+}
+
+/* 0000 msip hart 0
+ * 0004 msip hart 1
+ * 4000 mtimecmp hart 0 lo
+ * 4004 mtimecmp hart 0 hi
+ * 4008 mtimecmp hart 1 lo
+ * 400c mtimecmp hart 1 hi
+ * bff8 mtime lo
+ * bffc mtime hi
+ */
+
+#define MSIP_BASE	0x0
+#define MTIMECMP_BASE	0x4000
+#define MTIME_BASE	0xbff8
+
+void clint_t::reset() {
+  mtime = 0;
+}
+
+bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
+    std::vector<msip_t> msip(procs.size());
+    for (size_t i = 0; i < procs.size(); ++i)
+      msip[i] = !!(procs[i]->state.mip & MIP_MSIP);
+    memcpy(bytes, (uint8_t*)&msip[0] + addr - MSIP_BASE, len);
+  } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
+    memcpy(bytes, (uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, len);
+  } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
+    memcpy(bytes, (uint8_t*)&mtime + addr - MTIME_BASE, len);
+  } else {
+    return false;
+  }
+  return true;
+}
+
+bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
+    std::vector<msip_t> msip(procs.size());
+    std::vector<msip_t> mask(procs.size(), 0);
+    memcpy((uint8_t*)&msip[0] + addr - MSIP_BASE, bytes, len);
+    memset((uint8_t*)&mask[0] + addr - MSIP_BASE, 0xff, len);
+    for (size_t i = 0; i < procs.size(); ++i) {
+      if (!(mask[i] & 0xFF)) continue;
+      procs[i]->state.mip &= ~MIP_MSIP;
+      if (!!(msip[i] & 1))
+        procs[i]->state.mip |= MIP_MSIP;
+    }
+  } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
+    memcpy((uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, bytes, len);
+  } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
+    memcpy((uint8_t*)&mtime + addr - MTIME_BASE, bytes, len);
+  } else {
+    return false;
+  }
+  increment(0);
+  return true;
+}
+
+void clint_t::increment(reg_t inc)
+{
+  mtime += inc;
+  for (size_t i = 0; i < procs.size(); i++) {
+    procs[i]->state.mip &= ~MIP_MTIP;
+    if (mtime >= mtimecmp[i])
+      procs[i]->state.mip |= MIP_MTIP;
+  }
+}
diff --git a/tb/riscv-isa-sim/riscv/common.h b/tb/riscv-isa-sim/riscv/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ddd9849d83c887647c1a46b39d86d11514726a8
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/common.h
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_COMMON_H
+#define _RISCV_COMMON_H
+
+#define   likely(x) __builtin_expect(x, 1)
+#define unlikely(x) __builtin_expect(x, 0)
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/debug_defines.h b/tb/riscv-isa-sim/riscv/debug_defines.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6ddd4ff1e6d43a4d3969aa967af32b48cb8dc28
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/debug_defines.h
@@ -0,0 +1,1414 @@
+#define DTM_IDCODE                          0x01
+/*
+* Identifies the release version of this part.
+ */
+#define DTM_IDCODE_VERSION_OFFSET           28
+#define DTM_IDCODE_VERSION_LENGTH           4
+#define DTM_IDCODE_VERSION                  (0xfU << DTM_IDCODE_VERSION_OFFSET)
+/*
+* Identifies the designer's part number of this part.
+ */
+#define DTM_IDCODE_PARTNUMBER_OFFSET        12
+#define DTM_IDCODE_PARTNUMBER_LENGTH        16
+#define DTM_IDCODE_PARTNUMBER               (0xffffU << DTM_IDCODE_PARTNUMBER_OFFSET)
+/*
+* Identifies the designer/manufacturer of this part. Bits 6:0 must be
+* bits 6:0 of the designer/manufacturer's Identification Code as
+* assigned by JEDEC Standard JEP106. Bits 10:7 contain the modulo-16
+* count of the number of continuation characters (0x7f) in that same
+* Identification Code.
+ */
+#define DTM_IDCODE_MANUFID_OFFSET           1
+#define DTM_IDCODE_MANUFID_LENGTH           11
+#define DTM_IDCODE_MANUFID                  (0x7ffU << DTM_IDCODE_MANUFID_OFFSET)
+#define DTM_IDCODE_1_OFFSET                 0
+#define DTM_IDCODE_1_LENGTH                 1
+#define DTM_IDCODE_1                        (0x1U << DTM_IDCODE_1_OFFSET)
+#define DTM_DTMCS                           0x10
+/*
+* Writing 1 to this bit does a hard reset of the DTM,
+* causing the DTM to forget about any outstanding DMI transactions.
+* In general this should only be used when the Debugger has
+* reason to expect that the outstanding DMI transaction will never
+* complete (e.g. a reset condition caused an inflight DMI transaction to
+* be cancelled).
+ */
+#define DTM_DTMCS_DMIHARDRESET_OFFSET       17
+#define DTM_DTMCS_DMIHARDRESET_LENGTH       1
+#define DTM_DTMCS_DMIHARDRESET              (0x1U << DTM_DTMCS_DMIHARDRESET_OFFSET)
+/*
+* Writing 1 to this bit clears the sticky error state
+* and allows the DTM to retry or complete the previous
+* transaction.
+ */
+#define DTM_DTMCS_DMIRESET_OFFSET           16
+#define DTM_DTMCS_DMIRESET_LENGTH           1
+#define DTM_DTMCS_DMIRESET                  (0x1U << DTM_DTMCS_DMIRESET_OFFSET)
+/*
+* This is a hint to the debugger of the minimum number of
+* cycles a debugger should spend in
+* Run-Test/Idle after every DMI scan to avoid a `busy'
+* return code (\Fdmistat of 3). A debugger must still
+* check \Fdmistat when necessary.
+*
+* 0: It is not necessary to enter Run-Test/Idle at all.
+*
+* 1: Enter Run-Test/Idle and leave it immediately.
+*
+* 2: Enter Run-Test/Idle and stay there for 1 cycle before leaving.
+*
+* And so on.
+ */
+#define DTM_DTMCS_IDLE_OFFSET               12
+#define DTM_DTMCS_IDLE_LENGTH               3
+#define DTM_DTMCS_IDLE                      (0x7U << DTM_DTMCS_IDLE_OFFSET)
+/*
+* 0: No error.
+*
+* 1: Reserved. Interpret the same as 2.
+*
+* 2: An operation failed (resulted in \Fop of 2).
+*
+* 3: An operation was attempted while a DMI access was still in
+* progress (resulted in \Fop of 3).
+ */
+#define DTM_DTMCS_DMISTAT_OFFSET            10
+#define DTM_DTMCS_DMISTAT_LENGTH            2
+#define DTM_DTMCS_DMISTAT                   (0x3U << DTM_DTMCS_DMISTAT_OFFSET)
+/*
+* The size of \Faddress in \Rdmi.
+ */
+#define DTM_DTMCS_ABITS_OFFSET              4
+#define DTM_DTMCS_ABITS_LENGTH              6
+#define DTM_DTMCS_ABITS                     (0x3fU << DTM_DTMCS_ABITS_OFFSET)
+/*
+* 0: Version described in spec version 0.11.
+*
+* 1: Version described in spec version 0.13 (and later?), which
+* reduces the DMI data width to 32 bits.
+*
+* 15: Version not described in any available version of this spec.
+ */
+#define DTM_DTMCS_VERSION_OFFSET            0
+#define DTM_DTMCS_VERSION_LENGTH            4
+#define DTM_DTMCS_VERSION                   (0xfU << DTM_DTMCS_VERSION_OFFSET)
+#define DTM_DMI                             0x11
+/*
+* Address used for DMI access. In Update-DR this value is used
+* to access the DM over the DMI.
+ */
+#define DTM_DMI_ADDRESS_OFFSET              34
+#define DTM_DMI_ADDRESS_LENGTH              abits
+#define DTM_DMI_ADDRESS                     (((1L<<abits)-1) << DTM_DMI_ADDRESS_OFFSET)
+/*
+* The data to send to the DM over the DMI during Update-DR, and
+* the data returned from the DM as a result of the previous operation.
+ */
+#define DTM_DMI_DATA_OFFSET                 2
+#define DTM_DMI_DATA_LENGTH                 32
+#define DTM_DMI_DATA                        (0xffffffffULL << DTM_DMI_DATA_OFFSET)
+/*
+* When the debugger writes this field, it has the following meaning:
+*
+* 0: Ignore \Fdata and \Faddress. (nop)
+*
+* Don't send anything over the DMI during Update-DR.
+* This operation should never result in a busy or error response.
+* The address and data reported in the following Capture-DR
+* are undefined.
+*
+* 1: Read from \Faddress. (read)
+*
+* 2: Write \Fdata to \Faddress. (write)
+*
+* 3: Reserved.
+*
+* When the debugger reads this field, it means the following:
+*
+* 0: The previous operation completed successfully.
+*
+* 1: Reserved.
+*
+* 2: A previous operation failed.  The data scanned into \Rdmi in
+* this access will be ignored.  This status is sticky and can be
+* cleared by writing \Fdmireset in \Rdtmcs.
+*
+* This indicates that the DM itself responded with an error.
+* Note: there are no specified cases in which the DM would
+* respond with an error, and DMI is not required to support
+* returning errors.
+*
+* 3: An operation was attempted while a DMI request is still in
+* progress. The data scanned into \Rdmi in this access will be
+* ignored. This status is sticky and can be cleared by writing
+* \Fdmireset in \Rdtmcs. If a debugger sees this status, it
+* needs to give the target more TCK edges between Update-DR and
+* Capture-DR. The simplest way to do that is to add extra transitions
+* in Run-Test/Idle.
+*
+* (The DTM, DM, and/or component may be in different clock domains,
+* so synchronization may be required. Some relatively fixed number of
+* TCK ticks may be needed for the request to reach the DM, complete,
+* and for the response to be synchronized back into the TCK domain.)
+ */
+#define DTM_DMI_OP_OFFSET                   0
+#define DTM_DMI_OP_LENGTH                   2
+#define DTM_DMI_OP                          (0x3ULL << DTM_DMI_OP_OFFSET)
+#define CSR_DCSR                            0x7b0
+/*
+* 0: There is no external debug support.
+*
+* 4: External debug support exists as it is described in this document.
+*
+* 15: There is external debug support, but it does not conform to any
+* available version of this spec.
+ */
+#define CSR_DCSR_XDEBUGVER_OFFSET           28
+#define CSR_DCSR_XDEBUGVER_LENGTH           4
+#define CSR_DCSR_XDEBUGVER                  (0xfU << CSR_DCSR_XDEBUGVER_OFFSET)
+/*
+* When 1, {\tt ebreak} instructions in Machine Mode enter Debug Mode.
+ */
+#define CSR_DCSR_EBREAKM_OFFSET             15
+#define CSR_DCSR_EBREAKM_LENGTH             1
+#define CSR_DCSR_EBREAKM                    (0x1U << CSR_DCSR_EBREAKM_OFFSET)
+/*
+* When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode.
+ */
+#define CSR_DCSR_EBREAKS_OFFSET             13
+#define CSR_DCSR_EBREAKS_LENGTH             1
+#define CSR_DCSR_EBREAKS                    (0x1U << CSR_DCSR_EBREAKS_OFFSET)
+/*
+* When 1, {\tt ebreak} instructions in User/Application Mode enter
+* Debug Mode.
+ */
+#define CSR_DCSR_EBREAKU_OFFSET             12
+#define CSR_DCSR_EBREAKU_LENGTH             1
+#define CSR_DCSR_EBREAKU                    (0x1U << CSR_DCSR_EBREAKU_OFFSET)
+/*
+* 0: Interrupts are disabled during single stepping.
+*
+* 1: Interrupts are enabled during single stepping.
+*
+* Implementations may hard wire this bit to 0.
+* The debugger must read back the value it
+* writes to check whether the feature is supported. If not
+* supported, interrupt behavior can be emulated by the debugger.
+ */
+#define CSR_DCSR_STEPIE_OFFSET              11
+#define CSR_DCSR_STEPIE_LENGTH              1
+#define CSR_DCSR_STEPIE                     (0x1U << CSR_DCSR_STEPIE_OFFSET)
+/*
+* 0: Increment counters as usual.
+*
+* 1: Don't increment any counters while in Debug Mode or on {\tt
+* ebreak} instructions that cause entry into Debug Mode.  These
+* counters include the {\tt cycle} and {\tt instret} CSRs. This is
+* preferred for most debugging scenarios.
+*
+* An implementation may choose not to support writing to this bit.
+* The debugger must read back the value it writes to check whether
+* the feature is supported.
+ */
+#define CSR_DCSR_STOPCOUNT_OFFSET           10
+#define CSR_DCSR_STOPCOUNT_LENGTH           1
+#define CSR_DCSR_STOPCOUNT                  (0x1U << CSR_DCSR_STOPCOUNT_OFFSET)
+/*
+* 0: Increment timers as usual.
+*
+* 1: Don't increment any hart-local timers while in Debug Mode.
+*
+* An implementation may choose not to support writing to this bit.
+* The debugger must read back the value it writes to check whether
+* the feature is supported.
+ */
+#define CSR_DCSR_STOPTIME_OFFSET            9
+#define CSR_DCSR_STOPTIME_LENGTH            1
+#define CSR_DCSR_STOPTIME                   (0x1U << CSR_DCSR_STOPTIME_OFFSET)
+/*
+* Explains why Debug Mode was entered.
+*
+* When there are multiple reasons to enter Debug Mode in a single
+* cycle, hardware should set \Fcause to the cause with the highest
+* priority.
+*
+* 1: An {\tt ebreak} instruction was executed. (priority 3)
+*
+* 2: The Trigger Module caused a breakpoint exception. (priority 4)
+*
+* 3: The debugger requested entry to Debug Mode. (priority 2)
+*
+* 4: The hart single stepped because \Fstep was set. (priority 1)
+*
+* Other values are reserved for future use.
+ */
+#define CSR_DCSR_CAUSE_OFFSET               6
+#define CSR_DCSR_CAUSE_LENGTH               3
+#define CSR_DCSR_CAUSE                      (0x7U << CSR_DCSR_CAUSE_OFFSET)
+/*
+* When 1, \Fmprv in \Rmstatus takes effect during debug mode.
+* When 0, it is ignored during debug mode.
+* Implementing this bit is optional.
+* If not implemented it should be tied to 0.
+ */
+#define CSR_DCSR_MPRVEN_OFFSET              4
+#define CSR_DCSR_MPRVEN_LENGTH              1
+#define CSR_DCSR_MPRVEN                     (0x1U << CSR_DCSR_MPRVEN_OFFSET)
+/*
+* When set, there is a Non-Maskable-Interrupt (NMI) pending for the hart.
+*
+* Since an NMI can indicate a hardware error condition,
+* reliable debugging may no longer be possible once this bit becomes set.
+* This is implementation-dependent.
+ */
+#define CSR_DCSR_NMIP_OFFSET                3
+#define CSR_DCSR_NMIP_LENGTH                1
+#define CSR_DCSR_NMIP                       (0x1U << CSR_DCSR_NMIP_OFFSET)
+/*
+* When set and not in Debug Mode, the hart will only execute a single
+* instruction and then enter Debug Mode.
+* If the instruction does not complete due to an exception,
+* the hart will immediately enter Debug Mode before executing
+* the trap handler, with appropriate exception registers set.
+ */
+#define CSR_DCSR_STEP_OFFSET                2
+#define CSR_DCSR_STEP_LENGTH                1
+#define CSR_DCSR_STEP                       (0x1U << CSR_DCSR_STEP_OFFSET)
+/*
+* Contains the privilege level the hart was operating in when Debug
+* Mode was entered. The encoding is described in Table
+* \ref{tab:privlevel}.  A debugger can change this value to change
+* the hart's privilege level when exiting Debug Mode.
+*
+* Not all privilege levels are supported on all harts. If the
+* encoding written is not supported or the debugger is not allowed to
+* change to it, the hart may change to any supported privilege level.
+ */
+#define CSR_DCSR_PRV_OFFSET                 0
+#define CSR_DCSR_PRV_LENGTH                 2
+#define CSR_DCSR_PRV                        (0x3U << CSR_DCSR_PRV_OFFSET)
+#define CSR_DPC                             0x7b1
+#define CSR_DPC_DPC_OFFSET                  0
+#define CSR_DPC_DPC_LENGTH                  MXLEN
+#define CSR_DPC_DPC                         (((1L<<MXLEN)-1) << CSR_DPC_DPC_OFFSET)
+#define CSR_DSCRATCH0                       0x7b2
+#define CSR_DSCRATCH1                       0x7b3
+#define CSR_TSELECT                         0x7a0
+#define CSR_TSELECT_INDEX_OFFSET            0
+#define CSR_TSELECT_INDEX_LENGTH            MXLEN
+#define CSR_TSELECT_INDEX                   (((1L<<MXLEN)-1) << CSR_TSELECT_INDEX_OFFSET)
+#define CSR_TDATA1                          0x7a1
+/*
+* 0: There is no trigger at this \Rtselect.
+*
+* 1: The trigger is a legacy SiFive address match trigger. These
+* should not be implemented and aren't further documented here.
+*
+* 2: The trigger is an address/data match trigger. The remaining bits
+* in this register act as described in \Rmcontrol.
+*
+* 3: The trigger is an instruction count trigger. The remaining bits
+* in this register act as described in \Ricount.
+*
+* 4: The trigger is an interrupt trigger. The remaining bits
+* in this register act as described in \Ritrigger.
+*
+* 5: The trigger is an exception trigger. The remaining bits
+* in this register act as described in \Retrigger.
+*
+* 15: This trigger exists (so enumeration shouldn't terminate), but
+* is not currently available.
+*
+* Other values are reserved for future use.
+*
+* When this field is written to an unsupported value, it takes on its
+* reset value instead. The reset value is any one of the types
+* supported by the trigger selected by \Rtselect.
+ */
+#define CSR_TDATA1_TYPE_OFFSET              (MXLEN-4)
+#define CSR_TDATA1_TYPE_LENGTH              4
+#define CSR_TDATA1_TYPE                     (0xfULL << CSR_TDATA1_TYPE_OFFSET)
+/*
+* 0: Both Debug and M Mode can write the {\tt tdata} registers at the
+* selected \Rtselect.
+*
+* 1: Only Debug Mode can write the {\tt tdata} registers at the
+* selected \Rtselect.  Writes from other modes are ignored.
+*
+* This bit is only writable from Debug Mode.
+ */
+#define CSR_TDATA1_DMODE_OFFSET             (MXLEN-5)
+#define CSR_TDATA1_DMODE_LENGTH             1
+#define CSR_TDATA1_DMODE                    (0x1ULL << CSR_TDATA1_DMODE_OFFSET)
+/*
+* Trigger-specific data.
+ */
+#define CSR_TDATA1_DATA_OFFSET              0
+#define CSR_TDATA1_DATA_LENGTH              (MXLEN - 5)
+#define CSR_TDATA1_DATA                     (((1L<<MXLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET)
+#define CSR_TDATA2                          0x7a2
+#define CSR_TDATA2_DATA_OFFSET              0
+#define CSR_TDATA2_DATA_LENGTH              MXLEN
+#define CSR_TDATA2_DATA                     (((1L<<MXLEN)-1) << CSR_TDATA2_DATA_OFFSET)
+#define CSR_TDATA3                          0x7a3
+#define CSR_TDATA3_DATA_OFFSET              0
+#define CSR_TDATA3_DATA_LENGTH              MXLEN
+#define CSR_TDATA3_DATA                     (((1L<<MXLEN)-1) << CSR_TDATA3_DATA_OFFSET)
+#define CSR_TINFO                           0x7a4
+/*
+* One bit for each possible \Ftype enumerated in \Rtdataone. Bit N
+* corresponds to type N. If the bit is set, then that type is
+* supported by the currently selected trigger.
+*
+* If the currently selected trigger doesn't exist, this field
+* contains 1.
+*
+* If \Ftype is not writable, this register may be unimplemented, in
+* which case reading it causes an illegal instruction exception. In
+* this case the debugger can read the only supported type from
+* \Rtdataone.
+ */
+#define CSR_TINFO_INFO_OFFSET               0
+#define CSR_TINFO_INFO_LENGTH               16
+#define CSR_TINFO_INFO                      (0xffffULL << CSR_TINFO_INFO_OFFSET)
+#define CSR_MCONTROL                        0x7a1
+#define CSR_MCONTROL_TYPE_OFFSET            (MXLEN-4)
+#define CSR_MCONTROL_TYPE_LENGTH            4
+#define CSR_MCONTROL_TYPE                   (0xfULL << CSR_MCONTROL_TYPE_OFFSET)
+#define CSR_MCONTROL_DMODE_OFFSET           (MXLEN-5)
+#define CSR_MCONTROL_DMODE_LENGTH           1
+#define CSR_MCONTROL_DMODE                  (0x1ULL << CSR_MCONTROL_DMODE_OFFSET)
+/*
+* Specifies the largest naturally aligned powers-of-two (NAPOT) range
+* supported by the hardware when \Fmatch is 1. The value is the
+* logarithm base 2 of the
+* number of bytes in that range.  A value of 0 indicates that only
+* exact value matches are supported (one byte range). A value of 63
+* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
+* size.
+ */
+#define CSR_MCONTROL_MASKMAX_OFFSET         (MXLEN-11)
+#define CSR_MCONTROL_MASKMAX_LENGTH         6
+#define CSR_MCONTROL_MASKMAX                (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET)
+/*
+* If this optional bit is implemented, the hardware sets it when this
+* trigger matches. The trigger's user can set or clear it at any
+* time. The trigger's user can use this bit to determine which
+* trigger(s) matched.  If the bit is not implemented, it is always 0
+* and writing it has no effect.
+ */
+#define CSR_MCONTROL_HIT_OFFSET             20
+#define CSR_MCONTROL_HIT_LENGTH             1
+#define CSR_MCONTROL_HIT                    (0x1ULL << CSR_MCONTROL_HIT_OFFSET)
+/*
+* 0: Perform a match on the virtual address.
+*
+* 1: Perform a match on the data value loaded/stored, or the
+* instruction executed.
+ */
+#define CSR_MCONTROL_SELECT_OFFSET          19
+#define CSR_MCONTROL_SELECT_LENGTH          1
+#define CSR_MCONTROL_SELECT                 (0x1ULL << CSR_MCONTROL_SELECT_OFFSET)
+/*
+* 0: The action for this trigger will be taken just before the
+* instruction that triggered it is executed, but after all preceding
+* instructions are are committed.
+*
+* 1: The action for this trigger will be taken after the instruction
+* that triggered it is executed. It should be taken before the next
+* instruction is executed, but it is better to implement triggers and
+* not implement that suggestion than to not implement them at all.
+*
+* Most hardware will only implement one timing or the other, possibly
+* dependent on \Fselect, \Fexecute, \Fload, and \Fstore. This bit
+* primarily exists for the hardware to communicate to the debugger
+* what will happen. Hardware may implement the bit fully writable, in
+* which case the debugger has a little more control.
+*
+* Data load triggers with \Ftiming of 0 will result in the same load
+* happening again when the debugger lets the hart run. For data load
+* triggers, debuggers must first attempt to set the breakpoint with
+* \Ftiming of 1.
+*
+* A chain of triggers that don't all have the same \Ftiming value
+* will never fire (unless consecutive instructions match the
+* appropriate triggers).
+ */
+#define CSR_MCONTROL_TIMING_OFFSET          18
+#define CSR_MCONTROL_TIMING_LENGTH          1
+#define CSR_MCONTROL_TIMING                 (0x1ULL << CSR_MCONTROL_TIMING_OFFSET)
+/*
+* The action to take when the trigger fires. The values are explained
+* in Table~\ref{tab:action}.
+ */
+#define CSR_MCONTROL_ACTION_OFFSET          12
+#define CSR_MCONTROL_ACTION_LENGTH          6
+#define CSR_MCONTROL_ACTION                 (0x3fULL << CSR_MCONTROL_ACTION_OFFSET)
+/*
+* 0: When this trigger matches, the configured action is taken.
+*
+* 1: While this trigger does not match, it prevents the trigger with
+* the next index from matching.
+*
+* Because \Fchain affects the next trigger, hardware must zero it in
+* writes to \Rmcontrol that set \Fdmode to 0 if the next trigger has
+* \Fdmode of 1.
+* In addition hardware should ignore writes to \Rmcontrol that set
+* \Fdmode to 1 if the previous trigger has both \Fdmode of 0 and
+* \Fchain of 1. Debuggers must avoid the latter case by checking
+* \Fchain on the previous trigger if they're writing \Rmcontrol.
+*
+* Implementations that wish to limit the maximum length of a trigger
+* chain (eg. to meet timing requirements) may do so by zeroing
+* \Fchain in writes to \Rmcontrol that would make the chain too long.
+ */
+#define CSR_MCONTROL_CHAIN_OFFSET           11
+#define CSR_MCONTROL_CHAIN_LENGTH           1
+#define CSR_MCONTROL_CHAIN                  (0x1ULL << CSR_MCONTROL_CHAIN_OFFSET)
+/*
+* 0: Matches when the value equals \Rtdatatwo.
+*
+* 1: Matches when the top M bits of the value match the top M bits of
+* \Rtdatatwo. M is MXLEN-1 minus the index of the least-significant
+* bit containing 0 in \Rtdatatwo.
+*
+* 2: Matches when the value is greater than (unsigned) or equal to
+* \Rtdatatwo.
+*
+* 3: Matches when the value is less than (unsigned) \Rtdatatwo.
+*
+* 4: Matches when the lower half of the value equals the lower half
+* of \Rtdatatwo after the lower half of the value is ANDed with the
+* upper half of \Rtdatatwo.
+*
+* 5: Matches when the upper half of the value equals the lower half
+* of \Rtdatatwo after the upper half of the value is ANDed with the
+* upper half of \Rtdatatwo.
+*
+* Other values are reserved for future use.
+ */
+#define CSR_MCONTROL_MATCH_OFFSET           7
+#define CSR_MCONTROL_MATCH_LENGTH           4
+#define CSR_MCONTROL_MATCH                  (0xfULL << CSR_MCONTROL_MATCH_OFFSET)
+/*
+* When set, enable this trigger in M mode.
+ */
+#define CSR_MCONTROL_M_OFFSET               6
+#define CSR_MCONTROL_M_LENGTH               1
+#define CSR_MCONTROL_M                      (0x1ULL << CSR_MCONTROL_M_OFFSET)
+/*
+* When set, enable this trigger in S mode.
+ */
+#define CSR_MCONTROL_S_OFFSET               4
+#define CSR_MCONTROL_S_LENGTH               1
+#define CSR_MCONTROL_S                      (0x1ULL << CSR_MCONTROL_S_OFFSET)
+/*
+* When set, enable this trigger in U mode.
+ */
+#define CSR_MCONTROL_U_OFFSET               3
+#define CSR_MCONTROL_U_LENGTH               1
+#define CSR_MCONTROL_U                      (0x1ULL << CSR_MCONTROL_U_OFFSET)
+/*
+* When set, the trigger fires on the virtual address or opcode of an
+* instruction that is executed.
+ */
+#define CSR_MCONTROL_EXECUTE_OFFSET         2
+#define CSR_MCONTROL_EXECUTE_LENGTH         1
+#define CSR_MCONTROL_EXECUTE                (0x1ULL << CSR_MCONTROL_EXECUTE_OFFSET)
+/*
+* When set, the trigger fires on the virtual address or data of a store.
+ */
+#define CSR_MCONTROL_STORE_OFFSET           1
+#define CSR_MCONTROL_STORE_LENGTH           1
+#define CSR_MCONTROL_STORE                  (0x1ULL << CSR_MCONTROL_STORE_OFFSET)
+/*
+* When set, the trigger fires on the virtual address or data of a load.
+ */
+#define CSR_MCONTROL_LOAD_OFFSET            0
+#define CSR_MCONTROL_LOAD_LENGTH            1
+#define CSR_MCONTROL_LOAD                   (0x1ULL << CSR_MCONTROL_LOAD_OFFSET)
+#define CSR_ICOUNT                          0x7a1
+#define CSR_ICOUNT_TYPE_OFFSET              (MXLEN-4)
+#define CSR_ICOUNT_TYPE_LENGTH              4
+#define CSR_ICOUNT_TYPE                     (0xfULL << CSR_ICOUNT_TYPE_OFFSET)
+#define CSR_ICOUNT_DMODE_OFFSET             (MXLEN-5)
+#define CSR_ICOUNT_DMODE_LENGTH             1
+#define CSR_ICOUNT_DMODE                    (0x1ULL << CSR_ICOUNT_DMODE_OFFSET)
+/*
+* If this optional bit is implemented, the hardware sets it when this
+* trigger matches. The trigger's user can set or clear it at any
+* time. The trigger's user can use this bit to determine which
+* trigger(s) matched.  If the bit is not implemented, it is always 0
+* and writing it has no effect.
+ */
+#define CSR_ICOUNT_HIT_OFFSET               24
+#define CSR_ICOUNT_HIT_LENGTH               1
+#define CSR_ICOUNT_HIT                      (0x1ULL << CSR_ICOUNT_HIT_OFFSET)
+/*
+* When count is decremented to 0, the trigger fires. Instead of
+* changing \Fcount from 1 to 0, it is also acceptable for hardware to
+* clear \Fm, \Fs, and \Fu. This allows \Fcount to be hard-wired
+* to 1 if this register just exists for single step.
+ */
+#define CSR_ICOUNT_COUNT_OFFSET             10
+#define CSR_ICOUNT_COUNT_LENGTH             14
+#define CSR_ICOUNT_COUNT                    (0x3fffULL << CSR_ICOUNT_COUNT_OFFSET)
+/*
+* When set, every instruction completed or exception taken in M mode decrements \Fcount
+* by 1.
+ */
+#define CSR_ICOUNT_M_OFFSET                 9
+#define CSR_ICOUNT_M_LENGTH                 1
+#define CSR_ICOUNT_M                        (0x1ULL << CSR_ICOUNT_M_OFFSET)
+/*
+* When set, every instruction completed or exception taken in S mode decrements \Fcount
+* by 1.
+ */
+#define CSR_ICOUNT_S_OFFSET                 7
+#define CSR_ICOUNT_S_LENGTH                 1
+#define CSR_ICOUNT_S                        (0x1ULL << CSR_ICOUNT_S_OFFSET)
+/*
+* When set, every instruction completed or exception taken in U mode decrements \Fcount
+* by 1.
+ */
+#define CSR_ICOUNT_U_OFFSET                 6
+#define CSR_ICOUNT_U_LENGTH                 1
+#define CSR_ICOUNT_U                        (0x1ULL << CSR_ICOUNT_U_OFFSET)
+/*
+* The action to take when the trigger fires. The values are explained
+* in Table~\ref{tab:action}.
+ */
+#define CSR_ICOUNT_ACTION_OFFSET            0
+#define CSR_ICOUNT_ACTION_LENGTH            6
+#define CSR_ICOUNT_ACTION                   (0x3fULL << CSR_ICOUNT_ACTION_OFFSET)
+#define CSR_ITRIGGER                        0x7a1
+#define CSR_ITRIGGER_TYPE_OFFSET            (MXLEN-4)
+#define CSR_ITRIGGER_TYPE_LENGTH            4
+#define CSR_ITRIGGER_TYPE                   (0xfULL << CSR_ITRIGGER_TYPE_OFFSET)
+#define CSR_ITRIGGER_DMODE_OFFSET           (MXLEN-5)
+#define CSR_ITRIGGER_DMODE_LENGTH           1
+#define CSR_ITRIGGER_DMODE                  (0x1ULL << CSR_ITRIGGER_DMODE_OFFSET)
+/*
+* If this optional bit is implemented, the hardware sets it when this
+* trigger matches. The trigger's user can set or clear it at any
+* time. The trigger's user can use this bit to determine which
+* trigger(s) matched.  If the bit is not implemented, it is always 0
+* and writing it has no effect.
+ */
+#define CSR_ITRIGGER_HIT_OFFSET             (MXLEN-6)
+#define CSR_ITRIGGER_HIT_LENGTH             1
+#define CSR_ITRIGGER_HIT                    (0x1ULL << CSR_ITRIGGER_HIT_OFFSET)
+/*
+* When set, enable this trigger for interrupts that are taken from M
+* mode.
+ */
+#define CSR_ITRIGGER_M_OFFSET               9
+#define CSR_ITRIGGER_M_LENGTH               1
+#define CSR_ITRIGGER_M                      (0x1ULL << CSR_ITRIGGER_M_OFFSET)
+/*
+* When set, enable this trigger for interrupts that are taken from S
+* mode.
+ */
+#define CSR_ITRIGGER_S_OFFSET               7
+#define CSR_ITRIGGER_S_LENGTH               1
+#define CSR_ITRIGGER_S                      (0x1ULL << CSR_ITRIGGER_S_OFFSET)
+/*
+* When set, enable this trigger for interrupts that are taken from U
+* mode.
+ */
+#define CSR_ITRIGGER_U_OFFSET               6
+#define CSR_ITRIGGER_U_LENGTH               1
+#define CSR_ITRIGGER_U                      (0x1ULL << CSR_ITRIGGER_U_OFFSET)
+/*
+* The action to take when the trigger fires. The values are explained
+* in Table~\ref{tab:action}.
+ */
+#define CSR_ITRIGGER_ACTION_OFFSET          0
+#define CSR_ITRIGGER_ACTION_LENGTH          6
+#define CSR_ITRIGGER_ACTION                 (0x3fULL << CSR_ITRIGGER_ACTION_OFFSET)
+#define CSR_ETRIGGER                        0x7a1
+#define CSR_ETRIGGER_TYPE_OFFSET            (MXLEN-4)
+#define CSR_ETRIGGER_TYPE_LENGTH            4
+#define CSR_ETRIGGER_TYPE                   (0xfULL << CSR_ETRIGGER_TYPE_OFFSET)
+#define CSR_ETRIGGER_DMODE_OFFSET           (MXLEN-5)
+#define CSR_ETRIGGER_DMODE_LENGTH           1
+#define CSR_ETRIGGER_DMODE                  (0x1ULL << CSR_ETRIGGER_DMODE_OFFSET)
+/*
+* If this optional bit is implemented, the hardware sets it when this
+* trigger matches. The trigger's user can set or clear it at any
+* time. The trigger's user can use this bit to determine which
+* trigger(s) matched.  If the bit is not implemented, it is always 0
+* and writing it has no effect.
+ */
+#define CSR_ETRIGGER_HIT_OFFSET             (MXLEN-6)
+#define CSR_ETRIGGER_HIT_LENGTH             1
+#define CSR_ETRIGGER_HIT                    (0x1ULL << CSR_ETRIGGER_HIT_OFFSET)
+/*
+* When set, enable this trigger for exceptions that are taken from M
+* mode.
+ */
+#define CSR_ETRIGGER_M_OFFSET               9
+#define CSR_ETRIGGER_M_LENGTH               1
+#define CSR_ETRIGGER_M                      (0x1ULL << CSR_ETRIGGER_M_OFFSET)
+/*
+* When set, enable this trigger for exceptions that are taken from S
+* mode.
+ */
+#define CSR_ETRIGGER_S_OFFSET               7
+#define CSR_ETRIGGER_S_LENGTH               1
+#define CSR_ETRIGGER_S                      (0x1ULL << CSR_ETRIGGER_S_OFFSET)
+/*
+* When set, enable this trigger for exceptions that are taken from U
+* mode.
+ */
+#define CSR_ETRIGGER_U_OFFSET               6
+#define CSR_ETRIGGER_U_LENGTH               1
+#define CSR_ETRIGGER_U                      (0x1ULL << CSR_ETRIGGER_U_OFFSET)
+/*
+* The action to take when the trigger fires. The values are explained
+* in Table~\ref{tab:action}.
+ */
+#define CSR_ETRIGGER_ACTION_OFFSET          0
+#define CSR_ETRIGGER_ACTION_LENGTH          6
+#define CSR_ETRIGGER_ACTION                 (0x3fULL << CSR_ETRIGGER_ACTION_OFFSET)
+#define DMI_DMSTATUS                        0x11
+/*
+* If 1, then there is an implicit {\tt ebreak} instruction at the
+* non-existent word immediately after the Program Buffer. This saves
+* the debugger from having to write the {\tt ebreak} itself, and
+* allows the Program Buffer to be one word smaller.
+*
+* This must be 1 when \Fprogbufsize is 1.
+ */
+#define DMI_DMSTATUS_IMPEBREAK_OFFSET       22
+#define DMI_DMSTATUS_IMPEBREAK_LENGTH       1
+#define DMI_DMSTATUS_IMPEBREAK              (0x1U << DMI_DMSTATUS_IMPEBREAK_OFFSET)
+/*
+* This field is 1 when all currently selected harts have been reset but the reset has not been acknowledged.
+ */
+#define DMI_DMSTATUS_ALLHAVERESET_OFFSET    19
+#define DMI_DMSTATUS_ALLHAVERESET_LENGTH    1
+#define DMI_DMSTATUS_ALLHAVERESET           (0x1U << DMI_DMSTATUS_ALLHAVERESET_OFFSET)
+/*
+* This field is 1 when any currently selected hart has been reset but the reset has not been acknowledged.
+ */
+#define DMI_DMSTATUS_ANYHAVERESET_OFFSET    18
+#define DMI_DMSTATUS_ANYHAVERESET_LENGTH    1
+#define DMI_DMSTATUS_ANYHAVERESET           (0x1U << DMI_DMSTATUS_ANYHAVERESET_OFFSET)
+/*
+* This field is 1 when all currently selected harts have acknowledged
+* the previous resume request.
+ */
+#define DMI_DMSTATUS_ALLRESUMEACK_OFFSET    17
+#define DMI_DMSTATUS_ALLRESUMEACK_LENGTH    1
+#define DMI_DMSTATUS_ALLRESUMEACK           (0x1U << DMI_DMSTATUS_ALLRESUMEACK_OFFSET)
+/*
+* This field is 1 when any currently selected hart has acknowledged
+* the previous resume request.
+ */
+#define DMI_DMSTATUS_ANYRESUMEACK_OFFSET    16
+#define DMI_DMSTATUS_ANYRESUMEACK_LENGTH    1
+#define DMI_DMSTATUS_ANYRESUMEACK           (0x1U << DMI_DMSTATUS_ANYRESUMEACK_OFFSET)
+/*
+* This field is 1 when all currently selected harts do not exist in this system.
+ */
+#define DMI_DMSTATUS_ALLNONEXISTENT_OFFSET  15
+#define DMI_DMSTATUS_ALLNONEXISTENT_LENGTH  1
+#define DMI_DMSTATUS_ALLNONEXISTENT         (0x1U << DMI_DMSTATUS_ALLNONEXISTENT_OFFSET)
+/*
+* This field is 1 when any currently selected hart does not exist in this system.
+ */
+#define DMI_DMSTATUS_ANYNONEXISTENT_OFFSET  14
+#define DMI_DMSTATUS_ANYNONEXISTENT_LENGTH  1
+#define DMI_DMSTATUS_ANYNONEXISTENT         (0x1U << DMI_DMSTATUS_ANYNONEXISTENT_OFFSET)
+/*
+* This field is 1 when all currently selected harts are unavailable.
+ */
+#define DMI_DMSTATUS_ALLUNAVAIL_OFFSET      13
+#define DMI_DMSTATUS_ALLUNAVAIL_LENGTH      1
+#define DMI_DMSTATUS_ALLUNAVAIL             (0x1U << DMI_DMSTATUS_ALLUNAVAIL_OFFSET)
+/*
+* This field is 1 when any currently selected hart is unavailable.
+ */
+#define DMI_DMSTATUS_ANYUNAVAIL_OFFSET      12
+#define DMI_DMSTATUS_ANYUNAVAIL_LENGTH      1
+#define DMI_DMSTATUS_ANYUNAVAIL             (0x1U << DMI_DMSTATUS_ANYUNAVAIL_OFFSET)
+/*
+* This field is 1 when all currently selected harts are running.
+ */
+#define DMI_DMSTATUS_ALLRUNNING_OFFSET      11
+#define DMI_DMSTATUS_ALLRUNNING_LENGTH      1
+#define DMI_DMSTATUS_ALLRUNNING             (0x1U << DMI_DMSTATUS_ALLRUNNING_OFFSET)
+/*
+* This field is 1 when any currently selected hart is running.
+ */
+#define DMI_DMSTATUS_ANYRUNNING_OFFSET      10
+#define DMI_DMSTATUS_ANYRUNNING_LENGTH      1
+#define DMI_DMSTATUS_ANYRUNNING             (0x1U << DMI_DMSTATUS_ANYRUNNING_OFFSET)
+/*
+* This field is 1 when all currently selected harts are halted.
+ */
+#define DMI_DMSTATUS_ALLHALTED_OFFSET       9
+#define DMI_DMSTATUS_ALLHALTED_LENGTH       1
+#define DMI_DMSTATUS_ALLHALTED              (0x1U << DMI_DMSTATUS_ALLHALTED_OFFSET)
+/*
+* This field is 1 when any currently selected hart is halted.
+ */
+#define DMI_DMSTATUS_ANYHALTED_OFFSET       8
+#define DMI_DMSTATUS_ANYHALTED_LENGTH       1
+#define DMI_DMSTATUS_ANYHALTED              (0x1U << DMI_DMSTATUS_ANYHALTED_OFFSET)
+/*
+* 0 when authentication is required before using the DM.  1 when the
+* authentication check has passed. On components that don't implement
+* authentication, this bit must be preset as 1.
+ */
+#define DMI_DMSTATUS_AUTHENTICATED_OFFSET   7
+#define DMI_DMSTATUS_AUTHENTICATED_LENGTH   1
+#define DMI_DMSTATUS_AUTHENTICATED          (0x1U << DMI_DMSTATUS_AUTHENTICATED_OFFSET)
+/*
+* 0: The authentication module is ready to process the next
+* read/write to \Rauthdata.
+*
+* 1: The authentication module is busy. Accessing \Rauthdata results
+* in unspecified behavior.
+*
+* \Fauthbusy only becomes set in immediate response to an access to
+* \Rauthdata.
+ */
+#define DMI_DMSTATUS_AUTHBUSY_OFFSET        6
+#define DMI_DMSTATUS_AUTHBUSY_LENGTH        1
+#define DMI_DMSTATUS_AUTHBUSY               (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET)
+/*
+* 1 if this Debug Module supports halt-on-reset functionality
+* controllable by the \Fsetresethaltreq and \Fclrresethaltreq bits.
+* 0 otherwise.
+ */
+#define DMI_DMSTATUS_HASRESETHALTREQ_OFFSET 5
+#define DMI_DMSTATUS_HASRESETHALTREQ_LENGTH 1
+#define DMI_DMSTATUS_HASRESETHALTREQ        (0x1U << DMI_DMSTATUS_HASRESETHALTREQ_OFFSET)
+/*
+* 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which
+* is not relevant to the Device Tree.
+*
+* 1: \Rdevtreeaddrzero--\Rdevtreeaddrthree registers hold the address of the
+* Device Tree.
+ */
+#define DMI_DMSTATUS_DEVTREEVALID_OFFSET    4
+#define DMI_DMSTATUS_DEVTREEVALID_LENGTH    1
+#define DMI_DMSTATUS_DEVTREEVALID           (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET)
+/*
+* 0: There is no Debug Module present.
+*
+* 1: There is a Debug Module and it conforms to version 0.11 of this
+* specification.
+*
+* 2: There is a Debug Module and it conforms to version 0.13 of this
+* specification.
+*
+* 15: There is a Debug Module but it does not conform to any
+* available version of this spec.
+ */
+#define DMI_DMSTATUS_VERSION_OFFSET         0
+#define DMI_DMSTATUS_VERSION_LENGTH         4
+#define DMI_DMSTATUS_VERSION                (0xfU << DMI_DMSTATUS_VERSION_OFFSET)
+#define DMI_DMCONTROL                       0x10
+/*
+* Writes the halt request bit for all currently selected harts.
+* When set to 1, each selected hart will halt if it is not currently
+* halted.
+*
+* Writing 1 or 0 has no effect on a hart which is already halted, but
+* the bit must be cleared to 0 before the hart is resumed.
+*
+* Writes apply to the new value of \Fhartsel and \Fhasel.
+ */
+#define DMI_DMCONTROL_HALTREQ_OFFSET        31
+#define DMI_DMCONTROL_HALTREQ_LENGTH        1
+#define DMI_DMCONTROL_HALTREQ               (0x1U << DMI_DMCONTROL_HALTREQ_OFFSET)
+/*
+* Writes the resume request bit for all currently selected harts.
+* When set to 1, each selected hart will resume if it is currently
+* halted.
+*
+* The resume request bit is ignored while the halt request bit is
+* set.
+*
+* Writes apply to the new value of \Fhartsel and \Fhasel.
+ */
+#define DMI_DMCONTROL_RESUMEREQ_OFFSET      30
+#define DMI_DMCONTROL_RESUMEREQ_LENGTH      1
+#define DMI_DMCONTROL_RESUMEREQ             (0x1U << DMI_DMCONTROL_RESUMEREQ_OFFSET)
+/*
+* This optional field writes the reset bit for all the currently
+* selected harts.  To perform a reset the debugger writes 1, and then
+* writes 0 to deassert the reset signal.
+*
+* If this feature is not implemented, the bit always stays 0, so
+* after writing 1 the debugger can read the register back to see if
+* the feature is supported.
+*
+* Writes apply to the new value of \Fhartsel and \Fhasel.
+ */
+#define DMI_DMCONTROL_HARTRESET_OFFSET      29
+#define DMI_DMCONTROL_HARTRESET_LENGTH      1
+#define DMI_DMCONTROL_HARTRESET             (0x1U << DMI_DMCONTROL_HARTRESET_OFFSET)
+/*
+* Writing 1 to this bit clears the {\tt havereset} bits for
+* any selected harts.
+*
+* Writes apply to the new value of \Fhartsel and \Fhasel.
+ */
+#define DMI_DMCONTROL_ACKHAVERESET_OFFSET   28
+#define DMI_DMCONTROL_ACKHAVERESET_LENGTH   1
+#define DMI_DMCONTROL_ACKHAVERESET          (0x1U << DMI_DMCONTROL_ACKHAVERESET_OFFSET)
+/*
+* Selects the  definition of currently selected harts.
+*
+* 0: There is a single currently selected hart, that selected by \Fhartsel.
+*
+* 1: There may be multiple currently selected harts -- that selected by \Fhartsel,
+* plus those selected by the hart array mask register.
+*
+* An implementation which does not implement the hart array mask register
+* must tie this field to 0. A debugger which wishes to use the hart array
+* mask register feature should set this bit and read back to see if the functionality
+* is supported.
+ */
+#define DMI_DMCONTROL_HASEL_OFFSET          26
+#define DMI_DMCONTROL_HASEL_LENGTH          1
+#define DMI_DMCONTROL_HASEL                 (0x1U << DMI_DMCONTROL_HASEL_OFFSET)
+/*
+* The low 10 bits of \Fhartsel: the DM-specific index of the hart to
+* select. This hart is always part of the currently selected harts.
+ */
+#define DMI_DMCONTROL_HARTSELLO_OFFSET      16
+#define DMI_DMCONTROL_HARTSELLO_LENGTH      10
+#define DMI_DMCONTROL_HARTSELLO             (0x3ffU << DMI_DMCONTROL_HARTSELLO_OFFSET)
+/*
+* The high 10 bits of \Fhartsel: the DM-specific index of the hart to
+* select. This hart is always part of the currently selected harts.
+ */
+#define DMI_DMCONTROL_HARTSELHI_OFFSET      6
+#define DMI_DMCONTROL_HARTSELHI_LENGTH      10
+#define DMI_DMCONTROL_HARTSELHI             (0x3ffU << DMI_DMCONTROL_HARTSELHI_OFFSET)
+/*
+* This optional field writes the halt-on-reset request bit for all
+* currently selected harts.
+* When set to 1, each selected hart will halt upon the next deassertion
+* of its reset. The halt-on-reset request bit is not automatically
+* cleared. The debugger must write to \Fclrresethaltreq to clear it.
+*
+* Writes apply to the new value of \Fhartsel and \Fhasel.
+*
+* If \Fhasresethaltreq is 0, this field is not implemented.
+ */
+#define DMI_DMCONTROL_SETRESETHALTREQ_OFFSET 3
+#define DMI_DMCONTROL_SETRESETHALTREQ_LENGTH 1
+#define DMI_DMCONTROL_SETRESETHALTREQ       (0x1U << DMI_DMCONTROL_SETRESETHALTREQ_OFFSET)
+/*
+* This optional field clears the halt-on-reset request bit for all
+* currently selected harts.
+*
+* Writes apply to the new value of \Fhartsel and \Fhasel.
+ */
+#define DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET 2
+#define DMI_DMCONTROL_CLRRESETHALTREQ_LENGTH 1
+#define DMI_DMCONTROL_CLRRESETHALTREQ       (0x1U << DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET)
+/*
+* This bit controls the reset signal from the DM to the rest of the
+* system. The signal should reset every part of the system, including
+* every hart, except for the DM and any logic required to access the
+* DM.
+* To perform a system reset the debugger writes 1,
+* and then writes 0
+* to deassert the reset.
+ */
+#define DMI_DMCONTROL_NDMRESET_OFFSET       1
+#define DMI_DMCONTROL_NDMRESET_LENGTH       1
+#define DMI_DMCONTROL_NDMRESET              (0x1U << DMI_DMCONTROL_NDMRESET_OFFSET)
+/*
+* This bit serves as a reset signal for the Debug Module itself.
+*
+* 0: The module's state, including authentication mechanism,
+* takes its reset values (the \Fdmactive bit is the only bit which can
+* be written to something other than its reset value).
+*
+* 1: The module functions normally.
+*
+* No other mechanism should exist that may result in resetting the
+* Debug Module after power up, including the platform's system reset
+* or Debug Transport reset signals.
+*
+* A debugger may pulse this bit low to get the Debug Module into a
+* known state.
+*
+* Implementations may use this bit to aid debugging, for example by
+* preventing the Debug Module from being power gated while debugging
+* is active.
+ */
+#define DMI_DMCONTROL_DMACTIVE_OFFSET       0
+#define DMI_DMCONTROL_DMACTIVE_LENGTH       1
+#define DMI_DMCONTROL_DMACTIVE              (0x1U << DMI_DMCONTROL_DMACTIVE_OFFSET)
+#define DMI_HARTINFO                        0x12
+/*
+* Number of {\tt dscratch} registers available for the debugger
+* to use during program buffer execution, starting from \Rdscratchzero.
+* The debugger can make no assumptions about the contents of these
+* registers between commands.
+ */
+#define DMI_HARTINFO_NSCRATCH_OFFSET        20
+#define DMI_HARTINFO_NSCRATCH_LENGTH        4
+#define DMI_HARTINFO_NSCRATCH               (0xfU << DMI_HARTINFO_NSCRATCH_OFFSET)
+/*
+* 0: The {\tt data} registers are shadowed in the hart by CSR
+* registers. Each CSR register is MXLEN bits in size, and corresponds
+* to a single argument, per Table~\ref{tab:datareg}.
+*
+* 1: The {\tt data} registers are shadowed in the hart's memory map.
+* Each register takes up 4 bytes in the memory map.
+ */
+#define DMI_HARTINFO_DATAACCESS_OFFSET      16
+#define DMI_HARTINFO_DATAACCESS_LENGTH      1
+#define DMI_HARTINFO_DATAACCESS             (0x1U << DMI_HARTINFO_DATAACCESS_OFFSET)
+/*
+* If \Fdataaccess is 0: Number of CSR registers dedicated to
+* shadowing the {\tt data} registers.
+*
+* If \Fdataaccess is 1: Number of 32-bit words in the memory map
+* dedicated to shadowing the {\tt data} registers.
+*
+* Since there are at most 12 {\tt data} registers, the value in this
+* register must be 12 or smaller.
+ */
+#define DMI_HARTINFO_DATASIZE_OFFSET        12
+#define DMI_HARTINFO_DATASIZE_LENGTH        4
+#define DMI_HARTINFO_DATASIZE               (0xfU << DMI_HARTINFO_DATASIZE_OFFSET)
+/*
+* If \Fdataaccess is 0: The number of the first CSR dedicated to
+* shadowing the {\tt data} registers.
+*
+* If \Fdataaccess is 1: Signed address of RAM where the {\tt data}
+* registers are shadowed, to be used to access relative to \Rzero.
+ */
+#define DMI_HARTINFO_DATAADDR_OFFSET        0
+#define DMI_HARTINFO_DATAADDR_LENGTH        12
+#define DMI_HARTINFO_DATAADDR               (0xfffU << DMI_HARTINFO_DATAADDR_OFFSET)
+#define DMI_HAWINDOWSEL                     0x14
+/*
+* The high bits of this field may be tied to 0, depending on how large
+* the array mask register is.  Eg. on a system with 48 harts only bit 0
+* of this field may actually be writable.
+ */
+#define DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET  0
+#define DMI_HAWINDOWSEL_HAWINDOWSEL_LENGTH  15
+#define DMI_HAWINDOWSEL_HAWINDOWSEL         (0x7fffU << DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET)
+#define DMI_HAWINDOW                        0x15
+#define DMI_HAWINDOW_MASKDATA_OFFSET        0
+#define DMI_HAWINDOW_MASKDATA_LENGTH        32
+#define DMI_HAWINDOW_MASKDATA               (0xffffffffU << DMI_HAWINDOW_MASKDATA_OFFSET)
+#define DMI_ABSTRACTCS                      0x16
+/*
+* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
+ */
+#define DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET   24
+#define DMI_ABSTRACTCS_PROGBUFSIZE_LENGTH   5
+#define DMI_ABSTRACTCS_PROGBUFSIZE          (0x1fU << DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET)
+/*
+* 1: An abstract command is currently being executed.
+*
+* This bit is set as soon as \Rcommand is written, and is
+* not cleared until that command has completed.
+ */
+#define DMI_ABSTRACTCS_BUSY_OFFSET          12
+#define DMI_ABSTRACTCS_BUSY_LENGTH          1
+#define DMI_ABSTRACTCS_BUSY                 (0x1U << DMI_ABSTRACTCS_BUSY_OFFSET)
+/*
+* Gets set if an abstract command fails. The bits in this field remain set until
+* they are cleared by writing 1 to them. No abstract command is
+* started until the value is reset to 0.
+*
+* 0 (none): No error.
+*
+* 1 (busy): An abstract command was executing while \Rcommand,
+* \Rabstractcs, \Rabstractauto was written, or when one
+* of the {\tt data} or {\tt progbuf} registers was read or written.
+*
+* 2 (not supported): The requested command is not supported,
+* regardless of whether the hart is running or not.
+*
+* 3 (exception): An exception occurred while executing the command
+* (eg. while executing the Program Buffer).
+*
+* 4 (halt/resume): The abstract command couldn't execute because the
+* hart wasn't in the required state (running/halted).
+*
+* 7 (other): The command failed for another reason.
+ */
+#define DMI_ABSTRACTCS_CMDERR_OFFSET        8
+#define DMI_ABSTRACTCS_CMDERR_LENGTH        3
+#define DMI_ABSTRACTCS_CMDERR               (0x7U << DMI_ABSTRACTCS_CMDERR_OFFSET)
+/*
+* Number of {\tt data} registers that are implemented as part of the
+* abstract command interface. Valid sizes are 0 - 12.
+ */
+#define DMI_ABSTRACTCS_DATACOUNT_OFFSET     0
+#define DMI_ABSTRACTCS_DATACOUNT_LENGTH     4
+#define DMI_ABSTRACTCS_DATACOUNT            (0xfU << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
+#define DMI_COMMAND                         0x17
+/*
+* The type determines the overall functionality of this
+* abstract command.
+ */
+#define DMI_COMMAND_CMDTYPE_OFFSET          24
+#define DMI_COMMAND_CMDTYPE_LENGTH          8
+#define DMI_COMMAND_CMDTYPE                 (0xffU << DMI_COMMAND_CMDTYPE_OFFSET)
+/*
+* This field is interpreted in a command-specific manner,
+* described for each abstract command.
+ */
+#define DMI_COMMAND_CONTROL_OFFSET          0
+#define DMI_COMMAND_CONTROL_LENGTH          24
+#define DMI_COMMAND_CONTROL                 (0xffffffU << DMI_COMMAND_CONTROL_OFFSET)
+#define DMI_ABSTRACTAUTO                    0x18
+/*
+* When a bit in this field is 1, read or write accesses to the corresponding {\tt progbuf} word
+* cause the command in \Rcommand to be executed again.
+ */
+#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
+#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
+#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF    (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
+/*
+* When a bit in this field is 1, read or write accesses to the corresponding {\tt data} word
+* cause the command in \Rcommand to be executed again.
+ */
+#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
+#define DMI_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 12
+#define DMI_ABSTRACTAUTO_AUTOEXECDATA       (0xfffU << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET)
+#define DMI_DEVTREEADDR0                    0x19
+#define DMI_DEVTREEADDR0_ADDR_OFFSET        0
+#define DMI_DEVTREEADDR0_ADDR_LENGTH        32
+#define DMI_DEVTREEADDR0_ADDR               (0xffffffffU << DMI_DEVTREEADDR0_ADDR_OFFSET)
+#define DMI_DEVTREEADDR1                    0x1a
+#define DMI_DEVTREEADDR2                    0x1b
+#define DMI_DEVTREEADDR3                    0x1c
+#define DMI_NEXTDM                          0x1d
+#define DMI_NEXTDM_ADDR_OFFSET              0
+#define DMI_NEXTDM_ADDR_LENGTH              32
+#define DMI_NEXTDM_ADDR                     (0xffffffffU << DMI_NEXTDM_ADDR_OFFSET)
+#define DMI_DATA0                           0x04
+#define DMI_DATA0_DATA_OFFSET               0
+#define DMI_DATA0_DATA_LENGTH               32
+#define DMI_DATA0_DATA                      (0xffffffffU << DMI_DATA0_DATA_OFFSET)
+#define DMI_DATA11                          0x0f
+#define DMI_PROGBUF0                        0x20
+#define DMI_PROGBUF0_DATA_OFFSET            0
+#define DMI_PROGBUF0_DATA_LENGTH            32
+#define DMI_PROGBUF0_DATA                   (0xffffffffU << DMI_PROGBUF0_DATA_OFFSET)
+#define DMI_PROGBUF15                       0x2f
+#define DMI_AUTHDATA                        0x30
+#define DMI_AUTHDATA_DATA_OFFSET            0
+#define DMI_AUTHDATA_DATA_LENGTH            32
+#define DMI_AUTHDATA_DATA                   (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET)
+#define DMI_HALTSUM0                        0x40
+#define DMI_HALTSUM0_HALTSUM0_OFFSET        0
+#define DMI_HALTSUM0_HALTSUM0_LENGTH        32
+#define DMI_HALTSUM0_HALTSUM0               (0xffffffffU << DMI_HALTSUM0_HALTSUM0_OFFSET)
+#define DMI_HALTSUM1                        0x13
+#define DMI_HALTSUM1_HALTSUM1_OFFSET        0
+#define DMI_HALTSUM1_HALTSUM1_LENGTH        32
+#define DMI_HALTSUM1_HALTSUM1               (0xffffffffU << DMI_HALTSUM1_HALTSUM1_OFFSET)
+#define DMI_HALTSUM2                        0x34
+#define DMI_HALTSUM2_HALTSUM2_OFFSET        0
+#define DMI_HALTSUM2_HALTSUM2_LENGTH        32
+#define DMI_HALTSUM2_HALTSUM2               (0xffffffffU << DMI_HALTSUM2_HALTSUM2_OFFSET)
+#define DMI_HALTSUM3                        0x35
+#define DMI_HALTSUM3_HALTSUM3_OFFSET        0
+#define DMI_HALTSUM3_HALTSUM3_LENGTH        32
+#define DMI_HALTSUM3_HALTSUM3               (0xffffffffU << DMI_HALTSUM3_HALTSUM3_OFFSET)
+#define DMI_SBADDRESS3                      0x37
+/*
+* Accesses bits 127:96 of the physical address in {\tt sbaddress} (if
+* the system address bus is that wide).
+ */
+#define DMI_SBADDRESS3_ADDRESS_OFFSET       0
+#define DMI_SBADDRESS3_ADDRESS_LENGTH       32
+#define DMI_SBADDRESS3_ADDRESS              (0xffffffffU << DMI_SBADDRESS3_ADDRESS_OFFSET)
+#define DMI_SBCS                            0x38
+/*
+* 0: The System Bus interface conforms to mainline drafts of this
+* spec older than 1 January, 2018.
+*
+* 1: The System Bus interface conforms to this version of the spec.
+*
+* Other values are reserved for future versions.
+ */
+#define DMI_SBCS_SBVERSION_OFFSET           29
+#define DMI_SBCS_SBVERSION_LENGTH           3
+#define DMI_SBCS_SBVERSION                  (0x7U << DMI_SBCS_SBVERSION_OFFSET)
+/*
+* Set when the debugger attempts to read data while a read is in
+* progress, or when the debugger initiates a new access while one is
+* already in progress (while \Fsbbusy is set). It remains set until
+* it's explicitly cleared by the debugger.
+*
+* While this field is non-zero, no more system bus accesses can be
+* initiated by the Debug Module.
+ */
+#define DMI_SBCS_SBBUSYERROR_OFFSET         22
+#define DMI_SBCS_SBBUSYERROR_LENGTH         1
+#define DMI_SBCS_SBBUSYERROR                (0x1U << DMI_SBCS_SBBUSYERROR_OFFSET)
+/*
+* When 1, indicates the system bus master is busy. (Whether the
+* system bus itself is busy is related, but not the same thing.) This
+* bit goes high immediately when a read or write is requested for any
+* reason, and does not go low until the access is fully completed.
+*
+* Writes to \Rsbcs while \Fsbbusy is high result in undefined
+* behavior.  A debugger must not write to \Rsbcs until it reads
+* \Fsbbusy as 0.
+ */
+#define DMI_SBCS_SBBUSY_OFFSET              21
+#define DMI_SBCS_SBBUSY_LENGTH              1
+#define DMI_SBCS_SBBUSY                     (0x1U << DMI_SBCS_SBBUSY_OFFSET)
+/*
+* When 1, every write to \Rsbaddresszero automatically triggers a
+* system bus read at the new address.
+ */
+#define DMI_SBCS_SBREADONADDR_OFFSET        20
+#define DMI_SBCS_SBREADONADDR_LENGTH        1
+#define DMI_SBCS_SBREADONADDR               (0x1U << DMI_SBCS_SBREADONADDR_OFFSET)
+/*
+* Select the access size to use for system bus accesses.
+*
+* 0: 8-bit
+*
+* 1: 16-bit
+*
+* 2: 32-bit
+*
+* 3: 64-bit
+*
+* 4: 128-bit
+*
+* If \Fsbaccess has an unsupported value when the DM starts a bus
+* access, the access is not performed and \Fsberror is set to 3.
+ */
+#define DMI_SBCS_SBACCESS_OFFSET            17
+#define DMI_SBCS_SBACCESS_LENGTH            3
+#define DMI_SBCS_SBACCESS                   (0x7U << DMI_SBCS_SBACCESS_OFFSET)
+/*
+* When 1, {\tt sbaddress} is incremented by the access size (in
+* bytes) selected in \Fsbaccess after every system bus access.
+ */
+#define DMI_SBCS_SBAUTOINCREMENT_OFFSET     16
+#define DMI_SBCS_SBAUTOINCREMENT_LENGTH     1
+#define DMI_SBCS_SBAUTOINCREMENT            (0x1U << DMI_SBCS_SBAUTOINCREMENT_OFFSET)
+/*
+* When 1, every read from \Rsbdatazero automatically triggers a
+* system bus read at the (possibly auto-incremented) address.
+ */
+#define DMI_SBCS_SBREADONDATA_OFFSET        15
+#define DMI_SBCS_SBREADONDATA_LENGTH        1
+#define DMI_SBCS_SBREADONDATA               (0x1U << DMI_SBCS_SBREADONDATA_OFFSET)
+/*
+* When the Debug Module's system bus
+* master causes a bus error, this field gets set. The bits in this
+* field remain set until they are cleared by writing 1 to them.
+* While this field is non-zero, no more system bus accesses can be
+* initiated by the Debug Module.
+*
+* An implementation may report "Other" (7) for any error condition.
+*
+* 0: There was no bus error.
+*
+* 1: There was a timeout.
+*
+* 2: A bad address was accessed.
+*
+* 3: There was an alignment error.
+*
+* 4: An access of unsupported size was requested.
+*
+* 7: Other.
+ */
+#define DMI_SBCS_SBERROR_OFFSET             12
+#define DMI_SBCS_SBERROR_LENGTH             3
+#define DMI_SBCS_SBERROR                    (0x7U << DMI_SBCS_SBERROR_OFFSET)
+/*
+* Width of system bus addresses in bits. (0 indicates there is no bus
+* access support.)
+ */
+#define DMI_SBCS_SBASIZE_OFFSET             5
+#define DMI_SBCS_SBASIZE_LENGTH             7
+#define DMI_SBCS_SBASIZE                    (0x7fU << DMI_SBCS_SBASIZE_OFFSET)
+/*
+* 1 when 128-bit system bus accesses are supported.
+ */
+#define DMI_SBCS_SBACCESS128_OFFSET         4
+#define DMI_SBCS_SBACCESS128_LENGTH         1
+#define DMI_SBCS_SBACCESS128                (0x1U << DMI_SBCS_SBACCESS128_OFFSET)
+/*
+* 1 when 64-bit system bus accesses are supported.
+ */
+#define DMI_SBCS_SBACCESS64_OFFSET          3
+#define DMI_SBCS_SBACCESS64_LENGTH          1
+#define DMI_SBCS_SBACCESS64                 (0x1U << DMI_SBCS_SBACCESS64_OFFSET)
+/*
+* 1 when 32-bit system bus accesses are supported.
+ */
+#define DMI_SBCS_SBACCESS32_OFFSET          2
+#define DMI_SBCS_SBACCESS32_LENGTH          1
+#define DMI_SBCS_SBACCESS32                 (0x1U << DMI_SBCS_SBACCESS32_OFFSET)
+/*
+* 1 when 16-bit system bus accesses are supported.
+ */
+#define DMI_SBCS_SBACCESS16_OFFSET          1
+#define DMI_SBCS_SBACCESS16_LENGTH          1
+#define DMI_SBCS_SBACCESS16                 (0x1U << DMI_SBCS_SBACCESS16_OFFSET)
+/*
+* 1 when 8-bit system bus accesses are supported.
+ */
+#define DMI_SBCS_SBACCESS8_OFFSET           0
+#define DMI_SBCS_SBACCESS8_LENGTH           1
+#define DMI_SBCS_SBACCESS8                  (0x1U << DMI_SBCS_SBACCESS8_OFFSET)
+#define DMI_SBADDRESS0                      0x39
+/*
+* Accesses bits 31:0 of the physical address in {\tt sbaddress}.
+ */
+#define DMI_SBADDRESS0_ADDRESS_OFFSET       0
+#define DMI_SBADDRESS0_ADDRESS_LENGTH       32
+#define DMI_SBADDRESS0_ADDRESS              (0xffffffffU << DMI_SBADDRESS0_ADDRESS_OFFSET)
+#define DMI_SBADDRESS1                      0x3a
+/*
+* Accesses bits 63:32 of the physical address in {\tt sbaddress} (if
+* the system address bus is that wide).
+ */
+#define DMI_SBADDRESS1_ADDRESS_OFFSET       0
+#define DMI_SBADDRESS1_ADDRESS_LENGTH       32
+#define DMI_SBADDRESS1_ADDRESS              (0xffffffffU << DMI_SBADDRESS1_ADDRESS_OFFSET)
+#define DMI_SBADDRESS2                      0x3b
+/*
+* Accesses bits 95:64 of the physical address in {\tt sbaddress} (if
+* the system address bus is that wide).
+ */
+#define DMI_SBADDRESS2_ADDRESS_OFFSET       0
+#define DMI_SBADDRESS2_ADDRESS_LENGTH       32
+#define DMI_SBADDRESS2_ADDRESS              (0xffffffffU << DMI_SBADDRESS2_ADDRESS_OFFSET)
+#define DMI_SBDATA0                         0x3c
+/*
+* Accesses bits 31:0 of {\tt sbdata}.
+ */
+#define DMI_SBDATA0_DATA_OFFSET             0
+#define DMI_SBDATA0_DATA_LENGTH             32
+#define DMI_SBDATA0_DATA                    (0xffffffffU << DMI_SBDATA0_DATA_OFFSET)
+#define DMI_SBDATA1                         0x3d
+/*
+* Accesses bits 63:32 of {\tt sbdata} (if the system bus is that
+* wide).
+ */
+#define DMI_SBDATA1_DATA_OFFSET             0
+#define DMI_SBDATA1_DATA_LENGTH             32
+#define DMI_SBDATA1_DATA                    (0xffffffffU << DMI_SBDATA1_DATA_OFFSET)
+#define DMI_SBDATA2                         0x3e
+/*
+* Accesses bits 95:64 of {\tt sbdata} (if the system bus is that
+* wide).
+ */
+#define DMI_SBDATA2_DATA_OFFSET             0
+#define DMI_SBDATA2_DATA_LENGTH             32
+#define DMI_SBDATA2_DATA                    (0xffffffffU << DMI_SBDATA2_DATA_OFFSET)
+#define DMI_SBDATA3                         0x3f
+/*
+* Accesses bits 127:96 of {\tt sbdata} (if the system bus is that
+* wide).
+ */
+#define DMI_SBDATA3_DATA_OFFSET             0
+#define DMI_SBDATA3_DATA_LENGTH             32
+#define DMI_SBDATA3_DATA                    (0xffffffffU << DMI_SBDATA3_DATA_OFFSET)
+#define SHORTNAME                           0x123
+/*
+* Description of what this field is used for.
+ */
+#define SHORTNAME_FIELD_OFFSET              0
+#define SHORTNAME_FIELD_LENGTH              8
+#define SHORTNAME_FIELD                     (0xffU << SHORTNAME_FIELD_OFFSET)
+#define AC_ACCESS_REGISTER                  None
+/*
+* This is 0 to indicate Access Register Command.
+ */
+#define AC_ACCESS_REGISTER_CMDTYPE_OFFSET   24
+#define AC_ACCESS_REGISTER_CMDTYPE_LENGTH   8
+#define AC_ACCESS_REGISTER_CMDTYPE          (0xffU << AC_ACCESS_REGISTER_CMDTYPE_OFFSET)
+/*
+* 2: Access the lowest 32 bits of the register.
+*
+* 3: Access the lowest 64 bits of the register.
+*
+* 4: Access the lowest 128 bits of the register.
+*
+* If \Fsize specifies a size larger than the register's actual size,
+* then the access must fail. If a register is accessible, then reads of \Fsize
+* less than or equal to the register's actual size must be supported.
+*
+* This field controls the Argument Width as referenced in
+* Table~\ref{tab:datareg}.
+ */
+#define AC_ACCESS_REGISTER_SIZE_OFFSET      20
+#define AC_ACCESS_REGISTER_SIZE_LENGTH      3
+#define AC_ACCESS_REGISTER_SIZE             (0x7U << AC_ACCESS_REGISTER_SIZE_OFFSET)
+/*
+* When 1, execute the program in the Program Buffer exactly once
+* after performing the transfer, if any.
+ */
+#define AC_ACCESS_REGISTER_POSTEXEC_OFFSET  18
+#define AC_ACCESS_REGISTER_POSTEXEC_LENGTH  1
+#define AC_ACCESS_REGISTER_POSTEXEC         (0x1U << AC_ACCESS_REGISTER_POSTEXEC_OFFSET)
+/*
+* 0: Don't do the operation specified by \Fwrite.
+*
+* 1: Do the operation specified by \Fwrite.
+*
+* This bit can be used to just execute the Program Buffer without
+* having to worry about placing valid values into \Fsize or \Fregno.
+ */
+#define AC_ACCESS_REGISTER_TRANSFER_OFFSET  17
+#define AC_ACCESS_REGISTER_TRANSFER_LENGTH  1
+#define AC_ACCESS_REGISTER_TRANSFER         (0x1U << AC_ACCESS_REGISTER_TRANSFER_OFFSET)
+/*
+* When \Ftransfer is set:
+* 0: Copy data from the specified register into {\tt arg0} portion
+* of {\tt data}.
+*
+* 1: Copy data from {\tt arg0} portion of {\tt data} into the
+* specified register.
+ */
+#define AC_ACCESS_REGISTER_WRITE_OFFSET     16
+#define AC_ACCESS_REGISTER_WRITE_LENGTH     1
+#define AC_ACCESS_REGISTER_WRITE            (0x1U << AC_ACCESS_REGISTER_WRITE_OFFSET)
+/*
+* Number of the register to access, as described in
+* Table~\ref{tab:regno}.
+* \Rdpc may be used as an alias for PC if this command is
+* supported on a non-halted hart.
+ */
+#define AC_ACCESS_REGISTER_REGNO_OFFSET     0
+#define AC_ACCESS_REGISTER_REGNO_LENGTH     16
+#define AC_ACCESS_REGISTER_REGNO            (0xffffU << AC_ACCESS_REGISTER_REGNO_OFFSET)
+#define AC_QUICK_ACCESS                     None
+/*
+* This is 1 to indicate Quick Access command.
+ */
+#define AC_QUICK_ACCESS_CMDTYPE_OFFSET      24
+#define AC_QUICK_ACCESS_CMDTYPE_LENGTH      8
+#define AC_QUICK_ACCESS_CMDTYPE             (0xffU << AC_QUICK_ACCESS_CMDTYPE_OFFSET)
+#define VIRT_PRIV                           virtual
+/*
+* Contains the privilege level the hart was operating in when Debug
+* Mode was entered. The encoding is described in Table
+* \ref{tab:privlevel}, and matches the privilege level encoding from
+* the RISC-V Privileged ISA Specification. A user can write this
+* value to change the hart's privilege level when exiting Debug Mode.
+ */
+#define VIRT_PRIV_PRV_OFFSET                0
+#define VIRT_PRIV_PRV_LENGTH                2
+#define VIRT_PRIV_PRV                       (0x3U << VIRT_PRIV_PRV_OFFSET)
diff --git a/tb/riscv-isa-sim/riscv/debug_module.cc b/tb/riscv-isa-sim/riscv/debug_module.cc
new file mode 100644
index 0000000000000000000000000000000000000000..96de3c8ab234f59aa23cf079a16a9395f37acee4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/debug_module.cc
@@ -0,0 +1,790 @@
+#include <cassert>
+
+#include "debug_module.h"
+#include "debug_defines.h"
+#include "opcodes.h"
+#include "mmu.h"
+#include "sim.h"
+
+#include "debug_rom/debug_rom.h"
+#include "debug_rom_defines.h"
+
+#if 0
+#  define D(x) x
+#else
+#  define D(x)
+#endif
+
+///////////////////////// debug_module_t
+
+debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits,
+    bool require_authentication) :
+  progbufsize(progbufsize),
+  program_buffer_bytes(4 + 4*progbufsize),
+  max_bus_master_bits(max_bus_master_bits),
+  require_authentication(require_authentication),
+  debug_progbuf_start(debug_data_start - program_buffer_bytes),
+  debug_abstract_start(debug_progbuf_start - debug_abstract_size*4),
+  custom_base(0),
+  sim(sim)
+{
+  D(fprintf(stderr, "debug_data_start=0x%x\n", debug_data_start));
+  D(fprintf(stderr, "debug_progbuf_start=0x%x\n", debug_progbuf_start));
+  D(fprintf(stderr, "debug_abstract_start=0x%x\n", debug_abstract_start));
+
+  program_buffer = new uint8_t[program_buffer_bytes];
+
+  memset(halted, 0, sizeof(halted));
+  memset(debug_rom_flags, 0, sizeof(debug_rom_flags));
+  memset(resumeack, 0, sizeof(resumeack));
+  memset(havereset, 0, sizeof(havereset));
+  memset(program_buffer, 0, program_buffer_bytes);
+  program_buffer[4*progbufsize] = ebreak();
+  program_buffer[4*progbufsize+1] = ebreak() >> 8;
+  program_buffer[4*progbufsize+2] = ebreak() >> 16;
+  program_buffer[4*progbufsize+3] = ebreak() >> 24;
+  memset(dmdata, 0, sizeof(dmdata));
+
+  write32(debug_rom_whereto, 0,
+          jal(ZERO, debug_abstract_start - DEBUG_ROM_WHERETO));
+
+  memset(debug_abstract, 0, sizeof(debug_abstract));
+
+  reset();
+}
+
+debug_module_t::~debug_module_t()
+{
+  delete[] program_buffer;
+}
+
+void debug_module_t::reset()
+{
+  for (unsigned i = 0; i < sim->nprocs(); i++) {
+    processor_t *proc = sim->get_core(i);
+    if (proc)
+      proc->halt_request = false;
+  }
+
+  dmcontrol = {0};
+
+  dmstatus = {0};
+  dmstatus.impebreak = true;
+  dmstatus.authenticated = !require_authentication;
+  dmstatus.version = 2;
+
+  abstractcs = {0};
+  abstractcs.datacount = sizeof(dmdata) / 4;
+  abstractcs.progbufsize = progbufsize;
+
+  abstractauto = {0};
+
+  sbcs = {0};
+  if (max_bus_master_bits > 0) {
+    sbcs.version = 1;
+    sbcs.asize = sizeof(reg_t) * 8;
+  }
+  if (max_bus_master_bits >= 64)
+    sbcs.access64 = true;
+  if (max_bus_master_bits >= 32)
+    sbcs.access32 = true;
+  if (max_bus_master_bits >= 16)
+    sbcs.access16 = true;
+  if (max_bus_master_bits >= 8)
+    sbcs.access8 = true;
+
+  challenge = random();
+}
+
+void debug_module_t::add_device(bus_t *bus) {
+  bus->add_device(DEBUG_START, this);
+}
+
+bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  addr = DEBUG_START + addr;
+
+  if (addr >= DEBUG_ROM_ENTRY &&
+      (addr + len) <= (DEBUG_ROM_ENTRY + debug_rom_raw_len)) {
+    memcpy(bytes, debug_rom_raw + addr - DEBUG_ROM_ENTRY, len);
+    return true;
+  }
+
+  if (addr >= DEBUG_ROM_WHERETO && (addr + len) <= (DEBUG_ROM_WHERETO + 4)) {
+    memcpy(bytes, debug_rom_whereto + addr - DEBUG_ROM_WHERETO, len);
+    return true;
+  }
+
+  if (addr >= DEBUG_ROM_FLAGS && ((addr + len) <= DEBUG_ROM_FLAGS + 1024)) {
+    memcpy(bytes, debug_rom_flags + addr - DEBUG_ROM_FLAGS, len);
+    return true;
+  }
+
+  if (addr >= debug_abstract_start && ((addr + len) <= (debug_abstract_start + sizeof(debug_abstract)))) {
+    memcpy(bytes, debug_abstract + addr - debug_abstract_start, len);
+    return true;
+  }
+
+  if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
+    memcpy(bytes, dmdata + addr - debug_data_start, len);
+    return true;
+  }
+
+  if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
+    memcpy(bytes, program_buffer + addr - debug_progbuf_start, len);
+    return true;
+  }
+
+  fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
+          PRIx64 "\n", len, addr);
+
+  return false;
+}
+
+bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  D(
+      switch (len) {
+        case 4:
+          fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
+              "hartsel=0x%x\n", addr, (unsigned) len, *(uint32_t *) bytes,
+              dmcontrol.hartsel);
+          break;
+        default:
+          fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=...); "
+              "hartsel=0x%x\n", addr, (unsigned) len, dmcontrol.hartsel);
+          break;
+      }
+   );
+
+  uint8_t id_bytes[4];
+  uint32_t id = 0;
+  if (len == 4) {
+    memcpy(id_bytes, bytes, 4);
+    id = read32(id_bytes, 0);
+  }
+
+  addr = DEBUG_START + addr;
+
+  if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
+    memcpy(dmdata + addr - debug_data_start, bytes, len);
+    return true;
+  }
+
+  if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
+    memcpy(program_buffer + addr - debug_progbuf_start, bytes, len);
+
+    return true;
+  }
+
+  if (addr == DEBUG_ROM_HALTED) {
+    assert (len == 4);
+    halted[id] = true;
+    if (dmcontrol.hartsel == id) {
+        if (0 == (debug_rom_flags[id] & (1 << DEBUG_ROM_FLAG_GO))){
+          if (dmcontrol.hartsel == id) {
+              abstractcs.busy = false;
+          }
+        }
+    }
+    return true;
+  }
+
+  if (addr == DEBUG_ROM_GOING) {
+    debug_rom_flags[dmcontrol.hartsel] &= ~(1 << DEBUG_ROM_FLAG_GO);
+    return true;
+  }
+
+  if (addr == DEBUG_ROM_RESUMING) {
+    assert (len == 4);
+    halted[id] = false;
+    resumeack[id] = true;
+    debug_rom_flags[id] &= ~(1 << DEBUG_ROM_FLAG_RESUME);
+    return true;
+  }
+
+  if (addr == DEBUG_ROM_EXCEPTION) {
+    if (abstractcs.cmderr == CMDERR_NONE) {
+      abstractcs.cmderr = CMDERR_EXCEPTION;
+    }
+    return true;
+  }
+
+  fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
+          PRIx64 "\n", len, addr);
+  return false;
+}
+
+void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
+{
+  uint8_t* base = memory + index * 4;
+  base[0] = value & 0xff;
+  base[1] = (value >> 8) & 0xff;
+  base[2] = (value >> 16) & 0xff;
+  base[3] = (value >> 24) & 0xff;
+}
+
+uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
+{
+  uint8_t* base = memory + index * 4;
+  uint32_t value = ((uint32_t) base[0]) |
+    (((uint32_t) base[1]) << 8) |
+    (((uint32_t) base[2]) << 16) |
+    (((uint32_t) base[3]) << 24);
+  return value;
+}
+
+processor_t *debug_module_t::current_proc() const
+{
+  processor_t *proc = NULL;
+  try {
+    proc = sim->get_core(dmcontrol.hartsel);
+  } catch (const std::out_of_range&) {
+  }
+  return proc;
+}
+
+unsigned debug_module_t::sb_access_bits()
+{
+  return 8 << sbcs.sbaccess;
+}
+
+void debug_module_t::sb_autoincrement()
+{
+  if (!sbcs.autoincrement || !max_bus_master_bits)
+    return;
+
+  uint64_t value = sbaddress[0] + sb_access_bits() / 8;
+  sbaddress[0] = value;
+  uint32_t carry = value >> 32;
+
+  value = sbaddress[1] + carry;
+  sbaddress[1] = value;
+  carry = value >> 32;
+
+  value = sbaddress[2] + carry;
+  sbaddress[2] = value;
+  carry = value >> 32;
+
+  sbaddress[3] += carry;
+}
+
+void debug_module_t::sb_read()
+{
+  reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
+  try {
+    if (sbcs.sbaccess == 0 && max_bus_master_bits >= 8) {
+      sbdata[0] = sim->debug_mmu->load_uint8(address);
+    } else if (sbcs.sbaccess == 1 && max_bus_master_bits >= 16) {
+      sbdata[0] = sim->debug_mmu->load_uint16(address);
+    } else if (sbcs.sbaccess == 2 && max_bus_master_bits >= 32) {
+      sbdata[0] = sim->debug_mmu->load_uint32(address);
+    } else if (sbcs.sbaccess == 3 && max_bus_master_bits >= 64) {
+      uint64_t value = sim->debug_mmu->load_uint64(address);
+      sbdata[0] = value;
+      sbdata[1] = value >> 32;
+    } else {
+      sbcs.error = 3;
+    }
+  } catch (trap_load_access_fault& t) {
+    sbcs.error = 2;
+  }
+}
+
+void debug_module_t::sb_write()
+{
+  reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
+  D(fprintf(stderr, "sb_write() 0x%x @ 0x%lx\n", sbdata[0], address));
+  if (sbcs.sbaccess == 0 && max_bus_master_bits >= 8) {
+    sim->debug_mmu->store_uint8(address, sbdata[0]);
+  } else if (sbcs.sbaccess == 1 && max_bus_master_bits >= 16) {
+    sim->debug_mmu->store_uint16(address, sbdata[0]);
+  } else if (sbcs.sbaccess == 2 && max_bus_master_bits >= 32) {
+    sim->debug_mmu->store_uint32(address, sbdata[0]);
+  } else if (sbcs.sbaccess == 3 && max_bus_master_bits >= 64) {
+    sim->debug_mmu->store_uint64(address,
+        (((uint64_t) sbdata[1]) << 32) | sbdata[0]);
+  } else {
+    sbcs.error = 3;
+  }
+}
+
+bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
+{
+  uint32_t result = 0;
+  D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
+  if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
+    unsigned i = address - DMI_DATA0;
+    result = read32(dmdata, i);
+    if (abstractcs.busy) {
+      result = -1;
+      fprintf(stderr, "\ndmi_read(0x%02x (data[%d]) -> -1 because abstractcs.busy==true\n", address, i);
+    }
+
+    if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
+      abstractcs.cmderr = CMDERR_BUSY;
+    }
+
+    if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
+      perform_abstract_command();
+    }
+  } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
+    unsigned i = address - DMI_PROGBUF0;
+    result = read32(program_buffer, i);
+    if (abstractcs.busy) {
+      result = -1;
+      fprintf(stderr, "\ndmi_read(0x%02x (progbuf[%d]) -> -1 because abstractcs.busy==true\n", address, i);
+    }
+    if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
+      perform_abstract_command();
+    }
+
+  } else {
+    switch (address) {
+      case DMI_DMCONTROL:
+        {
+          processor_t *proc = current_proc();
+          if (proc)
+            dmcontrol.haltreq = proc->halt_request;
+
+          result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
+          result = set_field(result, DMI_DMCONTROL_RESUMEREQ, dmcontrol.resumereq);
+          result = set_field(result, DMI_DMCONTROL_HARTSELHI,
+              dmcontrol.hartsel >> DMI_DMCONTROL_HARTSELLO_LENGTH);
+          result = set_field(result, DMI_DMCONTROL_HARTSELLO, dmcontrol.hartsel);
+          result = set_field(result, DMI_DMCONTROL_HARTRESET, dmcontrol.hartreset);
+	  result = set_field(result, DMI_DMCONTROL_NDMRESET, dmcontrol.ndmreset);
+          result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
+        }
+        break;
+      case DMI_DMSTATUS:
+        {
+          processor_t *proc = current_proc();
+
+	  dmstatus.allnonexistant = false;
+	  dmstatus.allunavail = false;
+	  dmstatus.allrunning = false;
+	  dmstatus.allhalted = false;
+          dmstatus.allresumeack = false;
+          if (proc) {
+            if (halted[dmcontrol.hartsel]) {
+              dmstatus.allhalted = true;
+            } else {
+              dmstatus.allrunning = true;
+            }
+          } else {
+	    dmstatus.allnonexistant = true;
+          }
+	  dmstatus.anynonexistant = dmstatus.allnonexistant;
+	  dmstatus.anyunavail = dmstatus.allunavail;
+	  dmstatus.anyrunning = dmstatus.allrunning;
+	  dmstatus.anyhalted = dmstatus.allhalted;
+          if (proc) {
+            if (resumeack[dmcontrol.hartsel]) {
+              dmstatus.allresumeack = true;
+            } else {
+              dmstatus.allresumeack = false;
+            }
+          } else {
+            dmstatus.allresumeack = false;
+          }
+
+          result = set_field(result, DMI_DMSTATUS_IMPEBREAK,
+              dmstatus.impebreak);
+          result = set_field(result, DMI_DMSTATUS_ALLHAVERESET,
+              havereset[dmcontrol.hartsel]);
+          result = set_field(result, DMI_DMSTATUS_ANYHAVERESET,
+              havereset[dmcontrol.hartsel]);
+	  result = set_field(result, DMI_DMSTATUS_ALLNONEXISTENT, dmstatus.allnonexistant);
+	  result = set_field(result, DMI_DMSTATUS_ALLUNAVAIL, dmstatus.allunavail);
+	  result = set_field(result, DMI_DMSTATUS_ALLRUNNING, dmstatus.allrunning);
+	  result = set_field(result, DMI_DMSTATUS_ALLHALTED, dmstatus.allhalted);
+          result = set_field(result, DMI_DMSTATUS_ALLRESUMEACK, dmstatus.allresumeack);
+	  result = set_field(result, DMI_DMSTATUS_ANYNONEXISTENT, dmstatus.anynonexistant);
+	  result = set_field(result, DMI_DMSTATUS_ANYUNAVAIL, dmstatus.anyunavail);
+	  result = set_field(result, DMI_DMSTATUS_ANYRUNNING, dmstatus.anyrunning);
+	  result = set_field(result, DMI_DMSTATUS_ANYHALTED, dmstatus.anyhalted);
+          result = set_field(result, DMI_DMSTATUS_ANYRESUMEACK, dmstatus.anyresumeack);
+          result = set_field(result, DMI_DMSTATUS_AUTHENTICATED, dmstatus.authenticated);
+          result = set_field(result, DMI_DMSTATUS_AUTHBUSY, dmstatus.authbusy);
+          result = set_field(result, DMI_DMSTATUS_VERSION, dmstatus.version);
+        }
+      	break;
+      case DMI_ABSTRACTCS:
+        result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
+        result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
+        result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
+        result = set_field(result, DMI_ABSTRACTCS_PROGBUFSIZE,
+            abstractcs.progbufsize);
+        break;
+      case DMI_ABSTRACTAUTO:
+        result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF, abstractauto.autoexecprogbuf);
+        result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECDATA, abstractauto.autoexecdata);
+        break;
+      case DMI_COMMAND:
+        result = 0;
+        break;
+      case DMI_HARTINFO:
+        result = set_field(result, DMI_HARTINFO_NSCRATCH, 1);
+        result = set_field(result, DMI_HARTINFO_DATAACCESS, 1);
+        result = set_field(result, DMI_HARTINFO_DATASIZE, abstractcs.datacount);
+        result = set_field(result, DMI_HARTINFO_DATAADDR, debug_data_start);
+        break;
+      case DMI_SBCS:
+        result = set_field(result, DMI_SBCS_SBVERSION, sbcs.version);
+        result = set_field(result, DMI_SBCS_SBREADONADDR, sbcs.readonaddr);
+        result = set_field(result, DMI_SBCS_SBACCESS, sbcs.sbaccess);
+        result = set_field(result, DMI_SBCS_SBAUTOINCREMENT, sbcs.autoincrement);
+        result = set_field(result, DMI_SBCS_SBREADONDATA, sbcs.readondata);
+        result = set_field(result, DMI_SBCS_SBERROR, sbcs.error);
+        result = set_field(result, DMI_SBCS_SBASIZE, sbcs.asize);
+        result = set_field(result, DMI_SBCS_SBACCESS128, sbcs.access128);
+        result = set_field(result, DMI_SBCS_SBACCESS64, sbcs.access64);
+        result = set_field(result, DMI_SBCS_SBACCESS32, sbcs.access32);
+        result = set_field(result, DMI_SBCS_SBACCESS16, sbcs.access16);
+        result = set_field(result, DMI_SBCS_SBACCESS8, sbcs.access8);
+        break;
+      case DMI_SBADDRESS0:
+        result = sbaddress[0];
+        break;
+      case DMI_SBADDRESS1:
+        result = sbaddress[1];
+        break;
+      case DMI_SBADDRESS2:
+        result = sbaddress[2];
+        break;
+      case DMI_SBADDRESS3:
+        result = sbaddress[3];
+        break;
+      case DMI_SBDATA0:
+        result = sbdata[0];
+        if (sbcs.error == 0) {
+          sb_autoincrement();
+          if (sbcs.readondata) {
+            sb_read();
+          }
+        }
+        break;
+      case DMI_SBDATA1:
+        result = sbdata[1];
+        break;
+      case DMI_SBDATA2:
+        result = sbdata[2];
+        break;
+      case DMI_SBDATA3:
+        result = sbdata[3];
+        break;
+      case DMI_AUTHDATA:
+        result = challenge;
+        break;
+      default:
+        result = 0;
+        D(fprintf(stderr, "Unexpected. Returning Error."));
+        return false;
+    }
+  }
+  D(fprintf(stderr, "0x%x\n", result));
+  *value = result;
+  return true;
+}
+
+bool debug_module_t::perform_abstract_command()
+{
+  if (abstractcs.cmderr != CMDERR_NONE)
+    return true;
+  if (abstractcs.busy) {
+    abstractcs.cmderr = CMDERR_BUSY;
+    return true;
+  }
+
+  if ((command >> 24) == 0) {
+    // register access
+    unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
+    bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
+    unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
+
+    if (!halted[dmcontrol.hartsel]) {
+      abstractcs.cmderr = CMDERR_HALTRESUME;
+      return true;
+    }
+
+    unsigned i = 0;
+    if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
+
+      if (regno < 0x1000 && progbufsize < 2) {
+        // Make the debugger use the program buffer if it's available, so it
+        // can test both use cases.
+        write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH));
+
+        if (write) {
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, lw(S0, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, ld(S0, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+          write32(debug_abstract, i++, csrw(S0, regno));
+
+        } else {
+          write32(debug_abstract, i++, csrr(S0, regno));
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, sw(S0, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, sd(S0, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+        }
+        write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH));
+
+      } else if (regno >= 0x1000 && regno < 0x1020) {
+        unsigned regnum = regno - 0x1000;
+
+        switch (size) {
+          case 2:
+            if (write)
+              write32(debug_abstract, i++, lw(regnum, ZERO, debug_data_start));
+            else
+              write32(debug_abstract, i++, sw(regnum, ZERO, debug_data_start));
+            break;
+          case 3:
+            if (write)
+              write32(debug_abstract, i++, ld(regnum, ZERO, debug_data_start));
+            else
+              write32(debug_abstract, i++, sd(regnum, ZERO, debug_data_start));
+            break;
+          default:
+            abstractcs.cmderr = CMDERR_NOTSUP;
+            return true;
+        }
+
+      } else if (regno >= 0x1020 && regno < 0x1040) {
+        // Don't force the debugger to use progbuf if it exists, so the
+        // debugger has to make the decision not to use abstract commands to
+        // access 64-bit FPRs on 32-bit targets.
+        unsigned fprnum = regno - 0x1020;
+
+        if (write) {
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, flw(fprnum, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, fld(fprnum, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+
+        } else {
+          switch (size) {
+            case 2:
+              write32(debug_abstract, i++, fsw(fprnum, ZERO, debug_data_start));
+              break;
+            case 3:
+              write32(debug_abstract, i++, fsd(fprnum, ZERO, debug_data_start));
+              break;
+            default:
+              abstractcs.cmderr = CMDERR_NOTSUP;
+              return true;
+          }
+        }
+
+      } else if (regno >= 0xc000 && (regno & 1) == 1) {
+        // Support odd-numbered custom registers, to allow for debugger testing.
+        unsigned custom_number = regno - 0xc000;
+        abstractcs.cmderr = CMDERR_NONE;
+        if (write) {
+          // Writing V to custom register N will cause future reads of N to
+          // return V, reads of N-1 will return V-1, etc.
+          custom_base = read32(dmdata, 0) - custom_number;
+        } else {
+          write32(dmdata, 0, custom_number + custom_base);
+          write32(dmdata, 1, 0);
+        }
+        return true;
+
+      } else {
+        abstractcs.cmderr = CMDERR_NOTSUP;
+        return true;
+      }
+    }
+
+    if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
+      write32(debug_abstract, i,
+          jal(ZERO, debug_progbuf_start - debug_abstract_start - 4 * i));
+      i++;
+    } else {
+      write32(debug_abstract, i++, ebreak());
+    }
+
+    debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
+
+    abstractcs.busy = true;
+  } else {
+    abstractcs.cmderr = CMDERR_NOTSUP;
+  }
+  return true;
+}
+
+bool debug_module_t::dmi_write(unsigned address, uint32_t value)
+{
+  D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
+
+  if (!dmstatus.authenticated && address != DMI_AUTHDATA &&
+      address != DMI_DMCONTROL)
+    return false;
+
+  if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
+    unsigned i = address - DMI_DATA0;
+    if (!abstractcs.busy)
+      write32(dmdata, address - DMI_DATA0, value);
+
+    if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
+      abstractcs.cmderr = CMDERR_BUSY;
+    }
+
+    if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
+      perform_abstract_command();
+    }
+    return true;
+
+  } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
+    unsigned i = address - DMI_PROGBUF0;
+
+    if (!abstractcs.busy)
+      write32(program_buffer, i, value);
+
+    if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
+      perform_abstract_command();
+    }
+    return true;
+
+  } else {
+    switch (address) {
+      case DMI_DMCONTROL:
+        {
+          if (!dmcontrol.dmactive && get_field(value, DMI_DMCONTROL_DMACTIVE))
+            reset();
+          dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
+          if (!dmstatus.authenticated)
+            return true;
+          if (dmcontrol.dmactive) {
+            dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
+            dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
+            dmcontrol.hartreset = get_field(value, DMI_DMCONTROL_HARTRESET);
+            dmcontrol.ndmreset = get_field(value, DMI_DMCONTROL_NDMRESET);
+            dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSELHI) <<
+              DMI_DMCONTROL_HARTSELLO_LENGTH;
+            dmcontrol.hartsel |= get_field(value, DMI_DMCONTROL_HARTSELLO);
+            dmcontrol.hartsel &= (1L<<hartsellen) - 1;
+            if (get_field(value, DMI_DMCONTROL_ACKHAVERESET)) {
+              havereset[dmcontrol.hartsel] = false;
+            }
+          }
+          processor_t *proc = current_proc();
+          if (proc) {
+            proc->halt_request = dmcontrol.haltreq;
+            if (dmcontrol.resumereq) {
+              debug_rom_flags[dmcontrol.hartsel] |= (1 << DEBUG_ROM_FLAG_RESUME);
+              resumeack[dmcontrol.hartsel] = false;
+            }
+	    if (dmcontrol.hartreset) {
+	      proc->reset();
+	    }
+          }
+          if (dmcontrol.ndmreset) {
+            for (size_t i = 0; i < sim->nprocs(); i++) {
+              proc = sim->get_core(i);
+              proc->reset();
+            }
+          }
+        }
+        return true;
+
+      case DMI_COMMAND:
+        command = value;
+        return perform_abstract_command();
+
+      case DMI_ABSTRACTCS:
+        abstractcs.cmderr = (cmderr_t) (((uint32_t) (abstractcs.cmderr)) & (~(uint32_t)(get_field(value, DMI_ABSTRACTCS_CMDERR))));
+        return true;
+
+      case DMI_ABSTRACTAUTO:
+        abstractauto.autoexecprogbuf = get_field(value,
+            DMI_ABSTRACTAUTO_AUTOEXECPROGBUF);
+        abstractauto.autoexecdata = get_field(value,
+            DMI_ABSTRACTAUTO_AUTOEXECDATA);
+        return true;
+      case DMI_SBCS:
+        sbcs.readonaddr = get_field(value, DMI_SBCS_SBREADONADDR);
+        sbcs.sbaccess = get_field(value, DMI_SBCS_SBACCESS);
+        sbcs.autoincrement = get_field(value, DMI_SBCS_SBAUTOINCREMENT);
+        sbcs.readondata = get_field(value, DMI_SBCS_SBREADONDATA);
+        sbcs.error &= ~get_field(value, DMI_SBCS_SBERROR);
+        return true;
+      case DMI_SBADDRESS0:
+        sbaddress[0] = value;
+        if (sbcs.error == 0 && sbcs.readonaddr) {
+          sb_read();
+        }
+        return true;
+      case DMI_SBADDRESS1:
+        sbaddress[1] = value;
+        return true;
+      case DMI_SBADDRESS2:
+        sbaddress[2] = value;
+        return true;
+      case DMI_SBADDRESS3:
+        sbaddress[3] = value;
+        return true;
+      case DMI_SBDATA0:
+        sbdata[0] = value;
+        if (sbcs.error == 0) {
+          sb_write();
+          if (sbcs.autoincrement && sbcs.error == 0) {
+            sb_autoincrement();
+          }
+        }
+        return true;
+      case DMI_SBDATA1:
+        sbdata[1] = value;
+        return true;
+      case DMI_SBDATA2:
+        sbdata[2] = value;
+        return true;
+      case DMI_SBDATA3:
+        sbdata[3] = value;
+        return true;
+      case DMI_AUTHDATA:
+        D(fprintf(stderr, "debug authentication: got 0x%x; 0x%x unlocks\n", value,
+            challenge + secret));
+        if (require_authentication) {
+          if (value == challenge + secret) {
+            dmstatus.authenticated = true;
+          } else {
+            dmstatus.authenticated = false;
+            challenge = random();
+          }
+        }
+        return true;
+    }
+  }
+  return false;
+}
+
+void debug_module_t::proc_reset(unsigned id)
+{
+  havereset[id] = true;
+  halted[id] = false;
+}
diff --git a/tb/riscv-isa-sim/riscv/debug_module.h b/tb/riscv-isa-sim/riscv/debug_module.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b43ed628c52b5cb4745b9872cdebbb91885c318
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/debug_module.h
@@ -0,0 +1,164 @@
+// See LICENSE for license details.
+#ifndef _RISCV_DEBUG_MODULE_H
+#define _RISCV_DEBUG_MODULE_H
+
+#include <set>
+
+#include "devices.h"
+
+class sim_t;
+
+typedef struct {
+  bool haltreq;
+  bool resumereq;
+  unsigned hartsel;
+  bool hartreset;
+  bool dmactive;
+  bool ndmreset;
+} dmcontrol_t;
+
+typedef struct {
+  bool impebreak;
+  bool allhavereset;
+  bool anyhavereset;
+  bool allnonexistant;
+  bool anynonexistant;
+  bool allunavail;
+  bool anyunavail;
+  bool allrunning;
+  bool anyrunning;
+  bool allhalted;
+  bool anyhalted;
+  bool allresumeack;
+  bool anyresumeack;
+  bool authenticated;
+  bool authbusy;
+  bool cfgstrvalid;
+  unsigned version;
+} dmstatus_t;
+
+typedef enum cmderr {
+    CMDERR_NONE = 0,
+    CMDERR_BUSY = 1,
+    CMDERR_NOTSUP = 2,
+    CMDERR_EXCEPTION = 3,
+    CMDERR_HALTRESUME = 4,
+    CMDERR_OTHER = 7  
+} cmderr_t;
+
+typedef struct {
+  bool busy;
+  unsigned datacount;
+  unsigned progbufsize;
+  cmderr_t cmderr;
+} abstractcs_t;
+
+typedef struct {
+  unsigned autoexecprogbuf;
+  unsigned autoexecdata;
+} abstractauto_t;
+
+typedef struct {
+  unsigned version;
+  bool readonaddr;
+  unsigned sbaccess;
+  bool autoincrement;
+  bool readondata;
+  unsigned error;
+  unsigned asize;
+  bool access128;
+  bool access64;
+  bool access32;
+  bool access16;
+  bool access8;
+} sbcs_t;
+
+class debug_module_t : public abstract_device_t
+{
+  public:
+    /*
+     * If require_authentication is true, then a debugger must authenticate as
+     * follows:
+     * 1. Read a 32-bit value from authdata:
+     * 2. Write the value that was read back, plus one, to authdata.
+     */
+    debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits,
+        bool require_authentication);
+    ~debug_module_t();
+
+    void add_device(bus_t *bus);
+
+    bool load(reg_t addr, size_t len, uint8_t* bytes);
+    bool store(reg_t addr, size_t len, const uint8_t* bytes);
+
+    // Debug Module Interface that the debugger (in our case through JTAG DTM)
+    // uses to access the DM.
+    // Return true for success, false for failure.
+    bool dmi_read(unsigned address, uint32_t *value);
+    bool dmi_write(unsigned address, uint32_t value);
+
+    // Called when one of the attached harts was reset.
+    void proc_reset(unsigned id);
+
+  private:
+    static const unsigned datasize = 2;
+    // Size of program_buffer in 32-bit words, as exposed to the rest of the
+    // world.
+    unsigned progbufsize;
+    // Actual size of the program buffer, which is 1 word bigger than we let on
+    // to implement the implicit ebreak at the end.
+    unsigned program_buffer_bytes;
+    unsigned max_bus_master_bits;
+    bool require_authentication;
+    static const unsigned debug_data_start = 0x380;
+    unsigned debug_progbuf_start;
+
+    static const unsigned debug_abstract_size = 5;
+    unsigned debug_abstract_start;
+    // R/W this through custom registers, to allow debuggers to test that
+    // functionality.
+    unsigned custom_base;
+
+    // We only support 1024 harts currently. More requires at least resizing
+    // the arrays below, and their corresponding special memory regions.
+    static const unsigned hartsellen = 10;
+
+    sim_t *sim;
+
+    uint8_t debug_rom_whereto[4];
+    uint8_t debug_abstract[debug_abstract_size * 4];
+    uint8_t *program_buffer;
+    uint8_t dmdata[datasize * 4];
+
+    bool halted[1024];
+    bool resumeack[1024];
+    bool havereset[1024];
+    uint8_t debug_rom_flags[1024];
+
+    void write32(uint8_t *rom, unsigned int index, uint32_t value);
+    uint32_t read32(uint8_t *rom, unsigned int index);
+
+    void sb_autoincrement();
+    void sb_read();
+    void sb_write();
+    unsigned sb_access_bits();
+
+    dmcontrol_t dmcontrol;
+    dmstatus_t dmstatus;
+    abstractcs_t abstractcs;
+    abstractauto_t abstractauto;
+    uint32_t command;
+
+    sbcs_t sbcs;
+    uint32_t sbaddress[4];
+    uint32_t sbdata[4];
+
+    uint32_t challenge;
+    const uint32_t secret = 1;
+
+    processor_t *current_proc() const;
+    void reset();
+    bool perform_abstract_command();
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/debug_rom_defines.h b/tb/riscv-isa-sim/riscv/debug_rom_defines.h
new file mode 100644
index 0000000000000000000000000000000000000000..616cf59045fc066e4bfb683050ca1ccfd32ada98
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/debug_rom_defines.h
@@ -0,0 +1,23 @@
+// See LICENSE file for license details.
+
+#ifndef DEBUG_ROM_DEFINES_H
+#define DEBUG_ROM_DEFINES_H
+
+// These are implementation-specific addresses in the Debug Module
+#define DEBUG_ROM_HALTED    0x100
+#define DEBUG_ROM_GOING     0x104
+#define DEBUG_ROM_RESUMING  0x108
+#define DEBUG_ROM_EXCEPTION 0x10C
+
+// Region of memory where each hart has 1
+// byte to read.
+#define DEBUG_ROM_FLAGS 0x400
+#define DEBUG_ROM_FLAG_GO     0
+#define DEBUG_ROM_FLAG_RESUME 1
+
+// These needs to match the link.ld         
+#define DEBUG_ROM_WHERETO 0x300
+#define DEBUG_ROM_ENTRY   0x800
+#define DEBUG_ROM_TVEC    0x808
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/decode.h b/tb/riscv-isa-sim/riscv/decode.h
new file mode 100644
index 0000000000000000000000000000000000000000..b62bacce9d440d90accd4e5fbe42a3ff1c379baa
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/decode.h
@@ -0,0 +1,282 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_DECODE_H
+#define _RISCV_DECODE_H
+
+#if (-1 != ~0) || ((-1 >> 1) != -1)
+# error spike requires a two''s-complement c++ implementation
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# error spike requires a little-endian host
+#endif
+
+#include <cstdint>
+#include <string.h>
+#include <strings.h>
+#include "encoding.h"
+#include "config.h"
+#include "common.h"
+#include "softfloat_types.h"
+#include "specialize.h"
+#include <cinttypes>
+
+typedef int64_t sreg_t;
+typedef uint64_t reg_t;
+
+const int NXPR = 32;
+const int NFPR = 32;
+const int NCSR = 4096;
+
+#define X_RA 1
+#define X_SP 2
+
+#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 insn_length(x) \
+  (((x) & 0x03) < 0x03 ? 2 : \
+   ((x) & 0x1f) < 0x1f ? 4 : \
+   ((x) & 0x3f) < 0x3f ? 6 : \
+   8)
+#define MAX_INSN_LENGTH 8
+#define PC_ALIGN 2
+
+typedef uint64_t insn_bits_t;
+class insn_t
+{
+public:
+  insn_t() = default;
+  insn_t(insn_bits_t bits) : b(bits) {}
+  insn_bits_t bits() { return b; }
+  int length() { return insn_length(b); }
+  int64_t i_imm() { return int64_t(b) >> 20; }
+  int64_t shamt() { return x(20, 6); }
+  int64_t s_imm() { return x(7, 5) + (xs(25, 7) << 5); }
+  int64_t sb_imm() { return (x(8, 4) << 1) + (x(25,6) << 5) + (x(7,1) << 11) + (imm_sign() << 12); }
+  int64_t u_imm() { return int64_t(b) >> 12 << 12; }
+  int64_t uj_imm() { return (x(21, 10) << 1) + (x(20, 1) << 11) + (x(12, 8) << 12) + (imm_sign() << 20); }
+  uint64_t rd() { return x(7, 5); }
+  uint64_t rs1() { return x(15, 5); }
+  uint64_t rs2() { return x(20, 5); }
+  uint64_t rs3() { return x(27, 5); }
+  uint64_t rm() { return x(12, 3); }
+  uint64_t csr() { return x(20, 12); }
+
+  int64_t rvc_imm() { return x(2, 5) + (xs(12, 1) << 5); }
+  int64_t rvc_zimm() { return x(2, 5) + (x(12, 1) << 5); }
+  int64_t rvc_addi4spn_imm() { return (x(6, 1) << 2) + (x(5, 1) << 3) + (x(11, 2) << 4) + (x(7, 4) << 6); }
+  int64_t rvc_addi16sp_imm() { return (x(6, 1) << 4) + (x(2, 1) << 5) + (x(5, 1) << 6) + (x(3, 2) << 7) + (xs(12, 1) << 9); }
+  int64_t rvc_lwsp_imm() { return (x(4, 3) << 2) + (x(12, 1) << 5) + (x(2, 2) << 6); }
+  int64_t rvc_ldsp_imm() { return (x(5, 2) << 3) + (x(12, 1) << 5) + (x(2, 3) << 6); }
+  int64_t rvc_swsp_imm() { return (x(9, 4) << 2) + (x(7, 2) << 6); }
+  int64_t rvc_sdsp_imm() { return (x(10, 3) << 3) + (x(7, 3) << 6); }
+  int64_t rvc_lw_imm() { return (x(6, 1) << 2) + (x(10, 3) << 3) + (x(5, 1) << 6); }
+  int64_t rvc_ld_imm() { return (x(10, 3) << 3) + (x(5, 2) << 6); }
+  int64_t rvc_j_imm() { return (x(3, 3) << 1) + (x(11, 1) << 4) + (x(2, 1) << 5) + (x(7, 1) << 6) + (x(6, 1) << 7) + (x(9, 2) << 8) + (x(8, 1) << 10) + (xs(12, 1) << 11); }
+  int64_t rvc_b_imm() { return (x(3, 2) << 1) + (x(10, 2) << 3) + (x(2, 1) << 5) + (x(5, 2) << 6) + (xs(12, 1) << 8); }
+  int64_t rvc_simm3() { return x(10, 3); }
+  uint64_t rvc_rd() { return rd(); }
+  uint64_t rvc_rs1() { return rd(); }
+  uint64_t rvc_rs2() { return x(2, 5); }
+  uint64_t rvc_rs1s() { return 8 + x(7, 3); }
+  uint64_t rvc_rs2s() { return 8 + x(2, 3); }
+private:
+  insn_bits_t b;
+  uint64_t x(int lo, int len) { return (b >> lo) & ((insn_bits_t(1) << len)-1); }
+  uint64_t xs(int lo, int len) { return int64_t(b) << (64-lo-len) >> (64-len); }
+  uint64_t imm_sign() { return xs(63, 1); }
+};
+
+template <class T, size_t N, bool zero_reg>
+class regfile_t
+{
+public:
+  void write(size_t i, T value)
+  {
+    if (!zero_reg || i != 0)
+      data[i] = value;
+  }
+  const T& operator [] (size_t i) const
+  {
+    return data[i];
+  }
+private:
+  T data[N];
+};
+
+// helpful macros, etc
+#define MMU (*p->get_mmu())
+#define STATE (*p->get_state())
+#define READ_REG(reg) STATE.XPR[reg]
+#define READ_FREG(reg) STATE.FPR[reg]
+#define RS1 READ_REG(insn.rs1())
+#define RS2 READ_REG(insn.rs2())
+#define WRITE_RD(value) WRITE_REG(insn.rd(), value)
+
+#ifndef RISCV_ENABLE_COMMITLOG
+# define WRITE_REG(reg, value) STATE.XPR.write(reg, value)
+# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, freg(value))
+#else
+# define WRITE_REG(reg, value) ({ \
+    reg_t wdata = (value); /* value may have side effects */ \
+    STATE.log_reg_write = (commit_log_reg_t){(reg) << 1, {wdata, 0}}; \
+    STATE.XPR.write(reg, wdata); \
+  })
+# define WRITE_FREG(reg, value) ({ \
+    freg_t wdata = freg(value); /* value may have side effects */ \
+    STATE.log_reg_write = (commit_log_reg_t){((reg) << 1) | 1, wdata}; \
+    DO_WRITE_FREG(reg, wdata); \
+  })
+#endif
+
+// RVC macros
+#define WRITE_RVC_RS1S(value) WRITE_REG(insn.rvc_rs1s(), value)
+#define WRITE_RVC_RS2S(value) WRITE_REG(insn.rvc_rs2s(), value)
+#define WRITE_RVC_FRS2S(value) WRITE_FREG(insn.rvc_rs2s(), value)
+#define RVC_RS1 READ_REG(insn.rvc_rs1())
+#define RVC_RS2 READ_REG(insn.rvc_rs2())
+#define RVC_RS1S READ_REG(insn.rvc_rs1s())
+#define RVC_RS2S READ_REG(insn.rvc_rs2s())
+#define RVC_FRS2 READ_FREG(insn.rvc_rs2())
+#define RVC_FRS2S READ_FREG(insn.rvc_rs2s())
+#define RVC_SP READ_REG(X_SP)
+
+// FPU macros
+#define FRS1 READ_FREG(insn.rs1())
+#define FRS2 READ_FREG(insn.rs2())
+#define FRS3 READ_FREG(insn.rs3())
+// #define dirty_fp_state (STATE.mstatus |= MSTATUS_FS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
+#define dirty_fp_state (STATE.mstatus &= MSTATUS_FS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
+#define dirty_ext_state (STATE.mstatus |= MSTATUS_XS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
+#define DO_WRITE_FREG(reg, value) (STATE.FPR.write(reg, value), dirty_fp_state)
+#define WRITE_FRD(value) WRITE_FREG(insn.rd(), value)
+
+#define SHAMT (insn.i_imm() & 0x3F)
+#define BRANCH_TARGET (pc + insn.sb_imm())
+#define JUMP_TARGET (pc + insn.uj_imm())
+#define RM ({ int rm = insn.rm(); \
+              if(rm == 7) rm = STATE.frm; \
+              if(rm > 4) throw trap_illegal_instruction(0); \
+              rm; })
+
+#define get_field(reg, mask) (((reg) & (decltype(reg))(mask)) / ((mask) & ~((mask) << 1)))
+#define set_field(reg, mask, val) (((reg) & ~(decltype(reg))(mask)) | (((decltype(reg))(val) * ((mask) & ~((mask) << 1))) & (decltype(reg))(mask)))
+
+#define require(x) if (unlikely(!(x))) throw trap_illegal_instruction(0)
+#define require_privilege(p) require(STATE.prv >= (p))
+#define require_rv64 require(xlen == 64)
+#define require_rv32 require(xlen == 32)
+#define require_extension(s) require(p->supports_extension(s))
+#define require_fp require((STATE.mstatus & MSTATUS_FS) != 0)
+#define require_accelerator require((STATE.mstatus & MSTATUS_XS) != 0)
+
+#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \
+                               dirty_fp_state; \
+                               STATE.fflags |= softfloat_exceptionFlags; \
+                             } \
+                             softfloat_exceptionFlags = 0; })
+
+#define sext32(x) ((sreg_t)(int32_t)(x))
+#define zext32(x) ((reg_t)(uint32_t)(x))
+#define sext_xlen(x) (((sreg_t)(x) << (64-xlen)) >> (64-xlen))
+#define zext_xlen(x) (((reg_t)(x) << (64-xlen)) >> (64-xlen))
+
+#define set_pc(x) \
+  do { p->check_pc_alignment(x); \
+       npc = sext_xlen(x); \
+     } while(0)
+
+#define set_pc_and_serialize(x) \
+  do { reg_t __npc = (x) & p->pc_alignment_mask(); \
+       npc = PC_SERIALIZE_AFTER; \
+       STATE.pc = __npc; \
+     } while(0)
+
+#define wfi() \
+  do { set_pc_and_serialize(npc); \
+       npc = PC_SERIALIZE_WFI; \
+     } while(0)
+
+#define serialize() set_pc_and_serialize(npc)
+
+/* Sentinel PC values to serialize simulator pipeline */
+#define PC_SERIALIZE_BEFORE 3
+#define PC_SERIALIZE_AFTER 5
+#define PC_SERIALIZE_WFI 7
+#define invalid_pc(pc) ((pc) & 1)
+
+/* Convenience wrappers to simplify softfloat code sequences */
+#define isBoxedF32(r) (isBoxedF64(r) && ((uint32_t)((r.v[0] >> 32) + 1) == 0))
+#define unboxF32(r) (isBoxedF32(r) ? (uint32_t)r.v[0] : defaultNaNF32UI)
+#define isBoxedF64(r) ((r.v[1] + 1) == 0)
+#define unboxF64(r) (isBoxedF64(r) ? r.v[0] : defaultNaNF64UI)
+typedef float128_t freg_t;
+inline float32_t f32(uint32_t v) { return { v }; }
+inline float64_t f64(uint64_t v) { return { v }; }
+inline float32_t f32(freg_t r) { return f32(unboxF32(r)); }
+inline float64_t f64(freg_t r) { return f64(unboxF64(r)); }
+inline float128_t f128(freg_t r) { return r; }
+inline freg_t freg(float32_t f) { return { ((uint64_t)-1 << 32) | f.v, (uint64_t)-1 }; }
+inline freg_t freg(float64_t f) { return { f.v, (uint64_t)-1 }; }
+inline freg_t freg(float128_t f) { return f; }
+#define F32_SIGN ((uint32_t)1 << 31)
+#define F64_SIGN ((uint64_t)1 << 63)
+#define fsgnj32(a, b, n, x) \
+  f32((f32(a).v & ~F32_SIGN) | ((((x) ? f32(a).v : (n) ? F32_SIGN : 0) ^ f32(b).v) & F32_SIGN))
+#define fsgnj64(a, b, n, x) \
+  f64((f64(a).v & ~F64_SIGN) | ((((x) ? f64(a).v : (n) ? F64_SIGN : 0) ^ f64(b).v) & F64_SIGN))
+
+#define isNaNF128(x) isNaNF128UI(x.v[1], x.v[0])
+inline float128_t defaultNaNF128()
+{
+  float128_t nan;
+  nan.v[1] = defaultNaNF128UI64;
+  nan.v[0] = defaultNaNF128UI0;
+  return nan;
+}
+inline freg_t fsgnj128(freg_t a, freg_t b, bool n, bool x)
+{
+  a.v[1] = (a.v[1] & ~F64_SIGN) | (((x ? a.v[1] : n ? F64_SIGN : 0) ^ b.v[1]) & F64_SIGN);
+  return a;
+}
+inline freg_t f128_negate(freg_t a)
+{
+  a.v[1] ^= F64_SIGN;
+  return a;
+}
+
+#define validate_csr(which, write) ({ \
+  if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \
+  STATE.serialized = false; \
+  unsigned csr_priv = get_field((which), 0x300); \
+  unsigned csr_read_only = get_field((which), 0xC00) == 3; \
+  if (((write) && csr_read_only) || STATE.prv < csr_priv) \
+    throw trap_illegal_instruction(0); \
+  (which); })
+
+// Seems that 0x0 doesn't work.
+#define DEBUG_START             0x100
+#define DEBUG_END                 (0x1000 - 1)
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/devices.cc b/tb/riscv-isa-sim/riscv/devices.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bcdd3a19ea89d05b978eb91162d38e9f3db8c66f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/devices.cc
@@ -0,0 +1,50 @@
+#include "devices.h"
+
+void bus_t::add_device(reg_t addr, abstract_device_t* dev)
+{
+  // Searching devices via lower_bound/upper_bound
+  // implicitly relies on the underlying std::map 
+  // container to sort the keys and provide ordered
+  // iteration over this sort, which it does. (python's
+  // SortedDict is a good analogy)
+  devices[addr] = dev;
+}
+
+bool bus_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  // Find the device with the base address closest to but
+  // less than addr (price-is-right search)
+  auto it = devices.upper_bound(addr);
+  if (devices.empty() || it == devices.begin()) {
+    // Either the bus is empty, or there weren't 
+    // any items with a base address <= addr
+    return false;
+  }
+  // Found at least one item with base address <= addr
+  // The iterator points to the device after this, so
+  // go back by one item.
+  it--;
+  return it->second->load(addr - it->first, len, bytes);
+}
+
+bool bus_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  // See comments in bus_t::load
+  auto it = devices.upper_bound(addr);
+  if (devices.empty() || it == devices.begin()) {
+    return false;
+  }
+  it--;
+  return it->second->store(addr - it->first, len, bytes);
+}
+
+std::pair<reg_t, abstract_device_t*> bus_t::find_device(reg_t addr)
+{
+  // See comments in bus_t::load
+  auto it = devices.upper_bound(addr);
+  if (devices.empty() || it == devices.begin()) {
+    return std::make_pair((reg_t)0, (abstract_device_t*)NULL);
+  }
+  it--;
+  return std::make_pair(it->first, it->second);
+}
diff --git a/tb/riscv-isa-sim/riscv/devices.h b/tb/riscv-isa-sim/riscv/devices.h
new file mode 100644
index 0000000000000000000000000000000000000000..1276ac314e9419a0f3f411663d9f544a2ae72855
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/devices.h
@@ -0,0 +1,107 @@
+#ifndef _RISCV_DEVICES_H
+#define _RISCV_DEVICES_H
+
+#include "decode.h"
+#include <cstdlib>
+#include <string>
+#include <map>
+#include <vector>
+#include <fstream>
+
+class processor_t;
+
+class abstract_device_t {
+ public:
+  virtual bool load(reg_t addr, size_t len, uint8_t* bytes) = 0;
+  virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
+  virtual ~abstract_device_t() {}
+};
+
+class bus_t : public abstract_device_t {
+ public:
+  bool load(reg_t addr, size_t len, uint8_t* bytes);
+  bool store(reg_t addr, size_t len, const uint8_t* bytes);
+  void add_device(reg_t addr, abstract_device_t* dev);
+
+  std::pair<reg_t, abstract_device_t*> find_device(reg_t addr);
+
+ private:
+  std::map<reg_t, abstract_device_t*> devices;
+};
+
+class rom_device_t : public abstract_device_t {
+ public:
+  rom_device_t(std::vector<char> data);
+  bool load(reg_t addr, size_t len, uint8_t* bytes);
+  bool store(reg_t addr, size_t len, const uint8_t* bytes);
+  const std::vector<char>& contents() { return data; }
+ private:
+  std::vector<char> data;
+};
+
+class mem_t : public abstract_device_t {
+ public:
+  mem_t(size_t size) : len(size) {
+    if (!size)
+      throw std::runtime_error("zero bytes of target memory requested");
+    data = (char*)calloc(1, size);
+    if (!data)
+      throw std::runtime_error("couldn't allocate " + std::to_string(size) + " bytes of target memory");
+  }
+  mem_t(const mem_t& that) = delete;
+  ~mem_t() { free(data); }
+
+  bool load(reg_t addr, size_t len, uint8_t* bytes) { return false; }
+  bool store(reg_t addr, size_t len, const uint8_t* bytes) { return false; }
+  char* contents() { return data; }
+  size_t size() { return len; }
+
+ private:
+  char* data;
+  size_t len;
+};
+
+class clint_t : public abstract_device_t {
+ public:
+  clint_t(std::vector<processor_t*>&);
+  bool load(reg_t addr, size_t len, uint8_t* bytes);
+  bool store(reg_t addr, size_t len, const uint8_t* bytes);
+  void reset();
+  size_t size() { return CLINT_SIZE; }
+  void increment(reg_t inc);
+ private:
+  typedef uint64_t mtime_t;
+  typedef uint64_t mtimecmp_t;
+  typedef uint32_t msip_t;
+  std::vector<processor_t*>& procs;
+  mtime_t mtime;
+  std::vector<mtimecmp_t> mtimecmp;
+};
+
+class uart_t : public abstract_device_t {
+ public:
+  uart_t();
+  bool load(reg_t addr, size_t len, uint8_t* bytes);
+  bool store(reg_t addr, size_t len, const uint8_t* bytes);
+ private:
+  uint8_t ier;
+  uint8_t dll;
+  uint8_t dlm;
+  uint8_t lcr;
+  uint8_t lsr;
+  uint8_t scr;
+  uint8_t msr;
+  uint8_t mcr;
+  bool fifo_enabled;
+};
+
+class dump_t : public abstract_device_t {
+ public:
+  dump_t();
+  bool load(reg_t addr, size_t len, uint8_t* bytes);
+  bool store(reg_t addr, size_t len, const uint8_t* bytes);
+ private:
+  std::ofstream ofs;
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/disasm.h b/tb/riscv-isa-sim/riscv/disasm.h
new file mode 100644
index 0000000000000000000000000000000000000000..94e007a12d32ff254a079313f9b798594cd2e0f2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/disasm.h
@@ -0,0 +1,74 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_DISASM_H
+#define _RISCV_DISASM_H
+
+#include "decode.h"
+#include <string>
+#include <sstream>
+#include <vector>
+
+extern const char* xpr_name[NXPR];
+extern const char* fpr_name[NFPR];
+extern const char* csr_name(int which);
+
+class arg_t
+{
+ public:
+  virtual std::string to_string(insn_t val) const = 0;
+  virtual ~arg_t() {}
+};
+
+class disasm_insn_t
+{
+ public:
+  disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
+                const std::vector<const arg_t*>& args)
+    : match(match), mask(mask), args(args), name(name) {}
+
+  bool operator == (insn_t insn) const
+  {
+    return (insn.bits() & mask) == match;
+  }
+
+  std::string to_string(insn_t insn) const
+  {
+    std::stringstream s;
+    int len;
+    for (len = 0; name[len]; len++)
+      s << (name[len] == '_' ? '.' : name[len]);
+
+    if (args.size())
+    {
+      s << std::string(std::max(1, 8 - len), ' ');
+      for (size_t i = 0; i < args.size()-1; i++)
+        s << args[i]->to_string(insn) << ", ";
+      s << args[args.size()-1]->to_string(insn);
+    }
+    return s.str();
+  }
+
+  uint32_t get_match() const { return match; }
+  uint32_t get_mask() const { return mask; }
+
+ private:
+  uint32_t match;
+  uint32_t mask;
+  std::vector<const arg_t*> args;
+  const char* name;
+};
+
+class disassembler_t
+{
+ public:
+  disassembler_t(int xlen);
+  ~disassembler_t();
+  std::string disassemble(insn_t insn) const;
+  void add_insn(disasm_insn_t* insn);
+ private:
+  static const int HASH_SIZE = 256;
+  std::vector<const disasm_insn_t*> chain[HASH_SIZE+1];
+  const disasm_insn_t* lookup(insn_t insn) const;
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/dts.cc b/tb/riscv-isa-sim/riscv/dts.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6fa4ba6836e24d39a4eec078f2e5ba8737492c33
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/dts.cc
@@ -0,0 +1,166 @@
+// See LICENSE for license details.
+
+#include "dts.h"
+#include <iostream>
+#include <sstream>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+
+std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
+                     std::vector<processor_t*> procs,
+                     std::vector<std::pair<reg_t, mem_t*>> mems)
+{
+  std::stringstream s;
+  s << std::dec <<
+         "/dts-v1/;\n"
+         "\n"
+         "/ {\n"
+         "  #address-cells = <2>;\n"
+         "  #size-cells = <2>;\n"
+         "  compatible = \"ucbbar,spike-bare-dev\";\n"
+         "  model = \"ucbbar,spike-bare\";\n"
+         "  cpus {\n"
+         "    #address-cells = <1>;\n"
+         "    #size-cells = <0>;\n"
+         "    timebase-frequency = <" << (cpu_hz/insns_per_rtc_tick) << ">;\n";
+  for (size_t i = 0; i < procs.size(); i++) {
+    s << "    CPU" << i << ": cpu@" << i << " {\n"
+         "      device_type = \"cpu\";\n"
+         "      reg = <" << i << ">;\n"
+         "      status = \"okay\";\n"
+         "      compatible = \"riscv\";\n"
+         "      riscv,isa = \"" << procs[i]->get_isa_string() << "\";\n"
+         "      mmu-type = \"riscv," << (procs[i]->get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n"
+         "      clock-frequency = <" << cpu_hz << ">;\n"
+         "      CPU" << i << "_intc: interrupt-controller {\n"
+         "        #interrupt-cells = <1>;\n"
+         "        interrupt-controller;\n"
+         "        compatible = \"riscv,cpu-intc\";\n"
+         "      };\n"
+         "    };\n";
+  }
+  s <<   "  };\n";
+  for (auto& m : mems) {
+    s << std::hex <<
+         "  memory@" << m.first << " {\n"
+         "    device_type = \"memory\";\n"
+         "    reg = <0x" << (m.first >> 32) << " 0x" << (m.first & (uint32_t)-1) <<
+                   " 0x" << (m.second->size() >> 32) << " 0x" << (m.second->size() & (uint32_t)-1) << ">;\n"
+         "  };\n";
+  }
+  s <<   "  soc {\n"
+         "    #address-cells = <2>;\n"
+         "    #size-cells = <2>;\n"
+         "    compatible = \"ucbbar,spike-bare-soc\", \"simple-bus\";\n"
+       "    ranges;\n"
+         "    clint@" << CLINT_BASE << " {\n"
+         "      compatible = \"riscv,clint0\";\n"
+         "      interrupts-extended = <" << std::dec;
+  for (size_t i = 0; i < procs.size(); i++)
+    s << "&CPU" << i << "_intc 3 &CPU" << i << "_intc 7 ";
+  reg_t clintbs = CLINT_BASE;
+  reg_t clintsz = CLINT_SIZE;
+  s << std::hex << ">;\n"
+         "      reg = <0x" << (clintbs >> 32) << " 0x" << (clintbs & (uint32_t)-1) <<
+                     " 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n"
+         "    };\n"
+         "  };\n"
+         // "  htif {\n"
+         // "    compatible = \"ucb,htif0\";\n"
+         // "  };\n"
+         "  uart@" << UART_BASE << " {\n"
+         "    compatible = \"ns16750\";\n"
+         "    reg = <0x0 0x10000000 0x0 0x1000>;\n"
+         "    clock-frequency = <50000000>;\n"
+         "    current-speed = <115200>;\n"
+         // "    interrupt-parent = <&PLIC0>;\n"
+         // "    interrupts = <1>;\n"
+         "    reg-shift = <2>;\n"
+         "    reg-io-width = <4>;\n"
+         "  };\n"
+         "};\n";
+  return s.str();
+}
+
+std::string dts_compile(const std::string& dts)
+{
+  // Convert the DTS to DTB
+  int dts_pipe[2];
+  pid_t dts_pid;
+
+  if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) {
+    std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl;
+    exit(1);
+  }
+
+  // Child process to output dts
+  if (dts_pid == 0) {
+    close(dts_pipe[0]);
+    int step, len = dts.length();
+    const char *buf = dts.c_str();
+    for (int done = 0; done < len; done += step) {
+      step = write(dts_pipe[1], buf+done, len-done);
+      if (step == -1) {
+        std::cerr << "Failed to write dts: " << strerror(errno) << std::endl;
+        exit(1);
+      }
+    }
+    close(dts_pipe[1]);
+    exit(0);
+  }
+
+  pid_t dtb_pid;
+  int dtb_pipe[2];
+  if (pipe(dtb_pipe) != 0 || (dtb_pid = fork()) < 0) {
+    std::cerr << "Failed to fork dtb child: " << strerror(errno) << std::endl;
+    exit(1);
+  }
+
+  // Child process to output dtb
+  if (dtb_pid == 0) {
+    dup2(dts_pipe[0], 0);
+    dup2(dtb_pipe[1], 1);
+    close(dts_pipe[0]);
+    close(dts_pipe[1]);
+    close(dtb_pipe[0]);
+    close(dtb_pipe[1]);
+    execl(DTC, DTC, "-O", "dtb", 0);
+    std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl;
+    exit(1);
+  }
+
+  close(dts_pipe[1]);
+  close(dts_pipe[0]);
+  close(dtb_pipe[1]);
+
+  // Read-out dtb
+  std::stringstream dtb;
+
+  int got;
+  char buf[4096];
+  while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) {
+    dtb.write(buf, got);
+  }
+  if (got == -1) {
+    std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl;
+    exit(1);
+  }
+  close(dtb_pipe[0]);
+
+  // Reap children
+  int status;
+  waitpid(dts_pid, &status, 0);
+  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+    std::cerr << "Child dts process failed" << std::endl;
+    exit(1);
+  }
+  waitpid(dtb_pid, &status, 0);
+  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+    std::cerr << "Child dtb process failed" << std::endl;
+    exit(1);
+  }
+
+  return dtb.str();
+}
diff --git a/tb/riscv-isa-sim/riscv/dts.h b/tb/riscv-isa-sim/riscv/dts.h
new file mode 100644
index 0000000000000000000000000000000000000000..ec0aa6161bc9080e66b048450fa302bc6b62b764
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/dts.h
@@ -0,0 +1,15 @@
+// See LICENSE for license details.
+#ifndef _RISCV_DTS_H
+#define _RISCV_DTS_H
+
+#include "processor.h"
+#include "mmu.h"
+#include <string>
+
+std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
+                     std::vector<processor_t*> procs,
+                     std::vector<std::pair<reg_t, mem_t*>> mems);
+
+std::string dts_compile(const std::string& dts);
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/dump.cc b/tb/riscv-isa-sim/riscv/dump.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9df38e62fd80db83c86696c98115948bccf7c5f1
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/dump.cc
@@ -0,0 +1,21 @@
+#include "devices.h"
+#include "processor.h"
+#include <fstream>
+
+dump_t::dump_t() : ofs("dump.bin")
+{
+  // printf("Calling Dump\n");
+}
+
+bool dump_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  return true;
+}
+
+bool dump_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  // printf("DUmpping\n");
+  ofs.write(reinterpret_cast<const char *>(bytes), len);
+  return true;
+}
+
diff --git a/tb/riscv-isa-sim/riscv/encoding.h b/tb/riscv-isa-sim/riscv/encoding.h
new file mode 100644
index 0000000000000000000000000000000000000000..50b95d45706ca61204f7d3fd2b123f9edd581a7e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/encoding.h
@@ -0,0 +1,1475 @@
+// See LICENSE for license details.
+
+#ifndef RISCV_CSR_ENCODING_H
+#define RISCV_CSR_ENCODING_H
+
+#define MSTATUS_UIE         0x00000001
+#define MSTATUS_SIE         0x00000002
+#define MSTATUS_HIE         0x00000004
+#define MSTATUS_MIE         0x00000008
+#define MSTATUS_UPIE        0x00000010
+#define MSTATUS_SPIE        0x00000020
+#define MSTATUS_HPIE        0x00000040
+#define MSTATUS_MPIE        0x00000080
+#define MSTATUS_SPP         0x00000100
+#define MSTATUS_HPP         0x00000600
+#define MSTATUS_MPP         0x00001800
+#define MSTATUS_FS          0x00006000
+#define MSTATUS_XS          0x00018000
+#define MSTATUS_MPRV        0x00020000
+#define MSTATUS_SUM         0x00040000
+#define MSTATUS_MXR         0x00080000
+#define MSTATUS_TVM         0x00100000
+#define MSTATUS_TW          0x00200000
+#define MSTATUS_TSR         0x00400000
+#define MSTATUS32_SD        0x80000000
+#define MSTATUS_UXL         0x0000000300000000
+#define MSTATUS_SXL         0x0000000C00000000
+#define MSTATUS64_SD        0x8000000000000000
+
+#define SSTATUS_UIE         0x00000001
+#define SSTATUS_SIE         0x00000002
+#define SSTATUS_UPIE        0x00000010
+#define SSTATUS_SPIE        0x00000020
+#define SSTATUS_SPP         0x00000100
+#define SSTATUS_FS          0x00006000
+#define SSTATUS_XS          0x00018000
+#define SSTATUS_SUM         0x00040000
+#define SSTATUS_MXR         0x00080000
+#define SSTATUS32_SD        0x80000000
+#define SSTATUS_UXL         0x0000000300000000
+#define SSTATUS64_SD        0x8000000000000000
+
+#define DCSR_XDEBUGVER      (3U<<30)
+#define DCSR_NDRESET        (1<<29)
+#define DCSR_FULLRESET      (1<<28)
+#define DCSR_EBREAKM        (1<<15)
+#define DCSR_EBREAKH        (1<<14)
+#define DCSR_EBREAKS        (1<<13)
+#define DCSR_EBREAKU        (1<<12)
+#define DCSR_STOPCYCLE      (1<<10)
+#define DCSR_STOPTIME       (1<<9)
+#define DCSR_CAUSE          (7<<6)
+#define DCSR_DEBUGINT       (1<<5)
+#define DCSR_HALT           (1<<3)
+#define DCSR_STEP           (1<<2)
+#define DCSR_PRV            (3<<0)
+
+#define DCSR_CAUSE_NONE     0
+#define DCSR_CAUSE_SWBP     1
+#define DCSR_CAUSE_HWBP     2
+#define DCSR_CAUSE_DEBUGINT 3
+#define DCSR_CAUSE_STEP     4
+#define DCSR_CAUSE_HALT     5
+
+#define MCONTROL_TYPE(xlen)    (0xfULL<<((xlen)-4))
+#define MCONTROL_DMODE(xlen)   (1ULL<<((xlen)-5))
+#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
+
+#define MCONTROL_SELECT     (1<<19)
+#define MCONTROL_TIMING     (1<<18)
+#define MCONTROL_ACTION     (0x3f<<12)
+#define MCONTROL_CHAIN      (1<<11)
+#define MCONTROL_MATCH      (0xf<<7)
+#define MCONTROL_M          (1<<6)
+#define MCONTROL_H          (1<<5)
+#define MCONTROL_S          (1<<4)
+#define MCONTROL_U          (1<<3)
+#define MCONTROL_EXECUTE    (1<<2)
+#define MCONTROL_STORE      (1<<1)
+#define MCONTROL_LOAD       (1<<0)
+
+#define MCONTROL_TYPE_NONE      0
+#define MCONTROL_TYPE_MATCH     2
+
+#define MCONTROL_ACTION_DEBUG_EXCEPTION   0
+#define MCONTROL_ACTION_DEBUG_MODE        1
+#define MCONTROL_ACTION_TRACE_START       2
+#define MCONTROL_ACTION_TRACE_STOP        3
+#define MCONTROL_ACTION_TRACE_EMIT        4
+
+#define MCONTROL_MATCH_EQUAL     0
+#define MCONTROL_MATCH_NAPOT     1
+#define MCONTROL_MATCH_GE        2
+#define MCONTROL_MATCH_LT        3
+#define MCONTROL_MATCH_MASK_LOW  4
+#define MCONTROL_MATCH_MASK_HIGH 5
+
+#define MIP_SSIP            (1 << IRQ_S_SOFT)
+#define MIP_HSIP            (1 << IRQ_H_SOFT)
+#define MIP_MSIP            (1 << IRQ_M_SOFT)
+#define MIP_STIP            (1 << IRQ_S_TIMER)
+#define MIP_HTIP            (1 << IRQ_H_TIMER)
+#define MIP_MTIP            (1 << IRQ_M_TIMER)
+#define MIP_SEIP            (1 << IRQ_S_EXT)
+#define MIP_HEIP            (1 << IRQ_H_EXT)
+#define MIP_MEIP            (1 << IRQ_M_EXT)
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+
+#define PRV_U 0
+#define PRV_S 1
+#define PRV_H 2
+#define PRV_M 3
+
+#define SATP32_MODE 0x80000000
+#define SATP32_ASID 0x7FC00000
+#define SATP32_PPN  0x003FFFFF
+#define SATP64_MODE 0xF000000000000000
+#define SATP64_ASID 0x0FFFF00000000000
+#define SATP64_PPN  0x00000FFFFFFFFFFF
+
+#define SATP_MODE_OFF  0
+#define SATP_MODE_SV32 1
+#define SATP_MODE_SV39 8
+#define SATP_MODE_SV48 9
+#define SATP_MODE_SV57 10
+#define SATP_MODE_SV64 11
+
+#define PMP_R     0x01
+#define PMP_W     0x02
+#define PMP_X     0x04
+#define PMP_A     0x18
+#define PMP_L     0x80
+#define PMP_SHIFT 2
+
+#define PMP_TOR   0x08
+#define PMP_NA4   0x10
+#define PMP_NAPOT 0x18
+
+#define IRQ_S_SOFT   1
+#define IRQ_H_SOFT   2
+#define IRQ_M_SOFT   3
+#define IRQ_S_TIMER  5
+#define IRQ_H_TIMER  6
+#define IRQ_M_TIMER  7
+#define IRQ_S_EXT    9
+#define IRQ_H_EXT    10
+#define IRQ_M_EXT    11
+#define IRQ_COP      12
+#define IRQ_HOST     13
+
+#define DEFAULT_RSTVEC     0x00010000
+#define CLINT_BASE         0x02000000
+#define CLINT_SIZE         0x000c0000
+#define UART_BASE          0x10000000
+#define UART_SIZE          0x00010000
+#define EXT_IO_BASE        0x40000000
+#define DRAM_BASE          0x80000000
+#define DUMP_BASE          0x82000000
+#define DUMP_SIZE          0x20000000
+
+// page table entry (PTE) fields
+#define PTE_V     0x001 // Valid
+#define PTE_R     0x002 // Read
+#define PTE_W     0x004 // Write
+#define PTE_X     0x008 // Execute
+#define PTE_U     0x010 // User
+#define PTE_G     0x020 // Global
+#define PTE_A     0x040 // Accessed
+#define PTE_D     0x080 // Dirty
+#define PTE_SOFT  0x300 // Reserved for Software
+
+#define PTE_PPN_SHIFT 10
+
+#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
+
+#ifdef __riscv
+
+#if __riscv_xlen == 64
+# define MSTATUS_SD MSTATUS64_SD
+# define SSTATUS_SD SSTATUS64_SD
+# define RISCV_PGLEVEL_BITS 9
+# define SATP_MODE SATP64_MODE
+#else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
+# define RISCV_PGLEVEL_BITS 10
+# define SATP_MODE SATP32_MODE
+#endif
+#define RISCV_PGSHIFT 12
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
+
+#ifndef __ASSEMBLER__
+
+#ifdef __GNUC__
+
+#define read_csr(reg) ({ unsigned long __tmp; \
+  asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+  __tmp; })
+
+#define write_csr(reg, val) ({ \
+  asm volatile ("csrw " #reg ", %0" :: "rK"(val)); })
+
+#define swap_csr(reg, val) ({ unsigned long __tmp; \
+  asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \
+  __tmp; })
+
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
+  asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+  __tmp; })
+
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
+  asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
+  __tmp; })
+
+#define rdtime() read_csr(time)
+#define rdcycle() read_csr(cycle)
+#define rdinstret() read_csr(instret)
+
+#endif
+
+#endif
+
+#endif
+
+#endif
+/* Automatically generated by parse-opcodes.  */
+#ifndef RISCV_ENCODING_H
+#define RISCV_ENCODING_H
+#define MATCH_BEQ 0x63
+#define MASK_BEQ  0x707f
+#define MATCH_BNE 0x1063
+#define MASK_BNE  0x707f
+#define MATCH_BLT 0x4063
+#define MASK_BLT  0x707f
+#define MATCH_BGE 0x5063
+#define MASK_BGE  0x707f
+#define MATCH_BLTU 0x6063
+#define MASK_BLTU  0x707f
+#define MATCH_BGEU 0x7063
+#define MASK_BGEU  0x707f
+#define MATCH_JALR 0x67
+#define MASK_JALR  0x707f
+#define MATCH_JAL 0x6f
+#define MASK_JAL  0x7f
+#define MATCH_LUI 0x37
+#define MASK_LUI  0x7f
+#define MATCH_AUIPC 0x17
+#define MASK_AUIPC  0x7f
+#define MATCH_ADDI 0x13
+#define MASK_ADDI  0x707f
+#define MATCH_SLLI 0x1013
+#define MASK_SLLI  0xfc00707f
+#define MATCH_SLTI 0x2013
+#define MASK_SLTI  0x707f
+#define MATCH_SLTIU 0x3013
+#define MASK_SLTIU  0x707f
+#define MATCH_XORI 0x4013
+#define MASK_XORI  0x707f
+#define MATCH_SRLI 0x5013
+#define MASK_SRLI  0xfc00707f
+#define MATCH_SRAI 0x40005013
+#define MASK_SRAI  0xfc00707f
+#define MATCH_ORI 0x6013
+#define MASK_ORI  0x707f
+#define MATCH_ANDI 0x7013
+#define MASK_ANDI  0x707f
+#define MATCH_ADD 0x33
+#define MASK_ADD  0xfe00707f
+#define MATCH_SUB 0x40000033
+#define MASK_SUB  0xfe00707f
+#define MATCH_SLL 0x1033
+#define MASK_SLL  0xfe00707f
+#define MATCH_SLT 0x2033
+#define MASK_SLT  0xfe00707f
+#define MATCH_SLTU 0x3033
+#define MASK_SLTU  0xfe00707f
+#define MATCH_XOR 0x4033
+#define MASK_XOR  0xfe00707f
+#define MATCH_SRL 0x5033
+#define MASK_SRL  0xfe00707f
+#define MATCH_SRA 0x40005033
+#define MASK_SRA  0xfe00707f
+#define MATCH_OR 0x6033
+#define MASK_OR  0xfe00707f
+#define MATCH_AND 0x7033
+#define MASK_AND  0xfe00707f
+#define MATCH_ADDIW 0x1b
+#define MASK_ADDIW  0x707f
+#define MATCH_SLLIW 0x101b
+#define MASK_SLLIW  0xfe00707f
+#define MATCH_SRLIW 0x501b
+#define MASK_SRLIW  0xfe00707f
+#define MATCH_SRAIW 0x4000501b
+#define MASK_SRAIW  0xfe00707f
+#define MATCH_ADDW 0x3b
+#define MASK_ADDW  0xfe00707f
+#define MATCH_SUBW 0x4000003b
+#define MASK_SUBW  0xfe00707f
+#define MATCH_SLLW 0x103b
+#define MASK_SLLW  0xfe00707f
+#define MATCH_SRLW 0x503b
+#define MASK_SRLW  0xfe00707f
+#define MATCH_SRAW 0x4000503b
+#define MASK_SRAW  0xfe00707f
+#define MATCH_LB 0x3
+#define MASK_LB  0x707f
+#define MATCH_LH 0x1003
+#define MASK_LH  0x707f
+#define MATCH_LW 0x2003
+#define MASK_LW  0x707f
+#define MATCH_LD 0x3003
+#define MASK_LD  0x707f
+#define MATCH_LBU 0x4003
+#define MASK_LBU  0x707f
+#define MATCH_LHU 0x5003
+#define MASK_LHU  0x707f
+#define MATCH_LWU 0x6003
+#define MASK_LWU  0x707f
+#define MATCH_SB 0x23
+#define MASK_SB  0x707f
+#define MATCH_SH 0x1023
+#define MASK_SH  0x707f
+#define MATCH_SW 0x2023
+#define MASK_SW  0x707f
+#define MATCH_SD 0x3023
+#define MASK_SD  0x707f
+#define MATCH_FENCE 0xf
+#define MASK_FENCE  0x707f
+#define MATCH_FENCE_I 0x100f
+#define MASK_FENCE_I  0x707f
+#define MATCH_MUL 0x2000033
+#define MASK_MUL  0xfe00707f
+#define MATCH_MULH 0x2001033
+#define MASK_MULH  0xfe00707f
+#define MATCH_MULHSU 0x2002033
+#define MASK_MULHSU  0xfe00707f
+#define MATCH_MULHU 0x2003033
+#define MASK_MULHU  0xfe00707f
+#define MATCH_DIV 0x2004033
+#define MASK_DIV  0xfe00707f
+#define MATCH_DIVU 0x2005033
+#define MASK_DIVU  0xfe00707f
+#define MATCH_REM 0x2006033
+#define MASK_REM  0xfe00707f
+#define MATCH_REMU 0x2007033
+#define MASK_REMU  0xfe00707f
+#define MATCH_MULW 0x200003b
+#define MASK_MULW  0xfe00707f
+#define MATCH_DIVW 0x200403b
+#define MASK_DIVW  0xfe00707f
+#define MATCH_DIVUW 0x200503b
+#define MASK_DIVUW  0xfe00707f
+#define MATCH_REMW 0x200603b
+#define MASK_REMW  0xfe00707f
+#define MATCH_REMUW 0x200703b
+#define MASK_REMUW  0xfe00707f
+#define MATCH_AMOADD_W 0x202f
+#define MASK_AMOADD_W  0xf800707f
+#define MATCH_AMOXOR_W 0x2000202f
+#define MASK_AMOXOR_W  0xf800707f
+#define MATCH_AMOOR_W 0x4000202f
+#define MASK_AMOOR_W  0xf800707f
+#define MATCH_AMOAND_W 0x6000202f
+#define MASK_AMOAND_W  0xf800707f
+#define MATCH_AMOMIN_W 0x8000202f
+#define MASK_AMOMIN_W  0xf800707f
+#define MATCH_AMOMAX_W 0xa000202f
+#define MASK_AMOMAX_W  0xf800707f
+#define MATCH_AMOMINU_W 0xc000202f
+#define MASK_AMOMINU_W  0xf800707f
+#define MATCH_AMOMAXU_W 0xe000202f
+#define MASK_AMOMAXU_W  0xf800707f
+#define MATCH_AMOSWAP_W 0x800202f
+#define MASK_AMOSWAP_W  0xf800707f
+#define MATCH_LR_W 0x1000202f
+#define MASK_LR_W  0xf9f0707f
+#define MATCH_SC_W 0x1800202f
+#define MASK_SC_W  0xf800707f
+#define MATCH_AMOADD_D 0x302f
+#define MASK_AMOADD_D  0xf800707f
+#define MATCH_AMOXOR_D 0x2000302f
+#define MASK_AMOXOR_D  0xf800707f
+#define MATCH_AMOOR_D 0x4000302f
+#define MASK_AMOOR_D  0xf800707f
+#define MATCH_AMOAND_D 0x6000302f
+#define MASK_AMOAND_D  0xf800707f
+#define MATCH_AMOMIN_D 0x8000302f
+#define MASK_AMOMIN_D  0xf800707f
+#define MATCH_AMOMAX_D 0xa000302f
+#define MASK_AMOMAX_D  0xf800707f
+#define MATCH_AMOMINU_D 0xc000302f
+#define MASK_AMOMINU_D  0xf800707f
+#define MATCH_AMOMAXU_D 0xe000302f
+#define MASK_AMOMAXU_D  0xf800707f
+#define MATCH_AMOSWAP_D 0x800302f
+#define MASK_AMOSWAP_D  0xf800707f
+#define MATCH_LR_D 0x1000302f
+#define MASK_LR_D  0xf9f0707f
+#define MATCH_SC_D 0x1800302f
+#define MASK_SC_D  0xf800707f
+#define MATCH_ECALL 0x73
+#define MASK_ECALL  0xffffffff
+#define MATCH_EBREAK 0x100073
+#define MASK_EBREAK  0xffffffff
+#define MATCH_URET 0x200073
+#define MASK_URET  0xffffffff
+#define MATCH_SRET 0x10200073
+#define MASK_SRET  0xffffffff
+#define MATCH_MRET 0x30200073
+#define MASK_MRET  0xffffffff
+#define MATCH_DRET 0x7b200073
+#define MASK_DRET  0xffffffff
+#define MATCH_SFENCE_VMA 0x12000073
+#define MASK_SFENCE_VMA  0xfe007fff
+#define MATCH_WFI 0x10500073
+#define MASK_WFI  0xffffffff
+#define MATCH_CSRRW 0x1073
+#define MASK_CSRRW  0x707f
+#define MATCH_CSRRS 0x2073
+#define MASK_CSRRS  0x707f
+#define MATCH_CSRRC 0x3073
+#define MASK_CSRRC  0x707f
+#define MATCH_CSRRWI 0x5073
+#define MASK_CSRRWI  0x707f
+#define MATCH_CSRRSI 0x6073
+#define MASK_CSRRSI  0x707f
+#define MATCH_CSRRCI 0x7073
+#define MASK_CSRRCI  0x707f
+#define MATCH_FADD_S 0x53
+#define MASK_FADD_S  0xfe00007f
+#define MATCH_FSUB_S 0x8000053
+#define MASK_FSUB_S  0xfe00007f
+#define MATCH_FMUL_S 0x10000053
+#define MASK_FMUL_S  0xfe00007f
+#define MATCH_FDIV_S 0x18000053
+#define MASK_FDIV_S  0xfe00007f
+#define MATCH_FSGNJ_S 0x20000053
+#define MASK_FSGNJ_S  0xfe00707f
+#define MATCH_FSGNJN_S 0x20001053
+#define MASK_FSGNJN_S  0xfe00707f
+#define MATCH_FSGNJX_S 0x20002053
+#define MASK_FSGNJX_S  0xfe00707f
+#define MATCH_FMIN_S 0x28000053
+#define MASK_FMIN_S  0xfe00707f
+#define MATCH_FMAX_S 0x28001053
+#define MASK_FMAX_S  0xfe00707f
+#define MATCH_FSQRT_S 0x58000053
+#define MASK_FSQRT_S  0xfff0007f
+#define MATCH_FADD_D 0x2000053
+#define MASK_FADD_D  0xfe00007f
+#define MATCH_FSUB_D 0xa000053
+#define MASK_FSUB_D  0xfe00007f
+#define MATCH_FMUL_D 0x12000053
+#define MASK_FMUL_D  0xfe00007f
+#define MATCH_FDIV_D 0x1a000053
+#define MASK_FDIV_D  0xfe00007f
+#define MATCH_FSGNJ_D 0x22000053
+#define MASK_FSGNJ_D  0xfe00707f
+#define MATCH_FSGNJN_D 0x22001053
+#define MASK_FSGNJN_D  0xfe00707f
+#define MATCH_FSGNJX_D 0x22002053
+#define MASK_FSGNJX_D  0xfe00707f
+#define MATCH_FMIN_D 0x2a000053
+#define MASK_FMIN_D  0xfe00707f
+#define MATCH_FMAX_D 0x2a001053
+#define MASK_FMAX_D  0xfe00707f
+#define MATCH_FCVT_S_D 0x40100053
+#define MASK_FCVT_S_D  0xfff0007f
+#define MATCH_FCVT_D_S 0x42000053
+#define MASK_FCVT_D_S  0xfff0007f
+#define MATCH_FSQRT_D 0x5a000053
+#define MASK_FSQRT_D  0xfff0007f
+#define MATCH_FADD_Q 0x6000053
+#define MASK_FADD_Q  0xfe00007f
+#define MATCH_FSUB_Q 0xe000053
+#define MASK_FSUB_Q  0xfe00007f
+#define MATCH_FMUL_Q 0x16000053
+#define MASK_FMUL_Q  0xfe00007f
+#define MATCH_FDIV_Q 0x1e000053
+#define MASK_FDIV_Q  0xfe00007f
+#define MATCH_FSGNJ_Q 0x26000053
+#define MASK_FSGNJ_Q  0xfe00707f
+#define MATCH_FSGNJN_Q 0x26001053
+#define MASK_FSGNJN_Q  0xfe00707f
+#define MATCH_FSGNJX_Q 0x26002053
+#define MASK_FSGNJX_Q  0xfe00707f
+#define MATCH_FMIN_Q 0x2e000053
+#define MASK_FMIN_Q  0xfe00707f
+#define MATCH_FMAX_Q 0x2e001053
+#define MASK_FMAX_Q  0xfe00707f
+#define MATCH_FCVT_S_Q 0x40300053
+#define MASK_FCVT_S_Q  0xfff0007f
+#define MATCH_FCVT_Q_S 0x46000053
+#define MASK_FCVT_Q_S  0xfff0007f
+#define MATCH_FCVT_D_Q 0x42300053
+#define MASK_FCVT_D_Q  0xfff0007f
+#define MATCH_FCVT_Q_D 0x46100053
+#define MASK_FCVT_Q_D  0xfff0007f
+#define MATCH_FSQRT_Q 0x5e000053
+#define MASK_FSQRT_Q  0xfff0007f
+#define MATCH_FLE_S 0xa0000053
+#define MASK_FLE_S  0xfe00707f
+#define MATCH_FLT_S 0xa0001053
+#define MASK_FLT_S  0xfe00707f
+#define MATCH_FEQ_S 0xa0002053
+#define MASK_FEQ_S  0xfe00707f
+#define MATCH_FLE_D 0xa2000053
+#define MASK_FLE_D  0xfe00707f
+#define MATCH_FLT_D 0xa2001053
+#define MASK_FLT_D  0xfe00707f
+#define MATCH_FEQ_D 0xa2002053
+#define MASK_FEQ_D  0xfe00707f
+#define MATCH_FLE_Q 0xa6000053
+#define MASK_FLE_Q  0xfe00707f
+#define MATCH_FLT_Q 0xa6001053
+#define MASK_FLT_Q  0xfe00707f
+#define MATCH_FEQ_Q 0xa6002053
+#define MASK_FEQ_Q  0xfe00707f
+#define MATCH_FCVT_W_S 0xc0000053
+#define MASK_FCVT_W_S  0xfff0007f
+#define MATCH_FCVT_WU_S 0xc0100053
+#define MASK_FCVT_WU_S  0xfff0007f
+#define MATCH_FCVT_L_S 0xc0200053
+#define MASK_FCVT_L_S  0xfff0007f
+#define MATCH_FCVT_LU_S 0xc0300053
+#define MASK_FCVT_LU_S  0xfff0007f
+#define MATCH_FMV_X_W 0xe0000053
+#define MASK_FMV_X_W  0xfff0707f
+#define MATCH_FCLASS_S 0xe0001053
+#define MASK_FCLASS_S  0xfff0707f
+#define MATCH_FCVT_W_D 0xc2000053
+#define MASK_FCVT_W_D  0xfff0007f
+#define MATCH_FCVT_WU_D 0xc2100053
+#define MASK_FCVT_WU_D  0xfff0007f
+#define MATCH_FCVT_L_D 0xc2200053
+#define MASK_FCVT_L_D  0xfff0007f
+#define MATCH_FCVT_LU_D 0xc2300053
+#define MASK_FCVT_LU_D  0xfff0007f
+#define MATCH_FMV_X_D 0xe2000053
+#define MASK_FMV_X_D  0xfff0707f
+#define MATCH_FCLASS_D 0xe2001053
+#define MASK_FCLASS_D  0xfff0707f
+#define MATCH_FCVT_W_Q 0xc6000053
+#define MASK_FCVT_W_Q  0xfff0007f
+#define MATCH_FCVT_WU_Q 0xc6100053
+#define MASK_FCVT_WU_Q  0xfff0007f
+#define MATCH_FCVT_L_Q 0xc6200053
+#define MASK_FCVT_L_Q  0xfff0007f
+#define MATCH_FCVT_LU_Q 0xc6300053
+#define MASK_FCVT_LU_Q  0xfff0007f
+#define MATCH_FMV_X_Q 0xe6000053
+#define MASK_FMV_X_Q  0xfff0707f
+#define MATCH_FCLASS_Q 0xe6001053
+#define MASK_FCLASS_Q  0xfff0707f
+#define MATCH_FCVT_S_W 0xd0000053
+#define MASK_FCVT_S_W  0xfff0007f
+#define MATCH_FCVT_S_WU 0xd0100053
+#define MASK_FCVT_S_WU  0xfff0007f
+#define MATCH_FCVT_S_L 0xd0200053
+#define MASK_FCVT_S_L  0xfff0007f
+#define MATCH_FCVT_S_LU 0xd0300053
+#define MASK_FCVT_S_LU  0xfff0007f
+#define MATCH_FMV_W_X 0xf0000053
+#define MASK_FMV_W_X  0xfff0707f
+#define MATCH_FCVT_D_W 0xd2000053
+#define MASK_FCVT_D_W  0xfff0007f
+#define MATCH_FCVT_D_WU 0xd2100053
+#define MASK_FCVT_D_WU  0xfff0007f
+#define MATCH_FCVT_D_L 0xd2200053
+#define MASK_FCVT_D_L  0xfff0007f
+#define MATCH_FCVT_D_LU 0xd2300053
+#define MASK_FCVT_D_LU  0xfff0007f
+#define MATCH_FMV_D_X 0xf2000053
+#define MASK_FMV_D_X  0xfff0707f
+#define MATCH_FCVT_Q_W 0xd6000053
+#define MASK_FCVT_Q_W  0xfff0007f
+#define MATCH_FCVT_Q_WU 0xd6100053
+#define MASK_FCVT_Q_WU  0xfff0007f
+#define MATCH_FCVT_Q_L 0xd6200053
+#define MASK_FCVT_Q_L  0xfff0007f
+#define MATCH_FCVT_Q_LU 0xd6300053
+#define MASK_FCVT_Q_LU  0xfff0007f
+#define MATCH_FMV_Q_X 0xf6000053
+#define MASK_FMV_Q_X  0xfff0707f
+#define MATCH_FLW 0x2007
+#define MASK_FLW  0x707f
+#define MATCH_FLD 0x3007
+#define MASK_FLD  0x707f
+#define MATCH_FLQ 0x4007
+#define MASK_FLQ  0x707f
+#define MATCH_FSW 0x2027
+#define MASK_FSW  0x707f
+#define MATCH_FSD 0x3027
+#define MASK_FSD  0x707f
+#define MATCH_FSQ 0x4027
+#define MASK_FSQ  0x707f
+#define MATCH_FMADD_S 0x43
+#define MASK_FMADD_S  0x600007f
+#define MATCH_FMSUB_S 0x47
+#define MASK_FMSUB_S  0x600007f
+#define MATCH_FNMSUB_S 0x4b
+#define MASK_FNMSUB_S  0x600007f
+#define MATCH_FNMADD_S 0x4f
+#define MASK_FNMADD_S  0x600007f
+#define MATCH_FMADD_D 0x2000043
+#define MASK_FMADD_D  0x600007f
+#define MATCH_FMSUB_D 0x2000047
+#define MASK_FMSUB_D  0x600007f
+#define MATCH_FNMSUB_D 0x200004b
+#define MASK_FNMSUB_D  0x600007f
+#define MATCH_FNMADD_D 0x200004f
+#define MASK_FNMADD_D  0x600007f
+#define MATCH_FMADD_Q 0x6000043
+#define MASK_FMADD_Q  0x600007f
+#define MATCH_FMSUB_Q 0x6000047
+#define MASK_FMSUB_Q  0x600007f
+#define MATCH_FNMSUB_Q 0x600004b
+#define MASK_FNMSUB_Q  0x600007f
+#define MATCH_FNMADD_Q 0x600004f
+#define MASK_FNMADD_Q  0x600007f
+#define MATCH_C_NOP 0x1
+#define MASK_C_NOP  0xffff
+#define MATCH_C_ADDI16SP 0x6101
+#define MASK_C_ADDI16SP  0xef83
+#define MATCH_C_JR 0x8002
+#define MASK_C_JR  0xf07f
+#define MATCH_C_JALR 0x9002
+#define MASK_C_JALR  0xf07f
+#define MATCH_C_EBREAK 0x9002
+#define MASK_C_EBREAK  0xffff
+#define MATCH_C_LD 0x6000
+#define MASK_C_LD  0xe003
+#define MATCH_C_SD 0xe000
+#define MASK_C_SD  0xe003
+#define MATCH_C_ADDIW 0x2001
+#define MASK_C_ADDIW  0xe003
+#define MATCH_C_LDSP 0x6002
+#define MASK_C_LDSP  0xe003
+#define MATCH_C_SDSP 0xe002
+#define MASK_C_SDSP  0xe003
+#define MATCH_C_ADDI4SPN 0x0
+#define MASK_C_ADDI4SPN  0xe003
+#define MATCH_C_FLD 0x2000
+#define MASK_C_FLD  0xe003
+#define MATCH_C_LW 0x4000
+#define MASK_C_LW  0xe003
+#define MATCH_C_FLW 0x6000
+#define MASK_C_FLW  0xe003
+#define MATCH_C_FSD 0xa000
+#define MASK_C_FSD  0xe003
+#define MATCH_C_SW 0xc000
+#define MASK_C_SW  0xe003
+#define MATCH_C_FSW 0xe000
+#define MASK_C_FSW  0xe003
+#define MATCH_C_ADDI 0x1
+#define MASK_C_ADDI  0xe003
+#define MATCH_C_JAL 0x2001
+#define MASK_C_JAL  0xe003
+#define MATCH_C_LI 0x4001
+#define MASK_C_LI  0xe003
+#define MATCH_C_LUI 0x6001
+#define MASK_C_LUI  0xe003
+#define MATCH_C_SRLI 0x8001
+#define MASK_C_SRLI  0xec03
+#define MATCH_C_SRAI 0x8401
+#define MASK_C_SRAI  0xec03
+#define MATCH_C_ANDI 0x8801
+#define MASK_C_ANDI  0xec03
+#define MATCH_C_SUB 0x8c01
+#define MASK_C_SUB  0xfc63
+#define MATCH_C_XOR 0x8c21
+#define MASK_C_XOR  0xfc63
+#define MATCH_C_OR 0x8c41
+#define MASK_C_OR  0xfc63
+#define MATCH_C_AND 0x8c61
+#define MASK_C_AND  0xfc63
+#define MATCH_C_SUBW 0x9c01
+#define MASK_C_SUBW  0xfc63
+#define MATCH_C_ADDW 0x9c21
+#define MASK_C_ADDW  0xfc63
+#define MATCH_C_J 0xa001
+#define MASK_C_J  0xe003
+#define MATCH_C_BEQZ 0xc001
+#define MASK_C_BEQZ  0xe003
+#define MATCH_C_BNEZ 0xe001
+#define MASK_C_BNEZ  0xe003
+#define MATCH_C_SLLI 0x2
+#define MASK_C_SLLI  0xe003
+#define MATCH_C_FLDSP 0x2002
+#define MASK_C_FLDSP  0xe003
+#define MATCH_C_LWSP 0x4002
+#define MASK_C_LWSP  0xe003
+#define MATCH_C_FLWSP 0x6002
+#define MASK_C_FLWSP  0xe003
+#define MATCH_C_MV 0x8002
+#define MASK_C_MV  0xf003
+#define MATCH_C_ADD 0x9002
+#define MASK_C_ADD  0xf003
+#define MATCH_C_FSDSP 0xa002
+#define MASK_C_FSDSP  0xe003
+#define MATCH_C_SWSP 0xc002
+#define MASK_C_SWSP  0xe003
+#define MATCH_C_FSWSP 0xe002
+#define MASK_C_FSWSP  0xe003
+#define MATCH_CUSTOM0 0xb
+#define MASK_CUSTOM0  0x707f
+#define MATCH_CUSTOM0_RS1 0x200b
+#define MASK_CUSTOM0_RS1  0x707f
+#define MATCH_CUSTOM0_RS1_RS2 0x300b
+#define MASK_CUSTOM0_RS1_RS2  0x707f
+#define MATCH_CUSTOM0_RD 0x400b
+#define MASK_CUSTOM0_RD  0x707f
+#define MATCH_CUSTOM0_RD_RS1 0x600b
+#define MASK_CUSTOM0_RD_RS1  0x707f
+#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
+#define MASK_CUSTOM0_RD_RS1_RS2  0x707f
+#define MATCH_CUSTOM1 0x2b
+#define MASK_CUSTOM1  0x707f
+#define MATCH_CUSTOM1_RS1 0x202b
+#define MASK_CUSTOM1_RS1  0x707f
+#define MATCH_CUSTOM1_RS1_RS2 0x302b
+#define MASK_CUSTOM1_RS1_RS2  0x707f
+#define MATCH_CUSTOM1_RD 0x402b
+#define MASK_CUSTOM1_RD  0x707f
+#define MATCH_CUSTOM1_RD_RS1 0x602b
+#define MASK_CUSTOM1_RD_RS1  0x707f
+#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
+#define MASK_CUSTOM1_RD_RS1_RS2  0x707f
+#define MATCH_CUSTOM2 0x5b
+#define MASK_CUSTOM2  0x707f
+#define MATCH_CUSTOM2_RS1 0x205b
+#define MASK_CUSTOM2_RS1  0x707f
+#define MATCH_CUSTOM2_RS1_RS2 0x305b
+#define MASK_CUSTOM2_RS1_RS2  0x707f
+#define MATCH_CUSTOM2_RD 0x405b
+#define MASK_CUSTOM2_RD  0x707f
+#define MATCH_CUSTOM2_RD_RS1 0x605b
+#define MASK_CUSTOM2_RD_RS1  0x707f
+#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
+#define MASK_CUSTOM2_RD_RS1_RS2  0x707f
+#define MATCH_CUSTOM3 0x7b
+#define MASK_CUSTOM3  0x707f
+#define MATCH_CUSTOM3_RS1 0x207b
+#define MASK_CUSTOM3_RS1  0x707f
+#define MATCH_CUSTOM3_RS1_RS2 0x307b
+#define MASK_CUSTOM3_RS1_RS2  0x707f
+#define MATCH_CUSTOM3_RD 0x407b
+#define MASK_CUSTOM3_RD  0x707f
+#define MATCH_CUSTOM3_RD_RS1 0x607b
+#define MASK_CUSTOM3_RD_RS1  0x707f
+#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
+#define MASK_CUSTOM3_RD_RS1_RS2  0x707f
+#define CSR_FFLAGS 0x1
+#define CSR_FRM 0x2
+#define CSR_FCSR 0x3
+#define CSR_CYCLE 0xc00
+#define CSR_TIME 0xc01
+#define CSR_INSTRET 0xc02
+#define CSR_HPMCOUNTER3 0xc03
+#define CSR_HPMCOUNTER4 0xc04
+#define CSR_HPMCOUNTER5 0xc05
+#define CSR_HPMCOUNTER6 0xc06
+#define CSR_HPMCOUNTER7 0xc07
+#define CSR_HPMCOUNTER8 0xc08
+#define CSR_HPMCOUNTER9 0xc09
+#define CSR_HPMCOUNTER10 0xc0a
+#define CSR_HPMCOUNTER11 0xc0b
+#define CSR_HPMCOUNTER12 0xc0c
+#define CSR_HPMCOUNTER13 0xc0d
+#define CSR_HPMCOUNTER14 0xc0e
+#define CSR_HPMCOUNTER15 0xc0f
+#define CSR_HPMCOUNTER16 0xc10
+#define CSR_HPMCOUNTER17 0xc11
+#define CSR_HPMCOUNTER18 0xc12
+#define CSR_HPMCOUNTER19 0xc13
+#define CSR_HPMCOUNTER20 0xc14
+#define CSR_HPMCOUNTER21 0xc15
+#define CSR_HPMCOUNTER22 0xc16
+#define CSR_HPMCOUNTER23 0xc17
+#define CSR_HPMCOUNTER24 0xc18
+#define CSR_HPMCOUNTER25 0xc19
+#define CSR_HPMCOUNTER26 0xc1a
+#define CSR_HPMCOUNTER27 0xc1b
+#define CSR_HPMCOUNTER28 0xc1c
+#define CSR_HPMCOUNTER29 0xc1d
+#define CSR_HPMCOUNTER30 0xc1e
+#define CSR_HPMCOUNTER31 0xc1f
+#define CSR_SSTATUS 0x100
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+#define CSR_SCOUNTEREN 0x106
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SCAUSE 0x142
+#define CSR_STVAL 0x143
+#define CSR_SIP 0x144
+#define CSR_SATP 0x180
+#define CSR_MSTATUS 0x300
+#define CSR_MISA 0x301
+#define CSR_MEDELEG 0x302
+#define CSR_MIDELEG 0x303
+#define CSR_MIE 0x304
+#define CSR_MTVEC 0x305
+#define CSR_MCOUNTEREN 0x306
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MTVAL 0x343
+#define CSR_MIP 0x344
+#define CSR_PMPCFG0 0x3a0
+#define CSR_PMPCFG1 0x3a1
+#define CSR_PMPCFG2 0x3a2
+#define CSR_PMPCFG3 0x3a3
+#define CSR_PMPADDR0 0x3b0
+#define CSR_PMPADDR1 0x3b1
+#define CSR_PMPADDR2 0x3b2
+#define CSR_PMPADDR3 0x3b3
+#define CSR_PMPADDR4 0x3b4
+#define CSR_PMPADDR5 0x3b5
+#define CSR_PMPADDR6 0x3b6
+#define CSR_PMPADDR7 0x3b7
+#define CSR_PMPADDR8 0x3b8
+#define CSR_PMPADDR9 0x3b9
+#define CSR_PMPADDR10 0x3ba
+#define CSR_PMPADDR11 0x3bb
+#define CSR_PMPADDR12 0x3bc
+#define CSR_PMPADDR13 0x3bd
+#define CSR_PMPADDR14 0x3be
+#define CSR_PMPADDR15 0x3bf
+#define CSR_TSELECT 0x7a0
+#define CSR_TDATA1 0x7a1
+#define CSR_TDATA2 0x7a2
+#define CSR_TDATA3 0x7a3
+#define CSR_DCSR 0x7b0
+#define CSR_DPC 0x7b1
+#define CSR_DSCRATCH 0x7b2
+#define CSR_MCYCLE 0xb00
+#define CSR_MINSTRET 0xb02
+#define CSR_MHPMCOUNTER3 0xb03
+#define CSR_MHPMCOUNTER4 0xb04
+#define CSR_MHPMCOUNTER5 0xb05
+#define CSR_MHPMCOUNTER6 0xb06
+#define CSR_MHPMCOUNTER7 0xb07
+#define CSR_MHPMCOUNTER8 0xb08
+#define CSR_MHPMCOUNTER9 0xb09
+#define CSR_MHPMCOUNTER10 0xb0a
+#define CSR_MHPMCOUNTER11 0xb0b
+#define CSR_MHPMCOUNTER12 0xb0c
+#define CSR_MHPMCOUNTER13 0xb0d
+#define CSR_MHPMCOUNTER14 0xb0e
+#define CSR_MHPMCOUNTER15 0xb0f
+#define CSR_MHPMCOUNTER16 0xb10
+#define CSR_MHPMCOUNTER17 0xb11
+#define CSR_MHPMCOUNTER18 0xb12
+#define CSR_MHPMCOUNTER19 0xb13
+#define CSR_MHPMCOUNTER20 0xb14
+#define CSR_MHPMCOUNTER21 0xb15
+#define CSR_MHPMCOUNTER22 0xb16
+#define CSR_MHPMCOUNTER23 0xb17
+#define CSR_MHPMCOUNTER24 0xb18
+#define CSR_MHPMCOUNTER25 0xb19
+#define CSR_MHPMCOUNTER26 0xb1a
+#define CSR_MHPMCOUNTER27 0xb1b
+#define CSR_MHPMCOUNTER28 0xb1c
+#define CSR_MHPMCOUNTER29 0xb1d
+#define CSR_MHPMCOUNTER30 0xb1e
+#define CSR_MHPMCOUNTER31 0xb1f
+#define CSR_MHPMEVENT3 0x323
+#define CSR_MHPMEVENT4 0x324
+#define CSR_MHPMEVENT5 0x325
+#define CSR_MHPMEVENT6 0x326
+#define CSR_MHPMEVENT7 0x327
+#define CSR_MHPMEVENT8 0x328
+#define CSR_MHPMEVENT9 0x329
+#define CSR_MHPMEVENT10 0x32a
+#define CSR_MHPMEVENT11 0x32b
+#define CSR_MHPMEVENT12 0x32c
+#define CSR_MHPMEVENT13 0x32d
+#define CSR_MHPMEVENT14 0x32e
+#define CSR_MHPMEVENT15 0x32f
+#define CSR_MHPMEVENT16 0x330
+#define CSR_MHPMEVENT17 0x331
+#define CSR_MHPMEVENT18 0x332
+#define CSR_MHPMEVENT19 0x333
+#define CSR_MHPMEVENT20 0x334
+#define CSR_MHPMEVENT21 0x335
+#define CSR_MHPMEVENT22 0x336
+#define CSR_MHPMEVENT23 0x337
+#define CSR_MHPMEVENT24 0x338
+#define CSR_MHPMEVENT25 0x339
+#define CSR_MHPMEVENT26 0x33a
+#define CSR_MHPMEVENT27 0x33b
+#define CSR_MHPMEVENT28 0x33c
+#define CSR_MHPMEVENT29 0x33d
+#define CSR_MHPMEVENT30 0x33e
+#define CSR_MHPMEVENT31 0x33f
+#define CSR_MVENDORID 0xf11
+#define CSR_MARCHID 0xf12
+#define CSR_MIMPID 0xf13
+#define CSR_MHARTID 0xf14
+#define CSR_CYCLEH 0xc80
+#define CSR_TIMEH 0xc81
+#define CSR_INSTRETH 0xc82
+#define CSR_HPMCOUNTER3H 0xc83
+#define CSR_HPMCOUNTER4H 0xc84
+#define CSR_HPMCOUNTER5H 0xc85
+#define CSR_HPMCOUNTER6H 0xc86
+#define CSR_HPMCOUNTER7H 0xc87
+#define CSR_HPMCOUNTER8H 0xc88
+#define CSR_HPMCOUNTER9H 0xc89
+#define CSR_HPMCOUNTER10H 0xc8a
+#define CSR_HPMCOUNTER11H 0xc8b
+#define CSR_HPMCOUNTER12H 0xc8c
+#define CSR_HPMCOUNTER13H 0xc8d
+#define CSR_HPMCOUNTER14H 0xc8e
+#define CSR_HPMCOUNTER15H 0xc8f
+#define CSR_HPMCOUNTER16H 0xc90
+#define CSR_HPMCOUNTER17H 0xc91
+#define CSR_HPMCOUNTER18H 0xc92
+#define CSR_HPMCOUNTER19H 0xc93
+#define CSR_HPMCOUNTER20H 0xc94
+#define CSR_HPMCOUNTER21H 0xc95
+#define CSR_HPMCOUNTER22H 0xc96
+#define CSR_HPMCOUNTER23H 0xc97
+#define CSR_HPMCOUNTER24H 0xc98
+#define CSR_HPMCOUNTER25H 0xc99
+#define CSR_HPMCOUNTER26H 0xc9a
+#define CSR_HPMCOUNTER27H 0xc9b
+#define CSR_HPMCOUNTER28H 0xc9c
+#define CSR_HPMCOUNTER29H 0xc9d
+#define CSR_HPMCOUNTER30H 0xc9e
+#define CSR_HPMCOUNTER31H 0xc9f
+#define CSR_MCYCLEH 0xb80
+#define CSR_MINSTRETH 0xb82
+#define CSR_MHPMCOUNTER3H 0xb83
+#define CSR_MHPMCOUNTER4H 0xb84
+#define CSR_MHPMCOUNTER5H 0xb85
+#define CSR_MHPMCOUNTER6H 0xb86
+#define CSR_MHPMCOUNTER7H 0xb87
+#define CSR_MHPMCOUNTER8H 0xb88
+#define CSR_MHPMCOUNTER9H 0xb89
+#define CSR_MHPMCOUNTER10H 0xb8a
+#define CSR_MHPMCOUNTER11H 0xb8b
+#define CSR_MHPMCOUNTER12H 0xb8c
+#define CSR_MHPMCOUNTER13H 0xb8d
+#define CSR_MHPMCOUNTER14H 0xb8e
+#define CSR_MHPMCOUNTER15H 0xb8f
+#define CSR_MHPMCOUNTER16H 0xb90
+#define CSR_MHPMCOUNTER17H 0xb91
+#define CSR_MHPMCOUNTER18H 0xb92
+#define CSR_MHPMCOUNTER19H 0xb93
+#define CSR_MHPMCOUNTER20H 0xb94
+#define CSR_MHPMCOUNTER21H 0xb95
+#define CSR_MHPMCOUNTER22H 0xb96
+#define CSR_MHPMCOUNTER23H 0xb97
+#define CSR_MHPMCOUNTER24H 0xb98
+#define CSR_MHPMCOUNTER25H 0xb99
+#define CSR_MHPMCOUNTER26H 0xb9a
+#define CSR_MHPMCOUNTER27H 0xb9b
+#define CSR_MHPMCOUNTER28H 0xb9c
+#define CSR_MHPMCOUNTER29H 0xb9d
+#define CSR_MHPMCOUNTER30H 0xb9e
+#define CSR_MHPMCOUNTER31H 0xb9f
+#define CAUSE_MISALIGNED_FETCH 0x0
+#define CAUSE_FETCH_ACCESS 0x1
+#define CAUSE_ILLEGAL_INSTRUCTION 0x2
+#define CAUSE_BREAKPOINT 0x3
+#define CAUSE_MISALIGNED_LOAD 0x4
+#define CAUSE_LOAD_ACCESS 0x5
+#define CAUSE_MISALIGNED_STORE 0x6
+#define CAUSE_STORE_ACCESS 0x7
+#define CAUSE_USER_ECALL 0x8
+#define CAUSE_SUPERVISOR_ECALL 0x9
+#define CAUSE_HYPERVISOR_ECALL 0xa
+#define CAUSE_MACHINE_ECALL 0xb
+#define CAUSE_FETCH_PAGE_FAULT 0xc
+#define CAUSE_LOAD_PAGE_FAULT 0xd
+#define CAUSE_STORE_PAGE_FAULT 0xf
+#endif
+#ifdef DECLARE_INSN
+DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
+DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
+DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
+DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
+DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
+DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
+DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
+DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
+DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
+DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
+DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
+DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
+DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
+DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
+DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
+DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
+DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
+DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
+DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
+DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
+DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
+DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
+DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
+DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
+DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
+DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
+DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
+DECLARE_INSN(or, MATCH_OR, MASK_OR)
+DECLARE_INSN(and, MATCH_AND, MASK_AND)
+DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
+DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
+DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
+DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
+DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
+DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
+DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
+DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
+DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
+DECLARE_INSN(lb, MATCH_LB, MASK_LB)
+DECLARE_INSN(lh, MATCH_LH, MASK_LH)
+DECLARE_INSN(lw, MATCH_LW, MASK_LW)
+DECLARE_INSN(ld, MATCH_LD, MASK_LD)
+DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
+DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
+DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
+DECLARE_INSN(sb, MATCH_SB, MASK_SB)
+DECLARE_INSN(sh, MATCH_SH, MASK_SH)
+DECLARE_INSN(sw, MATCH_SW, MASK_SW)
+DECLARE_INSN(sd, MATCH_SD, MASK_SD)
+DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
+DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
+DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
+DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
+DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
+DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
+DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
+DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
+DECLARE_INSN(rem, MATCH_REM, MASK_REM)
+DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
+DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
+DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
+DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
+DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
+DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
+DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
+DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
+DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
+DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
+DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
+DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
+DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
+DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
+DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
+DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
+DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
+DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
+DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
+DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
+DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
+DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
+DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
+DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
+DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
+DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
+DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
+DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
+DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
+DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
+DECLARE_INSN(uret, MATCH_URET, MASK_URET)
+DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
+DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
+DECLARE_INSN(dret, MATCH_DRET, MASK_DRET)
+DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA)
+DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
+DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
+DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
+DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
+DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
+DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
+DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
+DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
+DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
+DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
+DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
+DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
+DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
+DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
+DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
+DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
+DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
+DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
+DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
+DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
+DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
+DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
+DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
+DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
+DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
+DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
+DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
+DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
+DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
+DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q)
+DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q)
+DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q)
+DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q)
+DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q)
+DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q)
+DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q)
+DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q)
+DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q)
+DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q)
+DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S)
+DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q)
+DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D)
+DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q)
+DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
+DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
+DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
+DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
+DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
+DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
+DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q)
+DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q)
+DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q)
+DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
+DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
+DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
+DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
+DECLARE_INSN(fmv_x_w, MATCH_FMV_X_W, MASK_FMV_X_W)
+DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
+DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
+DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
+DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
+DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
+DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
+DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
+DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q)
+DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q)
+DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q)
+DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q)
+DECLARE_INSN(fmv_x_q, MATCH_FMV_X_Q, MASK_FMV_X_Q)
+DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q)
+DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
+DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
+DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
+DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
+DECLARE_INSN(fmv_w_x, MATCH_FMV_W_X, MASK_FMV_W_X)
+DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
+DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
+DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
+DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
+DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
+DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W)
+DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU)
+DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L)
+DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU)
+DECLARE_INSN(fmv_q_x, MATCH_FMV_Q_X, MASK_FMV_Q_X)
+DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
+DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
+DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ)
+DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
+DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
+DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ)
+DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
+DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
+DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
+DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
+DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
+DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
+DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
+DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
+DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q)
+DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q)
+DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q)
+DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q)
+DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP)
+DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
+DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
+DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
+DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
+DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
+DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
+DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
+DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
+DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
+DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
+DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD)
+DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
+DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW)
+DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD)
+DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
+DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW)
+DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
+DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
+DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
+DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
+DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
+DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
+DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
+DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
+DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
+DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR)
+DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND)
+DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW)
+DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
+DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
+DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
+DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
+DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
+DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP)
+DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
+DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP)
+DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
+DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
+DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP)
+DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
+DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP)
+DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
+DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
+DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
+DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
+DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
+DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
+DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
+DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
+DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
+DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
+DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
+DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
+DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
+DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
+DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
+DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
+DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
+DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
+DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
+DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
+DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
+DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
+DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
+DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
+#endif
+#ifdef DECLARE_CSR
+DECLARE_CSR(fflags, CSR_FFLAGS)
+DECLARE_CSR(frm, CSR_FRM)
+DECLARE_CSR(fcsr, CSR_FCSR)
+DECLARE_CSR(cycle, CSR_CYCLE)
+DECLARE_CSR(time, CSR_TIME)
+DECLARE_CSR(instret, CSR_INSTRET)
+DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3)
+DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4)
+DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5)
+DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6)
+DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7)
+DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8)
+DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9)
+DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10)
+DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11)
+DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12)
+DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13)
+DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14)
+DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15)
+DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16)
+DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17)
+DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18)
+DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19)
+DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20)
+DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21)
+DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22)
+DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23)
+DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24)
+DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25)
+DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26)
+DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27)
+DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28)
+DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29)
+DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30)
+DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
+DECLARE_CSR(sstatus, CSR_SSTATUS)
+DECLARE_CSR(sie, CSR_SIE)
+DECLARE_CSR(stvec, CSR_STVEC)
+DECLARE_CSR(scounteren, CSR_SCOUNTEREN)
+DECLARE_CSR(sscratch, CSR_SSCRATCH)
+DECLARE_CSR(sepc, CSR_SEPC)
+DECLARE_CSR(scause, CSR_SCAUSE)
+DECLARE_CSR(stval, CSR_STVAL)
+DECLARE_CSR(sip, CSR_SIP)
+DECLARE_CSR(satp, CSR_SATP)
+DECLARE_CSR(mstatus, CSR_MSTATUS)
+DECLARE_CSR(misa, CSR_MISA)
+DECLARE_CSR(medeleg, CSR_MEDELEG)
+DECLARE_CSR(mideleg, CSR_MIDELEG)
+DECLARE_CSR(mie, CSR_MIE)
+DECLARE_CSR(mtvec, CSR_MTVEC)
+DECLARE_CSR(mcounteren, CSR_MCOUNTEREN)
+DECLARE_CSR(mscratch, CSR_MSCRATCH)
+DECLARE_CSR(mepc, CSR_MEPC)
+DECLARE_CSR(mcause, CSR_MCAUSE)
+DECLARE_CSR(mtval, CSR_MTVAL)
+DECLARE_CSR(mip, CSR_MIP)
+// DECLARE_CSR(pmpcfg0, CSR_PMPCFG0)
+// DECLARE_CSR(pmpcfg1, CSR_PMPCFG1)
+// DECLARE_CSR(pmpcfg2, CSR_PMPCFG2)
+// DECLARE_CSR(pmpcfg3, CSR_PMPCFG3)
+// DECLARE_CSR(pmpaddr0, CSR_PMPADDR0)
+// DECLARE_CSR(pmpaddr1, CSR_PMPADDR1)
+// DECLARE_CSR(pmpaddr2, CSR_PMPADDR2)
+// DECLARE_CSR(pmpaddr3, CSR_PMPADDR3)
+// DECLARE_CSR(pmpaddr4, CSR_PMPADDR4)
+// DECLARE_CSR(pmpaddr5, CSR_PMPADDR5)
+// DECLARE_CSR(pmpaddr6, CSR_PMPADDR6)
+// DECLARE_CSR(pmpaddr7, CSR_PMPADDR7)
+// DECLARE_CSR(pmpaddr8, CSR_PMPADDR8)
+// DECLARE_CSR(pmpaddr9, CSR_PMPADDR9)
+// DECLARE_CSR(pmpaddr10, CSR_PMPADDR10)
+// DECLARE_CSR(pmpaddr11, CSR_PMPADDR11)
+// DECLARE_CSR(pmpaddr12, CSR_PMPADDR12)
+// DECLARE_CSR(pmpaddr13, CSR_PMPADDR13)
+// DECLARE_CSR(pmpaddr14, CSR_PMPADDR14)
+// DECLARE_CSR(pmpaddr15, CSR_PMPADDR15)
+DECLARE_CSR(tselect, CSR_TSELECT)
+DECLARE_CSR(tdata1, CSR_TDATA1)
+DECLARE_CSR(tdata2, CSR_TDATA2)
+DECLARE_CSR(tdata3, CSR_TDATA3)
+DECLARE_CSR(dcsr, CSR_DCSR)
+DECLARE_CSR(dpc, CSR_DPC)
+DECLARE_CSR(dscratch, CSR_DSCRATCH)
+DECLARE_CSR(mcycle, CSR_MCYCLE)
+DECLARE_CSR(minstret, CSR_MINSTRET)
+DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3)
+DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4)
+DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5)
+DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6)
+DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7)
+DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8)
+DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9)
+DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10)
+DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11)
+DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12)
+DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13)
+DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14)
+DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15)
+DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16)
+DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17)
+DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18)
+DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19)
+DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20)
+DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21)
+DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22)
+DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23)
+DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24)
+DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25)
+DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26)
+DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27)
+DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
+DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
+DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
+DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
+DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
+DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
+DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
+DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6)
+DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7)
+DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8)
+DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9)
+DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10)
+DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11)
+DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12)
+DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13)
+DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14)
+DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15)
+DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16)
+DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17)
+DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18)
+DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19)
+DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20)
+DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21)
+DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22)
+DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23)
+DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24)
+DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25)
+DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26)
+DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27)
+DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28)
+DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29)
+DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30)
+DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31)
+DECLARE_CSR(mvendorid, CSR_MVENDORID)
+DECLARE_CSR(marchid, CSR_MARCHID)
+DECLARE_CSR(mimpid, CSR_MIMPID)
+DECLARE_CSR(mhartid, CSR_MHARTID)
+DECLARE_CSR(cycleh, CSR_CYCLEH)
+DECLARE_CSR(timeh, CSR_TIMEH)
+DECLARE_CSR(instreth, CSR_INSTRETH)
+DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H)
+DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H)
+DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H)
+DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H)
+DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H)
+DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H)
+DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H)
+DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H)
+DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H)
+DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H)
+DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H)
+DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H)
+DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H)
+DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H)
+DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H)
+DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H)
+DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H)
+DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H)
+DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H)
+DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H)
+DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H)
+DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H)
+DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H)
+DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H)
+DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H)
+DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H)
+DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H)
+DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H)
+DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H)
+DECLARE_CSR(mcycleh, CSR_MCYCLEH)
+DECLARE_CSR(minstreth, CSR_MINSTRETH)
+DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H)
+DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H)
+DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H)
+DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H)
+DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H)
+DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H)
+DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H)
+DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H)
+DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H)
+DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H)
+DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H)
+DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H)
+DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H)
+DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H)
+DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H)
+DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H)
+DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H)
+DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H)
+DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H)
+DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H)
+DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H)
+DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H)
+DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H)
+DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H)
+DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H)
+DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H)
+DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H)
+DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H)
+DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
+#endif
+#ifdef DECLARE_CAUSE
+DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
+DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS)
+DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION)
+DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT)
+DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
+DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS)
+DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
+DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS)
+DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
+DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
+DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
+DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
+DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT)
+DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT)
+DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT)
+#endif
diff --git a/tb/riscv-isa-sim/riscv/execute.cc b/tb/riscv-isa-sim/riscv/execute.cc
new file mode 100644
index 0000000000000000000000000000000000000000..535f51c1fe369bc4a898cfc56beda0e427612a78
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/execute.cc
@@ -0,0 +1,252 @@
+// See LICENSE for license details.
+
+#include "processor.h"
+#include "mmu.h"
+#include <cassert>
+
+
+static void commit_log_stash_privilege(processor_t* p)
+{
+#ifdef RISCV_ENABLE_COMMITLOG
+  state_t* state = p->get_state();
+  state->last_inst_priv = state->prv;
+  state->last_inst_xlen = p->get_xlen();
+  state->last_inst_flen = p->get_flen();
+#endif
+}
+
+static void commit_log_print_value(int width, uint64_t hi, uint64_t lo)
+{
+  switch (width) {
+    case 16:
+      fprintf(stderr, "0x%04" PRIx16, (uint16_t)lo);
+      break;
+    case 32:
+      fprintf(stderr, "0x%08" PRIx32, (uint32_t)lo);
+      break;
+    case 64:
+      fprintf(stderr, "0x%016" PRIx64, lo);
+      break;
+    case 128:
+      fprintf(stderr, "0x%016" PRIx64 "%016" PRIx64, hi, lo);
+      break;
+    default:
+      abort();
+  }
+}
+
+static void commit_log_print_insn(state_t* state, reg_t pc, insn_t insn)
+{
+#ifdef RISCV_ENABLE_COMMITLOG
+  auto& reg = state->log_reg_write;
+  int priv = state->last_inst_priv;
+  int xlen = state->last_inst_xlen;
+  int flen = state->last_inst_flen;
+
+  state->last_insn = insn.bits();
+
+  if (reg.addr) {
+    bool fp = reg.addr & 1;
+    int rd = reg.addr >> 1;
+    int size = fp ? flen : xlen;
+  }
+#endif
+}
+
+inline void processor_t::update_histogram(reg_t pc)
+{
+#ifdef RISCV_ENABLE_HISTOGRAM
+  pc_histogram[pc]++;
+#endif
+}
+
+// This is expected to be inlined by the compiler so each use of execute_insn
+// includes a duplicated body of the function to get separate fetch.func
+// function calls.
+static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
+{
+  commit_log_stash_privilege(p);
+  reg_t npc = fetch.func(p, fetch.insn, pc);
+  if (npc != PC_SERIALIZE_BEFORE) {
+    commit_log_print_insn(p->get_state(), pc, fetch.insn);
+    p->update_histogram(pc);
+  }
+  return npc;
+}
+
+bool processor_t::slow_path()
+{
+  return debug || state.single_step != state.STEP_NONE || state.dcsr.cause;
+}
+
+// fetch/decode/execute loop
+void processor_t::step(size_t n)
+{
+  #ifdef RISCV_ENABLE_COMMITLOG
+  state.was_exception = false;
+  #endif
+  if (state.dcsr.cause == DCSR_CAUSE_NONE) {
+    if (halt_request) {
+      enter_debug_mode(DCSR_CAUSE_DEBUGINT);
+    } // !!!The halt bit in DCSR is deprecated.
+    else if (state.dcsr.halt) {
+      enter_debug_mode(DCSR_CAUSE_HALT);
+    }
+  }
+
+  while (n > 0) {
+    size_t instret = 0;
+    reg_t pc = state.pc;
+    mmu_t* _mmu = mmu;
+
+    #define advance_pc() \
+     if (unlikely(invalid_pc(pc))) { \
+       switch (pc) { \
+         case PC_SERIALIZE_BEFORE: state.serialized = true; break; \
+         case PC_SERIALIZE_AFTER: ++instret; break; \
+         case PC_SERIALIZE_WFI: n = ++instret; break; \
+         default: abort(); \
+       } \
+       pc = state.pc; \
+       break; \
+     } else { \
+       state.pc = pc; \
+       instret++; \
+     }
+
+    try
+    {
+      insn_fetch_t fetch = mmu->load_insn(pc);
+
+      // check whether the instruction is an AMO, we dpn't take interrupts on AMOs
+      if (likely((fetch.insn.bits() & 0x2f) != 0x2f)) {
+        take_pending_interrupt();
+      }
+
+      if (unlikely(slow_path()))
+      {
+        while (instret < n)
+        {
+          if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
+            state.single_step = state.STEP_NONE;
+            if (state.dcsr.cause == DCSR_CAUSE_NONE) {
+              enter_debug_mode(DCSR_CAUSE_STEP);
+              // enter_debug_mode changed state.pc, so we can't just continue.
+              break;
+            }
+          }
+
+          if (unlikely(state.single_step == state.STEP_STEPPING)) {
+            state.single_step = state.STEP_STEPPED;
+          }
+
+          if (debug && !state.serialized)
+            disasm(fetch.insn);
+          pc = execute_insn(this, pc, fetch);
+
+          advance_pc();
+
+          if (unlikely(state.pc >= DEBUG_ROM_ENTRY &&
+                       state.pc < DEBUG_END)) {
+            // We're waiting for the debugger to tell us something.
+            return;
+          }
+
+        }
+      }
+      else while (instret < n)
+      {
+        // This code uses a modified Duff's Device to improve the performance
+        // of executing instructions. While typical Duff's Devices are used
+        // for software pipelining, the switch statement below primarily
+        // benefits from separate call points for the fetch.func function call
+        // found in each execute_insn. This function call is an indirect jump
+        // that depends on the current instruction. By having an indirect jump
+        // dedicated for each icache entry, you improve the performance of the
+        // host's next address predictor. Each case in the switch statement
+        // allows for the program flow to contine to the next case if it
+        // corresponds to the next instruction in the program and instret is
+        // still less than n.
+        //
+        // According to Andrew Waterman's recollection, this optimization
+        // resulted in approximately a 2x performance increase.
+
+        // This figures out where to jump to in the switch statement
+        size_t idx = _mmu->icache_index(pc);
+
+        // This gets the cached decoded instruction from the MMU. If the MMU
+        // does not have the current pc cached, it will refill the MMU and
+        // return the correct entry. ic_entry->data.func is the C++ function
+        // corresponding to the instruction.
+        auto ic_entry = _mmu->access_icache(pc);
+
+        // This macro is included in "icache.h" included within the switch
+        // statement below. The indirect jump corresponding to the instruction
+        // is located within the execute_insn() function call.
+        #define ICACHE_ACCESS(i) { \
+          insn_fetch_t fetch = ic_entry->data; \
+          pc = execute_insn(this, pc, fetch); \
+          ic_entry = ic_entry->next; \
+          if (i == mmu_t::ICACHE_ENTRIES-1) break; \
+          if (unlikely(ic_entry->tag != pc)) break; \
+          if (unlikely(instret+1 == n)) break; \
+          instret++; \
+          state.pc = pc; \
+        }
+
+        // This switch statement implements the modified Duff's device as
+        // explained above.
+        switch (idx) {
+          // "icache.h" is generated by the gen_icache script
+          #include "icache.h"
+        }
+
+        advance_pc();
+      }
+    }
+    catch(trap_t& t)
+    {
+      #ifdef RISCV_ENABLE_COMMITLOG
+      state.was_exception = true;
+      #endif
+      take_trap(t, pc);
+      n = instret;
+
+      if (unlikely(state.single_step == state.STEP_STEPPED)) {
+        state.single_step = state.STEP_NONE;
+        enter_debug_mode(DCSR_CAUSE_STEP);
+      }
+    }
+    catch (trigger_matched_t& t)
+    {
+      if (mmu->matched_trigger) {
+        // This exception came from the MMU. That means the instruction hasn't
+        // fully executed yet. We start it again, but this time it won't throw
+        // an exception because matched_trigger is already set. (All memory
+        // instructions are idempotent so restarting is safe.)
+
+        insn_fetch_t fetch = mmu->load_insn(pc);
+        pc = execute_insn(this, pc, fetch);
+        advance_pc();
+
+        delete mmu->matched_trigger;
+        mmu->matched_trigger = NULL;
+      }
+      switch (state.mcontrol[t.index].action) {
+        case ACTION_DEBUG_MODE:
+          enter_debug_mode(DCSR_CAUSE_HWBP);
+          break;
+        case ACTION_DEBUG_EXCEPTION: {
+          mem_trap_t trap(CAUSE_BREAKPOINT, t.address);
+          take_trap(trap, pc);
+          break;
+        }
+        default:
+          abort();
+      }
+    }
+
+    state.minstret += instret;
+    n -= instret;
+  }
+}
diff --git a/tb/riscv-isa-sim/riscv/extension.cc b/tb/riscv-isa-sim/riscv/extension.cc
new file mode 100644
index 0000000000000000000000000000000000000000..520c2ed578c3964c4cfba8c9f7da394a48c1bc5d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/extension.cc
@@ -0,0 +1,23 @@
+// See LICENSE for license details.
+
+#include "extension.h"
+#include "trap.h"
+
+extension_t::~extension_t()
+{
+}
+
+void extension_t::illegal_instruction()
+{
+  throw trap_illegal_instruction(0);
+}
+
+void extension_t::raise_interrupt()
+{
+  p->take_interrupt((reg_t)1 << IRQ_COP); // must not return
+  throw std::logic_error("a COP exception was posted, but interrupts are disabled!");
+}
+
+void extension_t::clear_interrupt()
+{
+}
diff --git a/tb/riscv-isa-sim/riscv/extension.h b/tb/riscv-isa-sim/riscv/extension.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1e847d9b8ebff01511fbed25aef21f910313ac2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/extension.h
@@ -0,0 +1,38 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_COPROCESSOR_H
+#define _RISCV_COPROCESSOR_H
+
+#include "processor.h"
+#include "disasm.h"
+#include <vector>
+#include <functional>
+
+class extension_t
+{
+ public:
+  virtual std::vector<insn_desc_t> get_instructions() = 0;
+  virtual std::vector<disasm_insn_t*> get_disasms() = 0;
+  virtual const char* name() = 0;
+  virtual void reset() {};
+  virtual void set_debug(bool value) {};
+  virtual ~extension_t();
+
+  void set_processor(processor_t* _p) { p = _p; }
+ protected:
+  processor_t* p;
+
+  void illegal_instruction();
+  void raise_interrupt();
+  void clear_interrupt();
+};
+
+std::function<extension_t*()> find_extension(const char* name);
+void register_extension(const char* name, std::function<extension_t*()> f);
+
+#define REGISTER_EXTENSION(name, constructor) \
+  class register_##name { \
+    public: register_##name() { register_extension(#name, constructor); } \
+  }; static register_##name dummy_##name;
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/extensions.cc b/tb/riscv-isa-sim/riscv/extensions.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d1690c4b8f65dd25159f84866b14fa132aac58c6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/extensions.cc
@@ -0,0 +1,37 @@
+// See LICENSE for license details.
+
+#include "extension.h"
+#include <string>
+#include <map>
+#include <dlfcn.h>
+
+static std::map<std::string, std::function<extension_t*()>>& extensions()
+{
+  static std::map<std::string, std::function<extension_t*()>> v;
+  return v;
+}
+
+void register_extension(const char* name, std::function<extension_t*()> f)
+{
+  extensions()[name] = f;
+}
+
+std::function<extension_t*()> find_extension(const char* name)
+{
+  if (!extensions().count(name)) {
+    // try to find extension xyz by loading libxyz.so
+    std::string libname = std::string("lib") + name + ".so";
+    if (!dlopen(libname.c_str(), RTLD_LAZY)) {
+      fprintf(stderr, "couldn't find extension '%s' (or library '%s')\n",
+              name, libname.c_str());
+      exit(-1);
+    }
+    if (!extensions().count(name)) {
+      fprintf(stderr, "couldn't find extension '%s' in shared library '%s'\n",
+              name, libname.c_str());
+      exit(-1);
+    }
+  }
+
+  return extensions()[name];
+}
diff --git a/tb/riscv-isa-sim/riscv/gen_icache b/tb/riscv-isa-sim/riscv/gen_icache
new file mode 100755
index 0000000000000000000000000000000000000000..7ec3c694344b3ff6d19fff5eadeb843ed4afda46
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/gen_icache
@@ -0,0 +1,7 @@
+#!/bin/sh
+n=$(($1-1))
+for i in `seq 0 $n`
+do
+  echo case $i: ICACHE_ACCESS\($i\)\;
+done
+echo
diff --git a/tb/riscv-isa-sim/riscv/insn_template.cc b/tb/riscv-isa-sim/riscv/insn_template.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1e79326c462446a94f6a16aa2b0cf7384ef45d16
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insn_template.cc
@@ -0,0 +1,21 @@
+// See LICENSE for license details.
+
+#include "insn_template.h"
+
+reg_t rv32_NAME(processor_t* p, insn_t insn, reg_t pc)
+{
+  int xlen = 32;
+  reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+  #include "insns/NAME.h"
+  trace_opcode(p, OPCODE, insn);
+  return npc;
+}
+
+reg_t rv64_NAME(processor_t* p, insn_t insn, reg_t pc)
+{
+  int xlen = 64;
+  reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+  #include "insns/NAME.h"
+  trace_opcode(p, OPCODE, insn);
+  return npc;
+}
diff --git a/tb/riscv-isa-sim/riscv/insn_template.h b/tb/riscv-isa-sim/riscv/insn_template.h
new file mode 100644
index 0000000000000000000000000000000000000000..07aa16ba05ab7dc24be90239ce720ccc1dc55fc4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insn_template.h
@@ -0,0 +1,9 @@
+// See LICENSE for license details.
+
+#include "mmu.h"
+#include "mulhi.h"
+#include "softfloat.h"
+#include "internals.h"
+#include "specialize.h"
+#include "tracer.h"
+#include <assert.h>
diff --git a/tb/riscv-isa-sim/riscv/insns/add.h b/tb/riscv-isa-sim/riscv/insns/add.h
new file mode 100644
index 0000000000000000000000000000000000000000..895e2b1867dbf29aee59a86fc68fcbad5e2535f1
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/add.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(RS1 + RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/addi.h b/tb/riscv-isa-sim/riscv/insns/addi.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bb5dcedfa8e3c1269cd2f37697c090535e70d04
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/addi.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/addiw.h b/tb/riscv-isa-sim/riscv/insns/addiw.h
new file mode 100644
index 0000000000000000000000000000000000000000..4263eada244bb6f2f43f88df926600ece25a3dca
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/addiw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32(insn.i_imm() + RS1));
diff --git a/tb/riscv-isa-sim/riscv/insns/addw.h b/tb/riscv-isa-sim/riscv/insns/addw.h
new file mode 100644
index 0000000000000000000000000000000000000000..706dc9c8f98b55be4bcc43d4bb7693d13bf738f5
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/addw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32(RS1 + RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoadd_d.h b/tb/riscv-isa-sim/riscv/insns/amoadd_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..6090fbc530d078cee63ea31bb78ecf70a1c6a534
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoadd_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs + RS2; }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoadd_w.h b/tb/riscv-isa-sim/riscv/insns/amoadd_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c6471afbe6e2dcb40fa504c7b4fc77739e72d9f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoadd_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs + RS2; })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoand_d.h b/tb/riscv-isa-sim/riscv/insns/amoand_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..80aea184de5521c64248ded6ff0c2ea79078c6a0
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoand_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs & RS2; }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoand_w.h b/tb/riscv-isa-sim/riscv/insns/amoand_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7e1ba7c06262b785db4d20ae7a32ab2220f3bb6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoand_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs & RS2; })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amomax_d.h b/tb/riscv-isa-sim/riscv/insns/amomax_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..496d8ada9be068e850fc9b0944cbc6e338e8c893
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amomax_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](int64_t lhs) { return std::max(lhs, int64_t(RS2)); }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amomax_w.h b/tb/riscv-isa-sim/riscv/insns/amomax_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..757bdd2ccb7bdab94d6a3fade459acf17f66bd2d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amomax_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](int32_t lhs) { return std::max(lhs, int32_t(RS2)); })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amomaxu_d.h b/tb/riscv-isa-sim/riscv/insns/amomaxu_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..12b173313d9e4f1636e13a67fea6785fbae8f8ae
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amomaxu_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return std::max(lhs, RS2); }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amomaxu_w.h b/tb/riscv-isa-sim/riscv/insns/amomaxu_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..538df1c40077dda756ae3b66813f92e5fde0a6d2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amomaxu_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return std::max(lhs, uint32_t(RS2)); })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amomin_d.h b/tb/riscv-isa-sim/riscv/insns/amomin_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..725d9839f8f186aeaec31481cb15fa71fbe72f47
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amomin_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](int64_t lhs) { return std::min(lhs, int64_t(RS2)); }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amomin_w.h b/tb/riscv-isa-sim/riscv/insns/amomin_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..ee53faa0cd61cad91f5dfaa5d59faaf1cc368ea3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amomin_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](int32_t lhs) { return std::min(lhs, int32_t(RS2)); })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amominu_d.h b/tb/riscv-isa-sim/riscv/insns/amominu_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..15b6c0a48bad12e9cafd9738fe7481bc933eb974
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amominu_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return std::min(lhs, RS2); }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amominu_w.h b/tb/riscv-isa-sim/riscv/insns/amominu_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..52e1141b87cd9cce8945e9394bc3bbce7b543d06
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amominu_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return std::min(lhs, uint32_t(RS2)); })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoor_d.h b/tb/riscv-isa-sim/riscv/insns/amoor_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..de8762745b3768a66be72da7c2bbcfc9d6d32b3f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoor_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs | RS2; }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoor_w.h b/tb/riscv-isa-sim/riscv/insns/amoor_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..3455981d86944802bdea0afae5689e05b7c28de2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoor_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs | RS2; })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoswap_d.h b/tb/riscv-isa-sim/riscv/insns/amoswap_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1bffdeb5cdda44cbc0e9b64f4602bec5eaf1632
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoswap_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return RS2; }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoswap_w.h b/tb/riscv-isa-sim/riscv/insns/amoswap_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f78369c76eeccec56f4c7e3d48d3687245b2839
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoswap_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return RS2; })));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoxor_d.h b/tb/riscv-isa-sim/riscv/insns/amoxor_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b3c0bf41fb9262a6fd2330772e54029770e3e04
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoxor_d.h
@@ -0,0 +1,3 @@
+require_extension('A');
+require_rv64;
+WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs ^ RS2; }));
diff --git a/tb/riscv-isa-sim/riscv/insns/amoxor_w.h b/tb/riscv-isa-sim/riscv/insns/amoxor_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1ea82f1d83b9f71e882770915d8c253dbf16e33
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/amoxor_w.h
@@ -0,0 +1,2 @@
+require_extension('A');
+WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs ^ RS2; })));
diff --git a/tb/riscv-isa-sim/riscv/insns/and.h b/tb/riscv-isa-sim/riscv/insns/and.h
new file mode 100644
index 0000000000000000000000000000000000000000..86b488314ff8ad737a232cd319dcd511e10935f9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/and.h
@@ -0,0 +1 @@
+WRITE_RD(RS1 & RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/andi.h b/tb/riscv-isa-sim/riscv/insns/andi.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcc51e44071ab6bdff0ac53fd81bf3d1acf0764d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/andi.h
@@ -0,0 +1 @@
+WRITE_RD(insn.i_imm() & RS1);
diff --git a/tb/riscv-isa-sim/riscv/insns/auipc.h b/tb/riscv-isa-sim/riscv/insns/auipc.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a2b169b59a4b46ecb2976bb7ae427ae0fe49c48
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/auipc.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(insn.u_imm() + pc));
diff --git a/tb/riscv-isa-sim/riscv/insns/beq.h b/tb/riscv-isa-sim/riscv/insns/beq.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd7e0614955879ef8a31ed978b9081e20a9da593
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/beq.h
@@ -0,0 +1,2 @@
+if(RS1 == RS2)
+  set_pc(BRANCH_TARGET);
diff --git a/tb/riscv-isa-sim/riscv/insns/bge.h b/tb/riscv-isa-sim/riscv/insns/bge.h
new file mode 100644
index 0000000000000000000000000000000000000000..da0c68e6a41fc8c048330b5473ffcf06343cde4f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/bge.h
@@ -0,0 +1,2 @@
+if(sreg_t(RS1) >= sreg_t(RS2))
+  set_pc(BRANCH_TARGET);
diff --git a/tb/riscv-isa-sim/riscv/insns/bgeu.h b/tb/riscv-isa-sim/riscv/insns/bgeu.h
new file mode 100644
index 0000000000000000000000000000000000000000..d764a347ef9223f0c9c2e87c14ac974e1f837b35
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/bgeu.h
@@ -0,0 +1,2 @@
+if(RS1 >= RS2)
+  set_pc(BRANCH_TARGET);
diff --git a/tb/riscv-isa-sim/riscv/insns/blt.h b/tb/riscv-isa-sim/riscv/insns/blt.h
new file mode 100644
index 0000000000000000000000000000000000000000..c54fb7693a01e5c8e57c47f2e41faa77fb35fe87
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/blt.h
@@ -0,0 +1,2 @@
+if(sreg_t(RS1) < sreg_t(RS2))
+  set_pc(BRANCH_TARGET);
diff --git a/tb/riscv-isa-sim/riscv/insns/bltu.h b/tb/riscv-isa-sim/riscv/insns/bltu.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff75e8a6da36a1e7b6f662685499b53aaf7b997f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/bltu.h
@@ -0,0 +1,2 @@
+if(RS1 < RS2)
+  set_pc(BRANCH_TARGET);
diff --git a/tb/riscv-isa-sim/riscv/insns/bne.h b/tb/riscv-isa-sim/riscv/insns/bne.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e6cb7c7ac2ffd3dfbdf34c6ab58cf27c69a2139
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/bne.h
@@ -0,0 +1,2 @@
+if(RS1 != RS2)
+  set_pc(BRANCH_TARGET);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_add.h b/tb/riscv-isa-sim/riscv/insns/c_add.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab7d4d4c8e643f252c80f6df73077d34a46f0d66
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_add.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_rs2() != 0);
+WRITE_RD(sext_xlen(RVC_RS1 + RVC_RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_addi.h b/tb/riscv-isa-sim/riscv/insns/c_addi.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb983442a37e1407e1eb2240737a5ab76f7820ae
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_addi.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RD(sext_xlen(RVC_RS1 + insn.rvc_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_addi4spn.h b/tb/riscv-isa-sim/riscv/insns/c_addi4spn.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5f3832f605b43ccc35106fe5b61570eca4ce6d6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_addi4spn.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_addi4spn_imm() != 0);
+WRITE_RVC_RS2S(sext_xlen(RVC_SP + insn.rvc_addi4spn_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_addw.h b/tb/riscv-isa-sim/riscv/insns/c_addw.h
new file mode 100644
index 0000000000000000000000000000000000000000..6e0ae3a52c2dab09dbe545d357b50fae493457f8
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_addw.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require_rv64;
+WRITE_RVC_RS1S(sext32(RVC_RS1S + RVC_RS2S));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_and.h b/tb/riscv-isa-sim/riscv/insns/c_and.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d7bab6c58997478d6542312f78282820df1bdd6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_and.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RVC_RS1S(RVC_RS1S & RVC_RS2S);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_andi.h b/tb/riscv-isa-sim/riscv/insns/c_andi.h
new file mode 100644
index 0000000000000000000000000000000000000000..9de5a1acb08b0190797bd94d5be3b0ff4bb4c9fc
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_andi.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RVC_RS1S(RVC_RS1S & insn.rvc_imm());
diff --git a/tb/riscv-isa-sim/riscv/insns/c_beqz.h b/tb/riscv-isa-sim/riscv/insns/c_beqz.h
new file mode 100644
index 0000000000000000000000000000000000000000..35c119603d08ab51bc87d391a324e24a7d0cf972
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_beqz.h
@@ -0,0 +1,3 @@
+require_extension('C');
+if (RVC_RS1S == 0)
+  set_pc(pc + insn.rvc_b_imm());
diff --git a/tb/riscv-isa-sim/riscv/insns/c_bnez.h b/tb/riscv-isa-sim/riscv/insns/c_bnez.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e40ea78e19fc05b6edc74baf09ed2e8f525c321
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_bnez.h
@@ -0,0 +1,3 @@
+require_extension('C');
+if (RVC_RS1S != 0)
+  set_pc(pc + insn.rvc_b_imm());
diff --git a/tb/riscv-isa-sim/riscv/insns/c_ebreak.h b/tb/riscv-isa-sim/riscv/insns/c_ebreak.h
new file mode 100644
index 0000000000000000000000000000000000000000..128b86b22c55beefbd0eb8ca43f3c3a3708676b7
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_ebreak.h
@@ -0,0 +1,2 @@
+require_extension('C');
+throw trap_breakpoint(pc);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_fld.h b/tb/riscv-isa-sim/riscv/insns/c_fld.h
new file mode 100644
index 0000000000000000000000000000000000000000..319615b8e4303bf952cd0306a526f8d7fa68f5cd
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_fld.h
@@ -0,0 +1,4 @@
+require_extension('C');
+require_extension('D');
+require_fp;
+WRITE_RVC_FRS2S(f64(MMU.load_uint64(RVC_RS1S + insn.rvc_ld_imm())));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_fldsp.h b/tb/riscv-isa-sim/riscv/insns/c_fldsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..534eef7d2877967ca9963a5eb67dace673073435
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_fldsp.h
@@ -0,0 +1,4 @@
+require_extension('C');
+require_extension('D');
+require_fp;
+WRITE_FRD(f64(MMU.load_uint64(RVC_SP + insn.rvc_ldsp_imm())));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_flw.h b/tb/riscv-isa-sim/riscv/insns/c_flw.h
new file mode 100644
index 0000000000000000000000000000000000000000..682566c705b764366f4681b6eff3dd85a2c27efa
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_flw.h
@@ -0,0 +1,8 @@
+require_extension('C');
+if (xlen == 32) {
+  require_extension('F');
+  require_fp;
+  WRITE_RVC_FRS2S(f32(MMU.load_uint32(RVC_RS1S + insn.rvc_lw_imm())));
+} else { // c.ld
+  WRITE_RVC_RS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/c_flwsp.h b/tb/riscv-isa-sim/riscv/insns/c_flwsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..79058c40a37d7b971640fc9877dc4be9ee91303b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_flwsp.h
@@ -0,0 +1,9 @@
+require_extension('C');
+if (xlen == 32) {
+  require_extension('F');
+  require_fp;
+  WRITE_FRD(f32(MMU.load_uint32(RVC_SP + insn.rvc_lwsp_imm())));
+} else { // c.ldsp
+  require(insn.rvc_rd() != 0);
+  WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/c_fsd.h b/tb/riscv-isa-sim/riscv/insns/c_fsd.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f2c8f4c3ac1743a40d94598eb1a8b49f969893e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_fsd.h
@@ -0,0 +1,4 @@
+require_extension('C');
+require_extension('D');
+require_fp;
+MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S.v[0]);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_fsdsp.h b/tb/riscv-isa-sim/riscv/insns/c_fsdsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..27b933191930f3fc8413cfb0668139de7e946b7b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_fsdsp.h
@@ -0,0 +1,4 @@
+require_extension('C');
+require_extension('D');
+require_fp;
+MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2.v[0]);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_fsw.h b/tb/riscv-isa-sim/riscv/insns/c_fsw.h
new file mode 100644
index 0000000000000000000000000000000000000000..70858229652189553e792b82a5a2178570107145
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_fsw.h
@@ -0,0 +1,8 @@
+require_extension('C');
+if (xlen == 32) {
+  require_extension('F');
+  require_fp;
+  MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v[0]);
+} else { // c.sd
+  MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/c_fswsp.h b/tb/riscv-isa-sim/riscv/insns/c_fswsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5a003fcd1f057df93f407747173772f3ab7a4df
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_fswsp.h
@@ -0,0 +1,8 @@
+require_extension('C');
+if (xlen == 32) {
+  require_extension('F');
+  require_fp;
+  MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v[0]);
+} else { // c.sdsp
+  MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2);
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/c_j.h b/tb/riscv-isa-sim/riscv/insns/c_j.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d8939c47fc40b4e06f7126c22f48e5137ad4175
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_j.h
@@ -0,0 +1,2 @@
+require_extension('C');
+set_pc(pc + insn.rvc_j_imm());
diff --git a/tb/riscv-isa-sim/riscv/insns/c_jal.h b/tb/riscv-isa-sim/riscv/insns/c_jal.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f156f61fbe3dc22b9565225ee7dcf5bfc57fdea
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_jal.h
@@ -0,0 +1,9 @@
+require_extension('C');
+if (xlen == 32) {
+  reg_t tmp = npc;
+  set_pc(pc + insn.rvc_j_imm());
+  WRITE_REG(X_RA, tmp);
+} else { // c.addiw
+  require(insn.rvc_rd() != 0);
+  WRITE_RD(sext32(RVC_RS1 + insn.rvc_imm()));
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/c_jalr.h b/tb/riscv-isa-sim/riscv/insns/c_jalr.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb1e4222dcd38829bb65f1c0e8e2073ecdb3c47c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_jalr.h
@@ -0,0 +1,5 @@
+require_extension('C');
+require(insn.rvc_rs1() != 0);
+reg_t tmp = npc;
+set_pc(RVC_RS1 & ~reg_t(1));
+WRITE_REG(X_RA, tmp);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_jr.h b/tb/riscv-isa-sim/riscv/insns/c_jr.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c4a8ea9a79d00feeb641230b4c679301ba83022
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_jr.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_rs1() != 0);
+set_pc(RVC_RS1 & ~reg_t(1));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_li.h b/tb/riscv-isa-sim/riscv/insns/c_li.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9fd66b2f32ee651f97a76c89ba68da0bce1cc56
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_li.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RD(insn.rvc_imm());
diff --git a/tb/riscv-isa-sim/riscv/insns/c_lui.h b/tb/riscv-isa-sim/riscv/insns/c_lui.h
new file mode 100644
index 0000000000000000000000000000000000000000..75d8eb892fa966dccc966690f3640e124d68ceda
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_lui.h
@@ -0,0 +1,8 @@
+require_extension('C');
+if (insn.rvc_rd() == 2) { // c.addi16sp
+  require(insn.rvc_addi16sp_imm() != 0);
+  WRITE_REG(X_SP, sext_xlen(RVC_SP + insn.rvc_addi16sp_imm()));
+} else {
+  require(insn.rvc_imm() != 0);
+  WRITE_RD(insn.rvc_imm() << 12);
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/c_lw.h b/tb/riscv-isa-sim/riscv/insns/c_lw.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef49dd90904f1608b9a5320cb8ccd17228020ee1
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_lw.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RVC_RS2S(MMU.load_int32(RVC_RS1S + insn.rvc_lw_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_lwsp.h b/tb/riscv-isa-sim/riscv/insns/c_lwsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..b3d74dbf087fb09553ca438bf4c44629ecfdc032
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_lwsp.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_rd() != 0);
+WRITE_RD(MMU.load_int32(RVC_SP + insn.rvc_lwsp_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_mv.h b/tb/riscv-isa-sim/riscv/insns/c_mv.h
new file mode 100644
index 0000000000000000000000000000000000000000..a03d0d0763f26a62f3503c4552af308d1671598b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_mv.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_rs2() != 0);
+WRITE_RD(RVC_RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_or.h b/tb/riscv-isa-sim/riscv/insns/c_or.h
new file mode 100644
index 0000000000000000000000000000000000000000..56436d1a18739fc418d373d771b2542e28b03d4f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_or.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RVC_RS1S(RVC_RS1S | RVC_RS2S);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_slli.h b/tb/riscv-isa-sim/riscv/insns/c_slli.h
new file mode 100644
index 0000000000000000000000000000000000000000..24fbb1335be3060dd7b9b1d2c2dd96a1585608ba
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_slli.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_zimm() < xlen);
+WRITE_RD(sext_xlen(RVC_RS1 << insn.rvc_zimm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_srai.h b/tb/riscv-isa-sim/riscv/insns/c_srai.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6638b1e2747c7bc2ec8bb268230658ff4f77052
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_srai.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_zimm() < xlen);
+WRITE_RVC_RS1S(sext_xlen(sext_xlen(RVC_RS1S) >> insn.rvc_zimm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_srli.h b/tb/riscv-isa-sim/riscv/insns/c_srli.h
new file mode 100644
index 0000000000000000000000000000000000000000..f410fefda56322c0aa7d4d39caa2d5af3c75fbee
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_srli.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require(insn.rvc_zimm() < xlen);
+WRITE_RVC_RS1S(sext_xlen(zext_xlen(RVC_RS1S) >> insn.rvc_zimm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_sub.h b/tb/riscv-isa-sim/riscv/insns/c_sub.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b8e3735c60ad1174f88adb091a47fd285b90e74
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_sub.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RVC_RS1S(sext_xlen(RVC_RS1S - RVC_RS2S));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_subw.h b/tb/riscv-isa-sim/riscv/insns/c_subw.h
new file mode 100644
index 0000000000000000000000000000000000000000..580f5b54e402e8a4b782b262e3b268e88fe95fda
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_subw.h
@@ -0,0 +1,3 @@
+require_extension('C');
+require_rv64;
+WRITE_RVC_RS1S(sext32(RVC_RS1S - RVC_RS2S));
diff --git a/tb/riscv-isa-sim/riscv/insns/c_sw.h b/tb/riscv-isa-sim/riscv/insns/c_sw.h
new file mode 100644
index 0000000000000000000000000000000000000000..3073e9d623dcb98265b2c1d1d3c59f51530ab386
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_sw.h
@@ -0,0 +1,2 @@
+require_extension('C');
+MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_RS2S);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_swsp.h b/tb/riscv-isa-sim/riscv/insns/c_swsp.h
new file mode 100644
index 0000000000000000000000000000000000000000..b8995ab05fd0596626e8c6a5d1770fc45cbd67d9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_swsp.h
@@ -0,0 +1,2 @@
+require_extension('C');
+MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/c_xor.h b/tb/riscv-isa-sim/riscv/insns/c_xor.h
new file mode 100644
index 0000000000000000000000000000000000000000..9981c1af90ee35fc603e9f4ce363bf0ec3744162
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/c_xor.h
@@ -0,0 +1,2 @@
+require_extension('C');
+WRITE_RVC_RS1S(RVC_RS1S ^ RVC_RS2S);
diff --git a/tb/riscv-isa-sim/riscv/insns/csrrc.h b/tb/riscv-isa-sim/riscv/insns/csrrc.h
new file mode 100644
index 0000000000000000000000000000000000000000..0472d80efd5164b885d99d94f7a58d8359a26037
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/csrrc.h
@@ -0,0 +1,8 @@
+bool write = insn.rs1() != 0;
+int csr = validate_csr(insn.csr(), write);
+reg_t old = p->get_csr(csr);
+if (write) {
+  p->set_csr(csr, old & ~RS1);
+}
+WRITE_RD(sext_xlen(old));
+serialize();
diff --git a/tb/riscv-isa-sim/riscv/insns/csrrci.h b/tb/riscv-isa-sim/riscv/insns/csrrci.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d83cc0617edd871ebb9ad823d86a4663c310ce9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/csrrci.h
@@ -0,0 +1,8 @@
+bool write = insn.rs1() != 0;
+int csr = validate_csr(insn.csr(), write);
+reg_t old = p->get_csr(csr);
+if (write) {
+  p->set_csr(csr, old & ~(reg_t)insn.rs1());
+}
+WRITE_RD(sext_xlen(old));
+serialize();
diff --git a/tb/riscv-isa-sim/riscv/insns/csrrs.h b/tb/riscv-isa-sim/riscv/insns/csrrs.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e8bde96379935755ef87b32903e5aadd81a5227
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/csrrs.h
@@ -0,0 +1,8 @@
+bool write = insn.rs1() != 0;
+int csr = validate_csr(insn.csr(), write);
+reg_t old = p->get_csr(csr);
+if (write) {
+  p->set_csr(csr, old | RS1);
+}
+WRITE_RD(sext_xlen(old));
+serialize();
diff --git a/tb/riscv-isa-sim/riscv/insns/csrrsi.h b/tb/riscv-isa-sim/riscv/insns/csrrsi.h
new file mode 100644
index 0000000000000000000000000000000000000000..b673725b54d1cbc8eb0a4e27e4af7d6563eb45b6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/csrrsi.h
@@ -0,0 +1,8 @@
+bool write = insn.rs1() != 0;
+int csr = validate_csr(insn.csr(), write);
+reg_t old = p->get_csr(csr);
+if (write) {
+  p->set_csr(csr, old | insn.rs1());
+}
+WRITE_RD(sext_xlen(old));
+serialize();
diff --git a/tb/riscv-isa-sim/riscv/insns/csrrw.h b/tb/riscv-isa-sim/riscv/insns/csrrw.h
new file mode 100644
index 0000000000000000000000000000000000000000..e45420b570bc52c8bd53e2aaaf893eb6db3b3607
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/csrrw.h
@@ -0,0 +1,5 @@
+int csr = validate_csr(insn.csr(), true);
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, RS1);
+WRITE_RD(sext_xlen(old));
+serialize();
diff --git a/tb/riscv-isa-sim/riscv/insns/csrrwi.h b/tb/riscv-isa-sim/riscv/insns/csrrwi.h
new file mode 100644
index 0000000000000000000000000000000000000000..decadf412141076aec92ec58c4a9101e26456c06
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/csrrwi.h
@@ -0,0 +1,5 @@
+int csr = validate_csr(insn.csr(), true);
+reg_t old = p->get_csr(csr);
+p->set_csr(csr, insn.rs1());
+WRITE_RD(sext_xlen(old));
+serialize();
diff --git a/tb/riscv-isa-sim/riscv/insns/div.h b/tb/riscv-isa-sim/riscv/insns/div.h
new file mode 100644
index 0000000000000000000000000000000000000000..9cbe8d6b321648b144834ef2514948c1b8f19bff
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/div.h
@@ -0,0 +1,9 @@
+require_extension('M');
+sreg_t lhs = sext_xlen(RS1);
+sreg_t rhs = sext_xlen(RS2);
+if(rhs == 0)
+  WRITE_RD(UINT64_MAX);
+else if(lhs == INT64_MIN && rhs == -1)
+  WRITE_RD(lhs);
+else
+  WRITE_RD(sext_xlen(lhs / rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/divu.h b/tb/riscv-isa-sim/riscv/insns/divu.h
new file mode 100644
index 0000000000000000000000000000000000000000..31d758560b8e5b9074c74292b871f32bd5207d06
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/divu.h
@@ -0,0 +1,7 @@
+require_extension('M');
+reg_t lhs = zext_xlen(RS1);
+reg_t rhs = zext_xlen(RS2);
+if(rhs == 0)
+  WRITE_RD(UINT64_MAX);
+else
+  WRITE_RD(sext_xlen(lhs / rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/divuw.h b/tb/riscv-isa-sim/riscv/insns/divuw.h
new file mode 100644
index 0000000000000000000000000000000000000000..e127619aa990ad3394c16810268be611543ef221
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/divuw.h
@@ -0,0 +1,8 @@
+require_extension('M');
+require_rv64;
+reg_t lhs = zext32(RS1);
+reg_t rhs = zext32(RS2);
+if(rhs == 0)
+  WRITE_RD(UINT64_MAX);
+else
+  WRITE_RD(sext32(lhs / rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/divw.h b/tb/riscv-isa-sim/riscv/insns/divw.h
new file mode 100644
index 0000000000000000000000000000000000000000..11be17e4c33d450244c42d98c99d2c31c8a35bd9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/divw.h
@@ -0,0 +1,8 @@
+require_extension('M');
+require_rv64;
+sreg_t lhs = sext32(RS1);
+sreg_t rhs = sext32(RS2);
+if(rhs == 0)
+  WRITE_RD(UINT64_MAX);
+else
+  WRITE_RD(sext32(lhs / rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/dret.h b/tb/riscv-isa-sim/riscv/insns/dret.h
new file mode 100644
index 0000000000000000000000000000000000000000..35c19cb8a29090b774ff8c7a1fa091aa36428e21
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/dret.h
@@ -0,0 +1,9 @@
+require_privilege(PRV_M);
+set_pc_and_serialize(STATE.dpc);
+p->set_privilege(STATE.dcsr.prv);
+
+/* We're not in Debug Mode anymore. */
+STATE.dcsr.cause = 0;
+
+if (STATE.dcsr.step)
+  STATE.single_step = STATE.STEP_STEPPING;
diff --git a/tb/riscv-isa-sim/riscv/insns/ebreak.h b/tb/riscv-isa-sim/riscv/insns/ebreak.h
new file mode 100644
index 0000000000000000000000000000000000000000..736cebef4b63e8a98674b836aebe06a341e972c9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/ebreak.h
@@ -0,0 +1 @@
+throw trap_breakpoint(pc);
diff --git a/tb/riscv-isa-sim/riscv/insns/ecall.h b/tb/riscv-isa-sim/riscv/insns/ecall.h
new file mode 100644
index 0000000000000000000000000000000000000000..e298ac722bca931646fe052a85448590aae09e78
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/ecall.h
@@ -0,0 +1,7 @@
+switch (STATE.prv)
+{
+  case PRV_U: throw trap_user_ecall();
+  case PRV_S: throw trap_supervisor_ecall();
+  case PRV_M: throw trap_machine_ecall();
+  default: abort();
+}
diff --git a/tb/riscv-isa-sim/riscv/insns/fadd_d.h b/tb/riscv-isa-sim/riscv/insns/fadd_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..4a436e24874aa052d61c177c3b6a53502b6ae46d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fadd_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_add(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fadd_q.h b/tb/riscv-isa-sim/riscv/insns/fadd_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..1139a74dc7ef2ae214cb8ae3575536ba0beca03c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fadd_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_add(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fadd_s.h b/tb/riscv-isa-sim/riscv/insns/fadd_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc18d58cd6f4495f40fe72c065a8f025225c7d8d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fadd_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_add(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fclass_d.h b/tb/riscv-isa-sim/riscv/insns/fclass_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..9456123d37f2cd728653b77cc5c4e54d652a7d70
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fclass_d.h
@@ -0,0 +1,3 @@
+require_extension('D');
+require_fp;
+WRITE_RD(f64_classify(f64(FRS1)));
diff --git a/tb/riscv-isa-sim/riscv/insns/fclass_q.h b/tb/riscv-isa-sim/riscv/insns/fclass_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..533075821ce18a4ea38df830b65450358d22c6d5
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fclass_q.h
@@ -0,0 +1,3 @@
+require_extension('Q');
+require_fp;
+WRITE_RD(f128_classify(f128(FRS1)));
diff --git a/tb/riscv-isa-sim/riscv/insns/fclass_s.h b/tb/riscv-isa-sim/riscv/insns/fclass_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..a392db881ed4d055be2c7b0dcc4ca8ac2ea1bc66
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fclass_s.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_RD(f32_classify(f32(FRS1)));
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_d_l.h b/tb/riscv-isa-sim/riscv/insns/fcvt_d_l.h
new file mode 100644
index 0000000000000000000000000000000000000000..08716cffe2d6af6f3f6844381c84b56c40e8d4fe
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_d_l.h
@@ -0,0 +1,6 @@
+require_extension('D');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(i64_to_f64(RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_d_lu.h b/tb/riscv-isa-sim/riscv/insns/fcvt_d_lu.h
new file mode 100644
index 0000000000000000000000000000000000000000..306d7fedd8c9889f6255ab12c5da2867ac734daa
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_d_lu.h
@@ -0,0 +1,6 @@
+require_extension('D');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(ui64_to_f64(RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_d_q.h b/tb/riscv-isa-sim/riscv/insns/fcvt_d_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..b50a43d07dad71ac665c8936768df1168e48fe27
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_d_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_to_f64(f128(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_d_s.h b/tb/riscv-isa-sim/riscv/insns/fcvt_d_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f805b061472c89dabdb25af51fb69a3fe1eefa1
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_d_s.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_to_f64(f32(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_d_w.h b/tb/riscv-isa-sim/riscv/insns/fcvt_d_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c4861c1555c48c9e136086de2890a568e9ddb2e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_d_w.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(i32_to_f64((int32_t)RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_d_wu.h b/tb/riscv-isa-sim/riscv/insns/fcvt_d_wu.h
new file mode 100644
index 0000000000000000000000000000000000000000..1dbf218a1cfa95a4799bb9606e0d35d3f89c9e7f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_d_wu.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(ui32_to_f64((uint32_t)RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_l_d.h b/tb/riscv-isa-sim/riscv/insns/fcvt_l_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..c09e6c4474209623415d398d9f96a0d6e17b1a05
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_l_d.h
@@ -0,0 +1,6 @@
+require_extension('D');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(f64_to_i64(f64(FRS1), RM, true));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_l_q.h b/tb/riscv-isa-sim/riscv/insns/fcvt_l_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..b28bca239b5a03d9b002785bb7af8316c453cb66
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_l_q.h
@@ -0,0 +1,6 @@
+require_extension('Q');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(f128_to_i64(f128(FRS1), RM, true));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_l_s.h b/tb/riscv-isa-sim/riscv/insns/fcvt_l_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..267e0eb8c9b3fa7aa7707f3c243faae247b7d28b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_l_s.h
@@ -0,0 +1,6 @@
+require_extension('F');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(f32_to_i64(f32(FRS1), RM, true));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_lu_d.h b/tb/riscv-isa-sim/riscv/insns/fcvt_lu_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a021204c21278a8b6e17c1a73afa564115e4ad4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_lu_d.h
@@ -0,0 +1,6 @@
+require_extension('D');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(f64_to_ui64(f64(FRS1), RM, true));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_lu_q.h b/tb/riscv-isa-sim/riscv/insns/fcvt_lu_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c5be7c6c8a7eda4c27e15100fa358879f9c87f7
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_lu_q.h
@@ -0,0 +1,6 @@
+require_extension('Q');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(f128_to_ui64(f128(FRS1), RM, true));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_lu_s.h b/tb/riscv-isa-sim/riscv/insns/fcvt_lu_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..94115a3f34da3096bdbeb242b60c3042829da206
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_lu_s.h
@@ -0,0 +1,6 @@
+require_extension('F');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(f32_to_ui64(f32(FRS1), RM, true));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_q_d.h b/tb/riscv-isa-sim/riscv/insns/fcvt_q_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2437b12fc0cda498588bb3e5fdb0dd2d3ed5a5c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_q_d.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_to_f128(f64(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_q_l.h b/tb/riscv-isa-sim/riscv/insns/fcvt_q_l.h
new file mode 100644
index 0000000000000000000000000000000000000000..f1f45ca3e6c24be23b0ce617ad47e5d8440d190a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_q_l.h
@@ -0,0 +1,6 @@
+require_extension('Q');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(i64_to_f128(RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_q_lu.h b/tb/riscv-isa-sim/riscv/insns/fcvt_q_lu.h
new file mode 100644
index 0000000000000000000000000000000000000000..850212e9bc28392d3846ec12927e8a8de9094d3a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_q_lu.h
@@ -0,0 +1,6 @@
+require_extension('Q');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(ui64_to_f128(RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_q_s.h b/tb/riscv-isa-sim/riscv/insns/fcvt_q_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..79e6bb6fc120af2a3d10e050091efcf0c96a306d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_q_s.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_to_f128(f32(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_q_w.h b/tb/riscv-isa-sim/riscv/insns/fcvt_q_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb83f15d99ce0feaef0f8af35077f83f1aef3377
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_q_w.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(i32_to_f128((int32_t)RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_q_wu.h b/tb/riscv-isa-sim/riscv/insns/fcvt_q_wu.h
new file mode 100644
index 0000000000000000000000000000000000000000..7c2ae97ec8f2acde801788acdc6d7f053abfb226
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_q_wu.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(ui32_to_f128((uint32_t)RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_s_d.h b/tb/riscv-isa-sim/riscv/insns/fcvt_s_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..40333359f371b97c5fe9cda14bcdbfae5c8f3690
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_s_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_to_f32(f64(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_s_l.h b/tb/riscv-isa-sim/riscv/insns/fcvt_s_l.h
new file mode 100644
index 0000000000000000000000000000000000000000..9abcc80509eaac8d7b256e6edb98180d48659716
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_s_l.h
@@ -0,0 +1,6 @@
+require_extension('F');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(i64_to_f32(RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_s_lu.h b/tb/riscv-isa-sim/riscv/insns/fcvt_s_lu.h
new file mode 100644
index 0000000000000000000000000000000000000000..70c676edf410ba60fdc3be0599a03077ea8f6d48
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_s_lu.h
@@ -0,0 +1,6 @@
+require_extension('F');
+require_rv64;
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(ui64_to_f32(RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_s_q.h b/tb/riscv-isa-sim/riscv/insns/fcvt_s_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..b0f118ec59253aad7161a0687c8d7e61a6e4b24e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_s_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_to_f32(f128(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_s_w.h b/tb/riscv-isa-sim/riscv/insns/fcvt_s_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ddabd87c12cda406cc3e924ba9c3103815d8298
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_s_w.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(i32_to_f32((int32_t)RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_s_wu.h b/tb/riscv-isa-sim/riscv/insns/fcvt_s_wu.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1394c3fd04af3f078f9cd29d201a52c63e199e4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_s_wu.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(ui32_to_f32((uint32_t)RS1));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_w_d.h b/tb/riscv-isa-sim/riscv/insns/fcvt_w_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..28eb2456d9843d109902a4b4e3e5896b4a394782
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_w_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(sext32(f64_to_i32(f64(FRS1), RM, true)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_w_q.h b/tb/riscv-isa-sim/riscv/insns/fcvt_w_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..e10bafc978b144a136c4c3c25301f230305dd091
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_w_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(sext32(f128_to_i32(f128(FRS1), RM, true)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_w_s.h b/tb/riscv-isa-sim/riscv/insns/fcvt_w_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..d30f1b44055fc303c8b493fb30870ce22225a533
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_w_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(sext32(f32_to_i32(f32(FRS1), RM, true)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_wu_d.h b/tb/riscv-isa-sim/riscv/insns/fcvt_wu_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..5cdc004c81f14010cae760d549de5622cbff7fb9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_wu_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(sext32(f64_to_ui32(f64(FRS1), RM, true)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_wu_q.h b/tb/riscv-isa-sim/riscv/insns/fcvt_wu_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..c391dc87591be7c7760bfed3fd83089f3a703adb
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_wu_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(sext32(f128_to_ui32(f128(FRS1), RM, true)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fcvt_wu_s.h b/tb/riscv-isa-sim/riscv/insns/fcvt_wu_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..034d6816238b8597f87ab071bcbfd40bce3f45ac
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fcvt_wu_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_RD(sext32(f32_to_ui32(f32(FRS1), RM, true)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fdiv_d.h b/tb/riscv-isa-sim/riscv/insns/fdiv_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae7911ae9ae57b314fd1bca5daba43f4af231331
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fdiv_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_div(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fdiv_q.h b/tb/riscv-isa-sim/riscv/insns/fdiv_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..2204831773cdc591a1ced0fb8657ea63c8b281d4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fdiv_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_div(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fdiv_s.h b/tb/riscv-isa-sim/riscv/insns/fdiv_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..c74ff0415cb7026e58f87af4e8c9a056c6eb0310
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fdiv_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_div(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fence.h b/tb/riscv-isa-sim/riscv/insns/fence.h
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tb/riscv-isa-sim/riscv/insns/fence_i.h b/tb/riscv-isa-sim/riscv/insns/fence_i.h
new file mode 100644
index 0000000000000000000000000000000000000000..38dcaf3fce0247d9746f81b21641c5013e8df00a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fence_i.h
@@ -0,0 +1 @@
+MMU.flush_icache();
diff --git a/tb/riscv-isa-sim/riscv/insns/feq_d.h b/tb/riscv-isa-sim/riscv/insns/feq_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..541ed5bbc95e7331acef0c5673dd126e4d3ee3c4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/feq_d.h
@@ -0,0 +1,4 @@
+require_extension('D');
+require_fp;
+WRITE_RD(f64_eq(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/feq_q.h b/tb/riscv-isa-sim/riscv/insns/feq_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..cee2da95a7caeb5f49571b5a03379ffbec4c62bf
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/feq_q.h
@@ -0,0 +1,4 @@
+require_extension('Q');
+require_fp;
+WRITE_RD(f128_eq(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/feq_s.h b/tb/riscv-isa-sim/riscv/insns/feq_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..489bea693836c445c47307049d920645be72635d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/feq_s.h
@@ -0,0 +1,4 @@
+require_extension('F');
+require_fp;
+WRITE_RD(f32_eq(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fld.h b/tb/riscv-isa-sim/riscv/insns/fld.h
new file mode 100644
index 0000000000000000000000000000000000000000..4dea1d47e92476ee8de3aec2119243c566d09ee9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fld.h
@@ -0,0 +1,3 @@
+require_extension('D');
+require_fp;
+WRITE_FRD(f64(MMU.load_uint64(RS1 + insn.i_imm())));
diff --git a/tb/riscv-isa-sim/riscv/insns/fle_d.h b/tb/riscv-isa-sim/riscv/insns/fle_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..419a36fc1b87abe0ce8a652c71a20ec88d208c8b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fle_d.h
@@ -0,0 +1,4 @@
+require_extension('D');
+require_fp;
+WRITE_RD(f64_le(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fle_q.h b/tb/riscv-isa-sim/riscv/insns/fle_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..8368af9dfde814a8024c8066a4cb635e2c43de75
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fle_q.h
@@ -0,0 +1,4 @@
+require_extension('Q');
+require_fp;
+WRITE_RD(f128_le(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fle_s.h b/tb/riscv-isa-sim/riscv/insns/fle_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c0124ef28df81511c9ab2c47f5ecfa7238f67e4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fle_s.h
@@ -0,0 +1,4 @@
+require_extension('F');
+require_fp;
+WRITE_RD(f32_le(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/flq.h b/tb/riscv-isa-sim/riscv/insns/flq.h
new file mode 100644
index 0000000000000000000000000000000000000000..81d225cd2223a0c583f4a20c3104409e75b1a9ea
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/flq.h
@@ -0,0 +1,3 @@
+require_extension('Q');
+require_fp;
+WRITE_FRD(MMU.load_float128(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/flt_d.h b/tb/riscv-isa-sim/riscv/insns/flt_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..7176a961d44f968b34387e68dc95e212f61335b7
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/flt_d.h
@@ -0,0 +1,4 @@
+require_extension('D');
+require_fp;
+WRITE_RD(f64_lt(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/flt_q.h b/tb/riscv-isa-sim/riscv/insns/flt_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..c452141885c0f49b81edc1c2d99330def299ded7
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/flt_q.h
@@ -0,0 +1,4 @@
+require_extension('Q');
+require_fp;
+WRITE_RD(f128_lt(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/flt_s.h b/tb/riscv-isa-sim/riscv/insns/flt_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..40acc34b9cefd3a8bfc9c7cdab9ffaa3641ccc43
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/flt_s.h
@@ -0,0 +1,4 @@
+require_extension('F');
+require_fp;
+WRITE_RD(f32_lt(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/flw.h b/tb/riscv-isa-sim/riscv/insns/flw.h
new file mode 100644
index 0000000000000000000000000000000000000000..61297544405cb65b65da17122e98247fccafa2ff
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/flw.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_FRD(f32(MMU.load_uint32(RS1 + insn.i_imm())));
diff --git a/tb/riscv-isa-sim/riscv/insns/fmadd_d.h b/tb/riscv-isa-sim/riscv/insns/fmadd_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab22bebbf609948ad7f862e9391b50d86b026684
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmadd_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(FRS3)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmadd_q.h b/tb/riscv-isa-sim/riscv/insns/fmadd_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..882dfc1dceebbc0edfaa625f55f8f3c9f962436a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmadd_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_mulAdd(f128(FRS1), f128(FRS2), f128(FRS3)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmadd_s.h b/tb/riscv-isa-sim/riscv/insns/fmadd_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..e919190caaa04608acc04e172614bfcd432ad2e3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmadd_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(FRS3)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmax_d.h b/tb/riscv-isa-sim/riscv/insns/fmax_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..11491f54bce66c61e6d8af1ee9634603238937d0
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmax_d.h
@@ -0,0 +1,9 @@
+require_extension('D');
+require_fp;
+bool greater = f64_lt_quiet(f64(FRS2), f64(FRS1)) ||
+               (f64_eq(f64(FRS2), f64(FRS1)) && (f64(FRS2).v & F64_SIGN));
+if (isNaNF64UI(f64(FRS1).v) && isNaNF64UI(f64(FRS2).v))
+  WRITE_FRD(f64(defaultNaNF64UI));
+else
+  WRITE_FRD(greater || isNaNF64UI(f64(FRS2).v) ? FRS1 : FRS2);
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmax_q.h b/tb/riscv-isa-sim/riscv/insns/fmax_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..7dd7884a678f23c23e2ee2a4a805ee4c5b093405
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmax_q.h
@@ -0,0 +1,9 @@
+require_extension('Q');
+require_fp;
+bool greater = f128_lt_quiet(f128(FRS2), f128(FRS1)) ||
+               (f128_eq(f128(FRS2), f128(FRS1)) && (f128(FRS2).v[1] & F64_SIGN));
+if (isNaNF128(f128(FRS1)) && isNaNF128(f128(FRS2)))
+  WRITE_FRD(f128(defaultNaNF128()));
+else
+  WRITE_FRD(greater || isNaNF128(f128(FRS2)) ? FRS1 : FRS2);
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmax_s.h b/tb/riscv-isa-sim/riscv/insns/fmax_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..41d8f921fdec4eba9eb7f42cb4a58597ae6d6c87
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmax_s.h
@@ -0,0 +1,9 @@
+require_extension('F');
+require_fp;
+bool greater = f32_lt_quiet(f32(FRS2), f32(FRS1)) ||
+               (f32_eq(f32(FRS2), f32(FRS1)) && (f32(FRS2).v & F32_SIGN));
+if (isNaNF32UI(f32(FRS1).v) && isNaNF32UI(f32(FRS2).v))
+  WRITE_FRD(f32(defaultNaNF32UI));
+else
+  WRITE_FRD(greater || isNaNF32UI(f32(FRS2).v) ? FRS1 : FRS2);
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmin_d.h b/tb/riscv-isa-sim/riscv/insns/fmin_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..5cf349d47ee4dda3e850942059b302d108071099
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmin_d.h
@@ -0,0 +1,9 @@
+require_extension('D');
+require_fp;
+bool less = f64_lt_quiet(f64(FRS1), f64(FRS2)) ||
+            (f64_eq(f64(FRS1), f64(FRS2)) && (f64(FRS1).v & F64_SIGN));
+if (isNaNF64UI(f64(FRS1).v) && isNaNF64UI(f64(FRS2).v))
+  WRITE_FRD(f64(defaultNaNF64UI));
+else
+  WRITE_FRD(less || isNaNF64UI(f64(FRS2).v) ? FRS1 : FRS2);
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmin_q.h b/tb/riscv-isa-sim/riscv/insns/fmin_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..fcb9526efd6e5d3d8f536716e4478812776ad03c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmin_q.h
@@ -0,0 +1,9 @@
+require_extension('Q');
+require_fp;
+bool less = f128_lt_quiet(f128(FRS1), f128(FRS2)) ||
+            (f128_eq(f128(FRS1), f128(FRS2)) && (f128(FRS1).v[1] & F64_SIGN));
+if (isNaNF128(f128(FRS1)) && isNaNF128(f128(FRS2)))
+  WRITE_FRD(f128(defaultNaNF128()));
+else
+  WRITE_FRD(less || isNaNF128(f128(FRS2)) ? FRS1 : FRS2);
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmin_s.h b/tb/riscv-isa-sim/riscv/insns/fmin_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..19e119381df1c2ae64d2e9d26c799080b8c580e0
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmin_s.h
@@ -0,0 +1,9 @@
+require_extension('F');
+require_fp;
+bool less = f32_lt_quiet(f32(FRS1), f32(FRS2)) ||
+            (f32_eq(f32(FRS1), f32(FRS2)) && (f32(FRS1).v & F32_SIGN));
+if (isNaNF32UI(f32(FRS1).v) && isNaNF32UI(f32(FRS2).v))
+  WRITE_FRD(f32(defaultNaNF32UI));
+else
+  WRITE_FRD(less || isNaNF32UI(f32(FRS2).v) ? FRS1 : FRS2);
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmsub_d.h b/tb/riscv-isa-sim/riscv/insns/fmsub_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b5bc0f75e4c9c26a42b35409df98d6de063c9c3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmsub_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_mulAdd(f64(FRS1), f64(FRS2), f64(f64(FRS3).v ^ F64_SIGN)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmsub_q.h b/tb/riscv-isa-sim/riscv/insns/fmsub_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bb96c2704d32f7c2496a70c54bab28c871626f9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmsub_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_mulAdd(f128(FRS1), f128(FRS2), f128_negate(f128(FRS3))));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmsub_s.h b/tb/riscv-isa-sim/riscv/insns/fmsub_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..d46c887e7c746137aebe24e64880fadb3fa34fdb
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmsub_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_mulAdd(f32(FRS1), f32(FRS2), f32(f32(FRS3).v ^ F32_SIGN)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmul_d.h b/tb/riscv-isa-sim/riscv/insns/fmul_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..9189d8d9ed4ffad7f9aff7dbc7f939076b092274
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmul_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_mul(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmul_q.h b/tb/riscv-isa-sim/riscv/insns/fmul_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..66f5a05cef91390ca527c7d8b0b76596fc8003b2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmul_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_mul(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmul_s.h b/tb/riscv-isa-sim/riscv/insns/fmul_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..145d5ce4d96fcc4e9d387f9817359ea1baa6f6f9
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmul_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_mul(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fmv_d_x.h b/tb/riscv-isa-sim/riscv/insns/fmv_d_x.h
new file mode 100644
index 0000000000000000000000000000000000000000..0bff5fb7540b347aeba01b0aff264f5d922161b0
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmv_d_x.h
@@ -0,0 +1,4 @@
+require_extension('D');
+require_rv64;
+require_fp;
+WRITE_FRD(f64(RS1));
diff --git a/tb/riscv-isa-sim/riscv/insns/fmv_w_x.h b/tb/riscv-isa-sim/riscv/insns/fmv_w_x.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f713231cb36ac3a6b32d8a6fc6276ef97b6f3db
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmv_w_x.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_FRD(f32(RS1));
diff --git a/tb/riscv-isa-sim/riscv/insns/fmv_x_d.h b/tb/riscv-isa-sim/riscv/insns/fmv_x_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1a23f482735b1dd97221b0f69eeaa2bcc98e39a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmv_x_d.h
@@ -0,0 +1,4 @@
+require_extension('D');
+require_rv64;
+require_fp;
+WRITE_RD(FRS1.v[0]);
diff --git a/tb/riscv-isa-sim/riscv/insns/fmv_x_w.h b/tb/riscv-isa-sim/riscv/insns/fmv_x_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..6754f8693f329bc16faed03f54c4481dbb305a56
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fmv_x_w.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_RD(sext32(FRS1.v[0]));
diff --git a/tb/riscv-isa-sim/riscv/insns/fnmadd_d.h b/tb/riscv-isa-sim/riscv/insns/fnmadd_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8dd743233cdf7ff7ef6dcc07231c003b8b98eb2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fnmadd_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_mulAdd(f64(f64(FRS1).v ^ F64_SIGN), f64(FRS2), f64(f64(FRS3).v ^ F64_SIGN)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fnmadd_q.h b/tb/riscv-isa-sim/riscv/insns/fnmadd_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..a36ce188bb8a0a2a6bbe8332f4f2c26a7060d694
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fnmadd_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_mulAdd(f128_negate(f128(FRS1)), f128(FRS2), f128_negate(f128(FRS3))));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fnmadd_s.h b/tb/riscv-isa-sim/riscv/insns/fnmadd_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c2996e3125909af3f6408f1798c5b717df4ae66
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fnmadd_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_mulAdd(f32(f32(FRS1).v ^ F32_SIGN), f32(FRS2), f32(f32(FRS3).v ^ F32_SIGN)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fnmsub_d.h b/tb/riscv-isa-sim/riscv/insns/fnmsub_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..c29a0b93ca059d7dc74cfc7e399185941bf59ecc
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fnmsub_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_mulAdd(f64(f64(FRS1).v ^ F64_SIGN), f64(FRS2), f64(FRS3)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fnmsub_q.h b/tb/riscv-isa-sim/riscv/insns/fnmsub_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..130b4ce3f50723ca716e4290e949d1987873c072
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fnmsub_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_mulAdd(f128_negate(f128(FRS1)), f128(FRS2), f128(FRS3)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fnmsub_s.h b/tb/riscv-isa-sim/riscv/insns/fnmsub_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..4c61fc7c81170175929bd556095ed97481e9c135
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fnmsub_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_mulAdd(f32(f32(FRS1).v ^ F32_SIGN), f32(FRS2), f32(FRS3)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsd.h b/tb/riscv-isa-sim/riscv/insns/fsd.h
new file mode 100644
index 0000000000000000000000000000000000000000..38c702b7a01bccb72eeb623ee5a84f68f61db615
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsd.h
@@ -0,0 +1,3 @@
+require_extension('D');
+require_fp;
+MMU.store_uint64(RS1 + insn.s_imm(), FRS2.v[0]);
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnj_d.h b/tb/riscv-isa-sim/riscv/insns/fsgnj_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..78f9ce78745c83c69b9f3df1b89a9079046e6eef
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnj_d.h
@@ -0,0 +1,3 @@
+require_extension('D');
+require_fp;
+WRITE_FRD(fsgnj64(FRS1, FRS2, false, false));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnj_q.h b/tb/riscv-isa-sim/riscv/insns/fsgnj_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b9a27083dae78e25760a05728971784b9d37bac
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnj_q.h
@@ -0,0 +1,3 @@
+require_extension('Q');
+require_fp;
+WRITE_FRD(fsgnj128(FRS1, FRS2, false, false));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnj_s.h b/tb/riscv-isa-sim/riscv/insns/fsgnj_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1a70cb7979bf7be59cc299ce64f0e736a308e64
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnj_s.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_FRD(fsgnj32(FRS1, FRS2, false, false));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnjn_d.h b/tb/riscv-isa-sim/riscv/insns/fsgnjn_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..f02c3116b78da8bc11574bab282bf2f7143a1598
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnjn_d.h
@@ -0,0 +1,3 @@
+require_extension('D');
+require_fp;
+WRITE_FRD(fsgnj64(FRS1, FRS2, true, false));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnjn_q.h b/tb/riscv-isa-sim/riscv/insns/fsgnjn_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..38c7bbffbe3299f038bf293f471541749cf2ca1f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnjn_q.h
@@ -0,0 +1,3 @@
+require_extension('Q');
+require_fp;
+WRITE_FRD(fsgnj128(FRS1, FRS2, true, false));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnjn_s.h b/tb/riscv-isa-sim/riscv/insns/fsgnjn_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..35906d6576159d47311f27dbe8debfde6c07446e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnjn_s.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_FRD(fsgnj32(FRS1, FRS2, true, false));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnjx_d.h b/tb/riscv-isa-sim/riscv/insns/fsgnjx_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..c12173719b79c51d84d4a7fc9a0db5effa4aebd1
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnjx_d.h
@@ -0,0 +1,3 @@
+require_extension('D');
+require_fp;
+WRITE_FRD(fsgnj64(FRS1, FRS2, false, true));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnjx_q.h b/tb/riscv-isa-sim/riscv/insns/fsgnjx_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc86d26d9aaa9cf9c20bfd11709367206002b041
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnjx_q.h
@@ -0,0 +1,3 @@
+require_extension('Q');
+require_fp;
+WRITE_FRD(fsgnj128(FRS1, FRS2, false, true));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsgnjx_s.h b/tb/riscv-isa-sim/riscv/insns/fsgnjx_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d5c624b65c152b0435d1e0591732db91807d58e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsgnjx_s.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+WRITE_FRD(fsgnj32(FRS1, FRS2, false, true));
diff --git a/tb/riscv-isa-sim/riscv/insns/fsq.h b/tb/riscv-isa-sim/riscv/insns/fsq.h
new file mode 100644
index 0000000000000000000000000000000000000000..610960e5998c1e8fe20ca0ca4b730174c41920ed
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsq.h
@@ -0,0 +1,3 @@
+require_extension('Q');
+require_fp;
+MMU.store_float128(RS1 + insn.s_imm(), FRS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/fsqrt_d.h b/tb/riscv-isa-sim/riscv/insns/fsqrt_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..da138ba1937f53070d05f81beb096a765580c457
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsqrt_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_sqrt(f64(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsqrt_q.h b/tb/riscv-isa-sim/riscv/insns/fsqrt_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..6cb6ba31170023004e150a8022d786fbd8c0fe3a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsqrt_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_sqrt(f128(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsqrt_s.h b/tb/riscv-isa-sim/riscv/insns/fsqrt_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..747684664e7c9b7b2ac7d8abd0917aadaca041e5
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsqrt_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_sqrt(f32(FRS1)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsub_d.h b/tb/riscv-isa-sim/riscv/insns/fsub_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..1418a063d6ebc1a2925e0884e1faf3c94167f92d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsub_d.h
@@ -0,0 +1,5 @@
+require_extension('D');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f64_sub(f64(FRS1), f64(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsub_q.h b/tb/riscv-isa-sim/riscv/insns/fsub_q.h
new file mode 100644
index 0000000000000000000000000000000000000000..e050e3aa98907c54680eb6a22f3c8db5269869c3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsub_q.h
@@ -0,0 +1,5 @@
+require_extension('Q');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f128_sub(f128(FRS1), f128(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsub_s.h b/tb/riscv-isa-sim/riscv/insns/fsub_s.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6183ea000965c87f50db9491a9242a5139cef53
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsub_s.h
@@ -0,0 +1,5 @@
+require_extension('F');
+require_fp;
+softfloat_roundingMode = RM;
+WRITE_FRD(f32_sub(f32(FRS1), f32(FRS2)));
+set_fp_exceptions;
diff --git a/tb/riscv-isa-sim/riscv/insns/fsw.h b/tb/riscv-isa-sim/riscv/insns/fsw.h
new file mode 100644
index 0000000000000000000000000000000000000000..8af51845f4a5306ef12cf2a703b16f15b6a0ce67
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/fsw.h
@@ -0,0 +1,3 @@
+require_extension('F');
+require_fp;
+MMU.store_uint32(RS1 + insn.s_imm(), FRS2.v[0]);
diff --git a/tb/riscv-isa-sim/riscv/insns/jal.h b/tb/riscv-isa-sim/riscv/insns/jal.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd599641e21553a9d064199b47774032e3c6042b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/jal.h
@@ -0,0 +1,3 @@
+reg_t tmp = npc;
+set_pc(JUMP_TARGET);
+WRITE_RD(tmp);
diff --git a/tb/riscv-isa-sim/riscv/insns/jalr.h b/tb/riscv-isa-sim/riscv/insns/jalr.h
new file mode 100644
index 0000000000000000000000000000000000000000..386e8db1f569793e2ba3cba20da2020ca183cede
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/jalr.h
@@ -0,0 +1,3 @@
+reg_t tmp = npc;
+set_pc((RS1 + insn.i_imm()) & ~reg_t(1));
+WRITE_RD(tmp);
diff --git a/tb/riscv-isa-sim/riscv/insns/lb.h b/tb/riscv-isa-sim/riscv/insns/lb.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f0999caa385317e543baca04266e73d63febe7f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lb.h
@@ -0,0 +1 @@
+WRITE_RD(MMU.load_int8(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/lbu.h b/tb/riscv-isa-sim/riscv/insns/lbu.h
new file mode 100644
index 0000000000000000000000000000000000000000..64d4a688b97d57d3ede6a7b9545157f52f0b145e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lbu.h
@@ -0,0 +1 @@
+WRITE_RD(MMU.load_uint8(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/ld.h b/tb/riscv-isa-sim/riscv/insns/ld.h
new file mode 100644
index 0000000000000000000000000000000000000000..1122b9807b3b273bb008972d35d87de087cad128
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/ld.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(MMU.load_int64(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/lh.h b/tb/riscv-isa-sim/riscv/insns/lh.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d458e0ee1004337d7dd08953a8d8f126cb55a4f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lh.h
@@ -0,0 +1 @@
+WRITE_RD(MMU.load_int16(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/lhu.h b/tb/riscv-isa-sim/riscv/insns/lhu.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d240702adc5c03077bf48d3ba2f5dd1d7d3161d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lhu.h
@@ -0,0 +1 @@
+WRITE_RD(MMU.load_uint16(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/lr_d.h b/tb/riscv-isa-sim/riscv/insns/lr_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..52090c31b87ccfbf1ef216e461a17d421059ee24
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lr_d.h
@@ -0,0 +1,4 @@
+require_extension('A');
+require_rv64;
+MMU.acquire_load_reservation(RS1);
+WRITE_RD(MMU.load_int64(RS1));
diff --git a/tb/riscv-isa-sim/riscv/insns/lr_w.h b/tb/riscv-isa-sim/riscv/insns/lr_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5845a68e1b42dc5f642118a67df4c0ff1e3a756
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lr_w.h
@@ -0,0 +1,3 @@
+require_extension('A');
+MMU.acquire_load_reservation(RS1);
+WRITE_RD(MMU.load_int32(RS1));
diff --git a/tb/riscv-isa-sim/riscv/insns/lui.h b/tb/riscv-isa-sim/riscv/insns/lui.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7b5264e0042407f23c9e58154c6356c8538150a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lui.h
@@ -0,0 +1 @@
+WRITE_RD(insn.u_imm());
diff --git a/tb/riscv-isa-sim/riscv/insns/lw.h b/tb/riscv-isa-sim/riscv/insns/lw.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e8ed040d19e2e2a646c1ea4e97abe113a998720
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lw.h
@@ -0,0 +1 @@
+WRITE_RD(MMU.load_int32(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/lwu.h b/tb/riscv-isa-sim/riscv/insns/lwu.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcc4d75bab8b4d0815fdb8468fd0505d4153f309
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/lwu.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(MMU.load_uint32(RS1 + insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/mret.h b/tb/riscv-isa-sim/riscv/insns/mret.h
new file mode 100644
index 0000000000000000000000000000000000000000..96933cf67262567c2e5cdf39ea73a4f9836d57cc
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/mret.h
@@ -0,0 +1,9 @@
+require_privilege(PRV_M);
+set_pc_and_serialize(p->get_state()->mepc);
+reg_t s = STATE.mstatus;
+reg_t prev_prv = get_field(s, MSTATUS_MPP);
+s = set_field(s, MSTATUS_MIE, get_field(s, MSTATUS_MPIE));
+s = set_field(s, MSTATUS_MPIE, 1);
+s = set_field(s, MSTATUS_MPP, PRV_U);
+p->set_privilege(prev_prv);
+p->set_csr(CSR_MSTATUS, s);
diff --git a/tb/riscv-isa-sim/riscv/insns/mul.h b/tb/riscv-isa-sim/riscv/insns/mul.h
new file mode 100644
index 0000000000000000000000000000000000000000..0102d3651009ab274350f142c4376e9d664b994a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/mul.h
@@ -0,0 +1,2 @@
+require_extension('M');
+WRITE_RD(sext_xlen(RS1 * RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/mulh.h b/tb/riscv-isa-sim/riscv/insns/mulh.h
new file mode 100644
index 0000000000000000000000000000000000000000..051382a96dec4f6489c7eb02a125567a9a992606
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/mulh.h
@@ -0,0 +1,5 @@
+require_extension('M');
+if (xlen == 64)
+  WRITE_RD(mulh(RS1, RS2));
+else
+  WRITE_RD(sext32((sext32(RS1) * sext32(RS2)) >> 32));
diff --git a/tb/riscv-isa-sim/riscv/insns/mulhsu.h b/tb/riscv-isa-sim/riscv/insns/mulhsu.h
new file mode 100644
index 0000000000000000000000000000000000000000..c53f90b00118c77326e778d9d0ff4b765bfb2527
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/mulhsu.h
@@ -0,0 +1,5 @@
+require_extension('M');
+if (xlen == 64)
+  WRITE_RD(mulhsu(RS1, RS2));
+else
+  WRITE_RD(sext32((sext32(RS1) * reg_t((uint32_t)RS2)) >> 32));
diff --git a/tb/riscv-isa-sim/riscv/insns/mulhu.h b/tb/riscv-isa-sim/riscv/insns/mulhu.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ae365080c6c5955f25c406dc2c7e0b76c223770
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/mulhu.h
@@ -0,0 +1,5 @@
+require_extension('M');
+if (xlen == 64)
+  WRITE_RD(mulhu(RS1, RS2));
+else
+  WRITE_RD(sext32(((uint64_t)(uint32_t)RS1 * (uint64_t)(uint32_t)RS2) >> 32));
diff --git a/tb/riscv-isa-sim/riscv/insns/mulw.h b/tb/riscv-isa-sim/riscv/insns/mulw.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed555452b7a32445a9b8ebcd9477d69821edfcd6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/mulw.h
@@ -0,0 +1,3 @@
+require_extension('M');
+require_rv64;
+WRITE_RD(sext32(RS1 * RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/or.h b/tb/riscv-isa-sim/riscv/insns/or.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f2fffc22e2a2ca0ae6663c79f31d27f5cf94ffb
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/or.h
@@ -0,0 +1 @@
+WRITE_RD(RS1 | RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/ori.h b/tb/riscv-isa-sim/riscv/insns/ori.h
new file mode 100644
index 0000000000000000000000000000000000000000..6403c39b5b476fa98948a6aa44dbbbdb1b430a74
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/ori.h
@@ -0,0 +1 @@
+WRITE_RD(insn.i_imm() | RS1);
diff --git a/tb/riscv-isa-sim/riscv/insns/rem.h b/tb/riscv-isa-sim/riscv/insns/rem.h
new file mode 100644
index 0000000000000000000000000000000000000000..858799577ccbc4875aa38932455c5d54261b545b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/rem.h
@@ -0,0 +1,9 @@
+require_extension('M');
+sreg_t lhs = sext_xlen(RS1);
+sreg_t rhs = sext_xlen(RS2);
+if(rhs == 0)
+  WRITE_RD(lhs);
+else if(lhs == INT64_MIN && rhs == -1)
+  WRITE_RD(0);
+else
+  WRITE_RD(sext_xlen(lhs % rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/remu.h b/tb/riscv-isa-sim/riscv/insns/remu.h
new file mode 100644
index 0000000000000000000000000000000000000000..e74774cc23d01baf018971b9b9e75a44d6001025
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/remu.h
@@ -0,0 +1,7 @@
+require_extension('M');
+reg_t lhs = zext_xlen(RS1);
+reg_t rhs = zext_xlen(RS2);
+if(rhs == 0)
+  WRITE_RD(sext_xlen(RS1));
+else
+  WRITE_RD(sext_xlen(lhs % rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/remuw.h b/tb/riscv-isa-sim/riscv/insns/remuw.h
new file mode 100644
index 0000000000000000000000000000000000000000..b239c8f32397db74e128e8139bbf028a5a3f004d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/remuw.h
@@ -0,0 +1,8 @@
+require_extension('M');
+require_rv64;
+reg_t lhs = zext32(RS1);
+reg_t rhs = zext32(RS2);
+if(rhs == 0)
+  WRITE_RD(sext32(lhs));
+else
+  WRITE_RD(sext32(lhs % rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/remw.h b/tb/riscv-isa-sim/riscv/insns/remw.h
new file mode 100644
index 0000000000000000000000000000000000000000..56221ccd4e742dbe142858d0e7739c182c95818a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/remw.h
@@ -0,0 +1,8 @@
+require_extension('M');
+require_rv64;
+sreg_t lhs = sext32(RS1);
+sreg_t rhs = sext32(RS2);
+if(rhs == 0)
+  WRITE_RD(lhs);
+else
+  WRITE_RD(sext32(lhs % rhs));
diff --git a/tb/riscv-isa-sim/riscv/insns/sb.h b/tb/riscv-isa-sim/riscv/insns/sb.h
new file mode 100644
index 0000000000000000000000000000000000000000..8729c2d47f46f5884e4d88ea4cb95e2e0a49c54f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sb.h
@@ -0,0 +1 @@
+MMU.store_uint8(RS1 + insn.s_imm(), RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/sc_d.h b/tb/riscv-isa-sim/riscv/insns/sc_d.h
new file mode 100644
index 0000000000000000000000000000000000000000..aeeabd350d36e0c98e2c76bf02dc8adc1f87905b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sc_d.h
@@ -0,0 +1,11 @@
+require_extension('A');
+require_rv64;
+if (MMU.check_load_reservation(RS1))
+{
+  MMU.store_uint64(RS1, RS2);
+  WRITE_RD(0);
+}
+else
+  WRITE_RD(1);
+
+MMU.yield_load_reservation();
diff --git a/tb/riscv-isa-sim/riscv/insns/sc_w.h b/tb/riscv-isa-sim/riscv/insns/sc_w.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b4be505840b0102fe1ffa9c8e9712b9b0658f1d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sc_w.h
@@ -0,0 +1,10 @@
+require_extension('A');
+if (MMU.check_load_reservation(RS1))
+{
+  MMU.store_uint32(RS1, RS2);
+  WRITE_RD(0);
+}
+else
+  WRITE_RD(1);
+
+MMU.yield_load_reservation();
diff --git a/tb/riscv-isa-sim/riscv/insns/sd.h b/tb/riscv-isa-sim/riscv/insns/sd.h
new file mode 100644
index 0000000000000000000000000000000000000000..664deb2c95ae5d0ec40a99f1b66d86ea8526c036
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sd.h
@@ -0,0 +1,2 @@
+require_rv64;
+MMU.store_uint64(RS1 + insn.s_imm(), RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/sfence_vma.h b/tb/riscv-isa-sim/riscv/insns/sfence_vma.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc4625f0bfe033ca3070bcac8892805514368876
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sfence_vma.h
@@ -0,0 +1,2 @@
+require_privilege(get_field(STATE.mstatus, MSTATUS_TVM) ? PRV_M : PRV_S);
+MMU.flush_tlb();
diff --git a/tb/riscv-isa-sim/riscv/insns/sh.h b/tb/riscv-isa-sim/riscv/insns/sh.h
new file mode 100644
index 0000000000000000000000000000000000000000..22aa3a889e58db8294691bfb97b116fd567daba1
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sh.h
@@ -0,0 +1 @@
+MMU.store_uint16(RS1 + insn.s_imm(), RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/sll.h b/tb/riscv-isa-sim/riscv/insns/sll.h
new file mode 100644
index 0000000000000000000000000000000000000000..7db761318f576847e2421ce2fbf4fabbcd71e8a7
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sll.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(RS1 << (RS2 & (xlen-1))));
diff --git a/tb/riscv-isa-sim/riscv/insns/slli.h b/tb/riscv-isa-sim/riscv/insns/slli.h
new file mode 100644
index 0000000000000000000000000000000000000000..26782fda3d1a00f0d44d4e17cc5f661eec055873
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/slli.h
@@ -0,0 +1,2 @@
+require(SHAMT < xlen);
+WRITE_RD(sext_xlen(RS1 << SHAMT));
diff --git a/tb/riscv-isa-sim/riscv/insns/slliw.h b/tb/riscv-isa-sim/riscv/insns/slliw.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1fda656c25093edc5ee67b430dcf9665545ba2d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/slliw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32(RS1 << SHAMT));
diff --git a/tb/riscv-isa-sim/riscv/insns/sllw.h b/tb/riscv-isa-sim/riscv/insns/sllw.h
new file mode 100644
index 0000000000000000000000000000000000000000..affe894441be2778b253a7f2ef33e764fd759468
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sllw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32(RS1 << (RS2 & 0x1F)));
diff --git a/tb/riscv-isa-sim/riscv/insns/slt.h b/tb/riscv-isa-sim/riscv/insns/slt.h
new file mode 100644
index 0000000000000000000000000000000000000000..25ccd45ee8958be21ae69f8507705032ec9fad1b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/slt.h
@@ -0,0 +1 @@
+WRITE_RD(sreg_t(RS1) < sreg_t(RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/slti.h b/tb/riscv-isa-sim/riscv/insns/slti.h
new file mode 100644
index 0000000000000000000000000000000000000000..3671d2418fbbd3771f6f412cf301748a4eac2a4c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/slti.h
@@ -0,0 +1 @@
+WRITE_RD(sreg_t(RS1) < sreg_t(insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/sltiu.h b/tb/riscv-isa-sim/riscv/insns/sltiu.h
new file mode 100644
index 0000000000000000000000000000000000000000..f39845713fbc80eda8acbb8ed83cb6a68b0b7f09
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sltiu.h
@@ -0,0 +1 @@
+WRITE_RD(RS1 < reg_t(insn.i_imm()));
diff --git a/tb/riscv-isa-sim/riscv/insns/sltu.h b/tb/riscv-isa-sim/riscv/insns/sltu.h
new file mode 100644
index 0000000000000000000000000000000000000000..84d97a2a3d2f89c6d3c59654cf86492b84b22cf3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sltu.h
@@ -0,0 +1 @@
+WRITE_RD(RS1 < RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/sra.h b/tb/riscv-isa-sim/riscv/insns/sra.h
new file mode 100644
index 0000000000000000000000000000000000000000..403b9b733a5e3cce36c7885e906a80f4dace1309
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sra.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(sext_xlen(RS1) >> (RS2 & (xlen-1))));
diff --git a/tb/riscv-isa-sim/riscv/insns/srai.h b/tb/riscv-isa-sim/riscv/insns/srai.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ae1d4e5af36affad7c319225e89508b8bbce504
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/srai.h
@@ -0,0 +1,2 @@
+require(SHAMT < xlen);
+WRITE_RD(sext_xlen(sext_xlen(RS1) >> SHAMT));
diff --git a/tb/riscv-isa-sim/riscv/insns/sraiw.h b/tb/riscv-isa-sim/riscv/insns/sraiw.h
new file mode 100644
index 0000000000000000000000000000000000000000..b344459bf423c61a8e04e823ba5052a79e482102
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sraiw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32(int32_t(RS1) >> SHAMT));
diff --git a/tb/riscv-isa-sim/riscv/insns/sraw.h b/tb/riscv-isa-sim/riscv/insns/sraw.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca9c0c76ce8e855cb6fd2cdec9087c84b8b26daf
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sraw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32(int32_t(RS1) >> (RS2 & 0x1F)));
diff --git a/tb/riscv-isa-sim/riscv/insns/sret.h b/tb/riscv-isa-sim/riscv/insns/sret.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae841de93f19cc1111761e545780947f4d95fb41
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sret.h
@@ -0,0 +1,9 @@
+require_privilege(get_field(STATE.mstatus, MSTATUS_TSR) ? PRV_M : PRV_S);
+set_pc_and_serialize(p->get_state()->sepc);
+reg_t s = STATE.mstatus;
+reg_t prev_prv = get_field(s, MSTATUS_SPP);
+s = set_field(s, MSTATUS_SIE, get_field(s, MSTATUS_SPIE));
+s = set_field(s, MSTATUS_SPIE, 1);
+s = set_field(s, MSTATUS_SPP, PRV_U);
+p->set_privilege(prev_prv);
+p->set_csr(CSR_MSTATUS, s);
diff --git a/tb/riscv-isa-sim/riscv/insns/srl.h b/tb/riscv-isa-sim/riscv/insns/srl.h
new file mode 100644
index 0000000000000000000000000000000000000000..0dabe9ecde160c95c58e72248cd78b22918d5d3d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/srl.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(zext_xlen(RS1) >> (RS2 & (xlen-1))));
diff --git a/tb/riscv-isa-sim/riscv/insns/srli.h b/tb/riscv-isa-sim/riscv/insns/srli.h
new file mode 100644
index 0000000000000000000000000000000000000000..ea0b40d6549b5f1f9ea51b1d8d5988e514ac0ef4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/srli.h
@@ -0,0 +1,2 @@
+require(SHAMT < xlen);
+WRITE_RD(sext_xlen(zext_xlen(RS1) >> SHAMT));
diff --git a/tb/riscv-isa-sim/riscv/insns/srliw.h b/tb/riscv-isa-sim/riscv/insns/srliw.h
new file mode 100644
index 0000000000000000000000000000000000000000..c657d3da8bbeb078318900619b4eda189086ed1a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/srliw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32((uint32_t)RS1 >> SHAMT));
diff --git a/tb/riscv-isa-sim/riscv/insns/srlw.h b/tb/riscv-isa-sim/riscv/insns/srlw.h
new file mode 100644
index 0000000000000000000000000000000000000000..a8eb4519859382c5b0b3a9f93bb34a48b1edceef
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/srlw.h
@@ -0,0 +1,2 @@
+require_rv64;
+WRITE_RD(sext32((uint32_t)RS1 >> (RS2 & 0x1F)));
diff --git a/tb/riscv-isa-sim/riscv/insns/sub.h b/tb/riscv-isa-sim/riscv/insns/sub.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ed48f7449061acd822a616d24fb8b16303cb13b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sub.h
@@ -0,0 +1 @@
+WRITE_RD(sext_xlen(RS1 - RS2));
diff --git a/tb/riscv-isa-sim/riscv/insns/subw.h b/tb/riscv-isa-sim/riscv/insns/subw.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4168efe824f608ff0ab3b841db92bd50f378bde
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/subw.h
@@ -0,0 +1,3 @@
+require_rv64;
+WRITE_RD(sext32(RS1 - RS2));
+
diff --git a/tb/riscv-isa-sim/riscv/insns/sw.h b/tb/riscv-isa-sim/riscv/insns/sw.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa5ead372e57b31785dc1a2a1ebc681197660869
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/sw.h
@@ -0,0 +1 @@
+MMU.store_uint32(RS1 + insn.s_imm(), RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/wfi.h b/tb/riscv-isa-sim/riscv/insns/wfi.h
new file mode 100644
index 0000000000000000000000000000000000000000..6504b78c608b0cf192df1bfd8592cb799389ff42
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/wfi.h
@@ -0,0 +1,2 @@
+require_privilege(get_field(STATE.mstatus, MSTATUS_TW) ? PRV_M : PRV_S);
+wfi();
diff --git a/tb/riscv-isa-sim/riscv/insns/xor.h b/tb/riscv-isa-sim/riscv/insns/xor.h
new file mode 100644
index 0000000000000000000000000000000000000000..771efa7fa05aa5f7341ba48f6cc66935ec788a5a
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/xor.h
@@ -0,0 +1 @@
+WRITE_RD(RS1 ^ RS2);
diff --git a/tb/riscv-isa-sim/riscv/insns/xori.h b/tb/riscv-isa-sim/riscv/insns/xori.h
new file mode 100644
index 0000000000000000000000000000000000000000..33ce6307419d25055922e60bf4da30c89e3de8b3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/insns/xori.h
@@ -0,0 +1 @@
+WRITE_RD(insn.i_imm() ^ RS1);
diff --git a/tb/riscv-isa-sim/riscv/interactive.cc b/tb/riscv-isa-sim/riscv/interactive.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c96c71ace75f358ee2f4139e7a4688576f803443
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/interactive.cc
@@ -0,0 +1,369 @@
+// See LICENSE for license details.
+
+#include "decode.h"
+#include "disasm.h"
+#include "sim.h"
+#include "mmu.h"
+#include <sys/mman.h>
+#include <termios.h>
+#include <map>
+#include <iostream>
+#include <climits>
+#include <cinttypes>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <math.h>
+
+DECLARE_TRAP(-1, interactive)
+
+processor_t *sim_t::get_core(const std::string& i)
+{
+  char *ptr;
+  unsigned long p = strtoul(i.c_str(), &ptr, 10);
+  if (*ptr || p >= procs.size())
+    throw trap_interactive();
+  return get_core(p);
+}
+
+static std::string readline(int fd)
+{
+  struct termios tios;
+  bool noncanonical = tcgetattr(fd, &tios) == 0 && (tios.c_lflag & ICANON) == 0;
+
+  std::string s;
+  for (char ch; read(fd, &ch, 1) == 1; )
+  {
+    if (ch == '\x7f')
+    {
+      if (s.empty())
+        continue;
+      s.erase(s.end()-1);
+
+      if (noncanonical && write(fd, "\b \b", 3) != 3)
+        ; // shut up gcc
+    }
+    else if (noncanonical && write(fd, &ch, 1) != 1)
+      ; // shut up gcc
+
+    if (ch == '\n')
+      break;
+    if (ch != '\x7f')
+      s += ch;
+  }
+  return s;
+}
+
+void sim_t::interactive()
+{
+  typedef void (sim_t::*interactive_func)(const std::string&, const std::vector<std::string>&);
+  std::map<std::string,interactive_func> funcs;
+
+  funcs["run"] = &sim_t::interactive_run_noisy;
+  funcs["r"] = funcs["run"];
+  funcs["rs"] = &sim_t::interactive_run_silent;
+  funcs["reg"] = &sim_t::interactive_reg;
+  funcs["freg"] = &sim_t::interactive_freg;
+  funcs["fregs"] = &sim_t::interactive_fregs;
+  funcs["fregd"] = &sim_t::interactive_fregd;
+  funcs["pc"] = &sim_t::interactive_pc;
+  funcs["mem"] = &sim_t::interactive_mem;
+  funcs["str"] = &sim_t::interactive_str;
+  funcs["until"] = &sim_t::interactive_until_silent;
+  funcs["untiln"] = &sim_t::interactive_until_noisy;
+  funcs["while"] = &sim_t::interactive_until_silent;
+  funcs["quit"] = &sim_t::interactive_quit;
+  funcs["q"] = funcs["quit"];
+  funcs["help"] = &sim_t::interactive_help;
+  funcs["h"] = funcs["help"];
+
+  while (!done())
+  {
+    std::cerr << ": " << std::flush;
+    std::string s = readline(2);
+
+    std::stringstream ss(s);
+    std::string cmd, tmp;
+    std::vector<std::string> args;
+
+    if (!(ss >> cmd))
+    {
+      set_procs_debug(true);
+      step(1);
+      continue;
+    }
+
+    while (ss >> tmp)
+      args.push_back(tmp);
+
+    try
+    {
+      if(funcs.count(cmd))
+        (this->*funcs[cmd])(cmd, args);
+      else
+        fprintf(stderr, "Unknown command %s\n", cmd.c_str());
+    }
+    catch(trap_t t) {}
+  }
+  ctrlc_pressed = false;
+}
+
+void sim_t::interactive_help(const std::string& cmd, const std::vector<std::string>& args)
+{
+  std::cerr <<
+    "Interactive commands:\n"
+    "reg <core> [reg]                # Display [reg] (all if omitted) in <core>\n"
+    "fregs <core> <reg>              # Display single precision <reg> in <core>\n"
+    "fregd <core> <reg>              # Display double precision <reg> in <core>\n"
+    "pc <core>                       # Show current PC in <core>\n"
+    "mem <hex addr>                  # Show contents of physical memory\n"
+    "str <hex addr>                  # Show NUL-terminated C string\n"
+    "until reg <core> <reg> <val>    # Stop when <reg> in <core> hits <val>\n"
+    "until pc <core> <val>           # Stop when PC in <core> hits <val>\n"
+    "untiln pc <core> <val>          # Run noisy and stop when PC in <core> hits <val>\n"
+    "until mem <addr> <val>          # Stop when memory <addr> becomes <val>\n"
+    "while reg <core> <reg> <val>    # Run while <reg> in <core> is <val>\n"
+    "while pc <core> <val>           # Run while PC in <core> is <val>\n"
+    "while mem <addr> <val>          # Run while memory <addr> is <val>\n"
+    "run [count]                     # Resume noisy execution (until CTRL+C, or [count] insns)\n"
+    "r [count]                         Alias for run\n"
+    "rs [count]                      # Resume silent execution (until CTRL+C, or [count] insns)\n"
+    "quit                            # End the simulation\n"
+    "q                                 Alias for quit\n"
+    "help                            # This screen!\n"
+    "h                                 Alias for help\n"
+    "Note: Hitting enter is the same as: run 1\n"
+    << std::flush;
+}
+
+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)
+{
+  size_t steps = args.size() ? atoll(args[0].c_str()) : -1;
+  ctrlc_pressed = false;
+  set_procs_debug(noisy);
+  for (size_t i = 0; i < steps && !ctrlc_pressed && !done(); i++)
+    step(1);
+}
+
+void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
+{
+  exit(0);
+}
+
+reg_t sim_t::get_pc(const std::vector<std::string>& args)
+{
+  if(args.size() != 1)
+    throw trap_interactive();
+
+  processor_t *p = get_core(args[0]);
+  return p->get_state()->pc;
+}
+
+void sim_t::interactive_pc(const std::string& cmd, const std::vector<std::string>& args)
+{
+  fprintf(stderr, "0x%016" PRIx64 "\n", get_pc(args));
+}
+
+reg_t sim_t::get_reg(const std::vector<std::string>& args)
+{
+  if(args.size() != 2)
+    throw trap_interactive();
+
+  processor_t *p = get_core(args[0]);
+
+  unsigned long r = std::find(xpr_name, xpr_name + NXPR, args[1]) - xpr_name;
+  if (r == NXPR) {
+    char *ptr;
+    r = strtoul(args[1].c_str(), &ptr, 10);
+    if (*ptr) {
+      #define DECLARE_CSR(name, number) if (args[1] == #name) return p->get_csr(number);
+      #include "encoding.h"              // generates if's for all csrs
+      r = NXPR;                          // else case (csr name not found)
+      #undef DECLARE_CSR
+    }
+  }
+
+  if (r >= NXPR)
+    throw trap_interactive();
+
+  return p->get_state()->XPR[r];
+}
+
+freg_t sim_t::get_freg(const std::vector<std::string>& args)
+{
+  if(args.size() != 2)
+    throw trap_interactive();
+
+  processor_t *p = get_core(args[0]);
+  int r = std::find(fpr_name, fpr_name + NFPR, args[1]) - fpr_name;
+  if (r == NFPR)
+    r = atoi(args[1].c_str());
+  if (r >= NFPR)
+    throw trap_interactive();
+
+  return p->get_state()->FPR[r];
+}
+
+void sim_t::interactive_reg(const std::string& cmd, const std::vector<std::string>& args)
+{
+  if (args.size() == 1) {
+    // Show all the regs!
+    processor_t *p = get_core(args[0]);
+
+    for (int r = 0; r < NXPR; ++r) {
+      fprintf(stderr, "%-4s: 0x%016" PRIx64 "  ", xpr_name[r], p->get_state()->XPR[r]);
+      if ((r + 1) % 4 == 0)
+        fprintf(stderr, "\n");
+    }
+  } else
+    fprintf(stderr, "0x%016" PRIx64 "\n", get_reg(args));
+}
+
+union fpr
+{
+  freg_t r;
+  float s;
+  double d;
+};
+
+void sim_t::interactive_freg(const std::string& cmd, const std::vector<std::string>& args)
+{
+  freg_t r = get_freg(args);
+  fprintf(stderr, "0x%016" PRIx64 "%016" PRIx64 "\n", r.v[1], r.v[0]);
+}
+
+void sim_t::interactive_fregs(const std::string& cmd, const std::vector<std::string>& args)
+{
+  fpr f;
+  f.r = get_freg(args);
+  fprintf(stderr, "%g\n", isBoxedF32(f.r) ? (double)f.s : NAN);
+}
+
+void sim_t::interactive_fregd(const std::string& cmd, const std::vector<std::string>& args)
+{
+  fpr f;
+  f.r = get_freg(args);
+  fprintf(stderr, "%g\n", isBoxedF64(f.r) ? f.d : NAN);
+}
+
+reg_t sim_t::get_mem(const std::vector<std::string>& args)
+{
+  if(args.size() != 1 && args.size() != 2)
+    throw trap_interactive();
+
+  std::string addr_str = args[0];
+  mmu_t* mmu = debug_mmu;
+  if(args.size() == 2)
+  {
+    processor_t *p = get_core(args[0]);
+    mmu = p->get_mmu();
+    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)
+{
+  fprintf(stderr, "0x%016" PRIx64 "\n", get_mem(args));
+}
+
+void sim_t::interactive_str(const std::string& cmd, const std::vector<std::string>& args)
+{
+  if(args.size() != 1)
+    throw trap_interactive();
+
+  reg_t addr = strtol(args[0].c_str(),NULL,16);
+
+  char ch;
+  while((ch = debug_mmu->load_uint8(addr++)))
+    putchar(ch);
+
+  putchar('\n');
+}
+
+void sim_t::interactive_until_silent(const std::string& cmd, const std::vector<std::string>& args)
+{
+  interactive_until(cmd, args, false);
+}
+
+void sim_t::interactive_until_noisy(const std::string& cmd, const std::vector<std::string>& args)
+{
+  interactive_until(cmd, args, true);
+}
+
+void sim_t::interactive_until(const std::string& cmd, const std::vector<std::string>& args, bool noisy)
+{
+  bool cmd_until = cmd == "until" || cmd == "untiln";
+
+  if(args.size() < 3)
+    return;
+
+  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);
+
+  auto func = args[0] == "reg" ? &sim_t::get_reg :
+              args[0] == "pc"  ? &sim_t::get_pc :
+              args[0] == "mem" ? &sim_t::get_mem :
+              NULL;
+
+  if (func == NULL)
+    return;
+
+  ctrlc_pressed = false;
+
+  while (1)
+  {
+    try
+    {
+      reg_t current = (this->*func)(args2);
+
+      if (cmd_until == (current == val))
+        break;
+      if (ctrlc_pressed)
+        break;
+    }
+    catch (trap_t t) {}
+
+    set_procs_debug(noisy);
+    step(1);
+  }
+}
diff --git a/tb/riscv-isa-sim/riscv/jtag_dtm.cc b/tb/riscv-isa-sim/riscv/jtag_dtm.cc
new file mode 100644
index 0000000000000000000000000000000000000000..365528a49a7566919c7b0742151f3fab846b5435
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/jtag_dtm.cc
@@ -0,0 +1,184 @@
+#include <stdio.h>
+
+#include "decode.h"
+#include "jtag_dtm.h"
+#include "debug_module.h"
+#include "debug_defines.h"
+
+#if 0
+#  define D(x) x
+#else
+#  define D(x)
+#endif
+
+enum {
+  IR_IDCODE=1,
+  IR_DTMCONTROL=0x10,
+  IR_DBUS=0x11,
+  IR_RESET=0x1c
+};
+
+#define DTMCONTROL_VERSION      0xf
+#define DTMCONTROL_ABITS        (0x3f << 4)
+#define DTMCONTROL_DBUSSTAT     (3<<10)
+#define DTMCONTROL_IDLE         (7<<12)
+#define DTMCONTROL_DBUSRESET    (1<<16)
+
+#define DMI_OP                 3
+#define DMI_DATA               (0xffffffffL<<2)
+#define DMI_ADDRESS            ((1L<<(abits+34)) - (1L<<34))
+
+#define DMI_OP_STATUS_SUCCESS	0
+#define DMI_OP_STATUS_RESERVED	1
+#define DMI_OP_STATUS_FAILED	2
+#define DMI_OP_STATUS_BUSY	3
+
+#define DMI_OP_NOP	        0
+#define DMI_OP_READ	        1
+#define DMI_OP_WRITE	        2
+#define DMI_OP_RESERVED	        3
+
+jtag_dtm_t::jtag_dtm_t(debug_module_t *dm) :
+  dm(dm),
+  _tck(false), _tms(false), _tdi(false), _tdo(false),
+  dtmcontrol((abits << DTM_DTMCS_ABITS_OFFSET) | 1),
+  dmi(DMI_OP_STATUS_SUCCESS << DTM_DMI_OP_OFFSET),
+  _state(TEST_LOGIC_RESET)
+{
+}
+
+void jtag_dtm_t::reset() {
+  _state = TEST_LOGIC_RESET;
+}
+
+void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
+  const jtag_state_t next[16][2] = {
+    /* TEST_LOGIC_RESET */    { RUN_TEST_IDLE, TEST_LOGIC_RESET },
+    /* RUN_TEST_IDLE */       { RUN_TEST_IDLE, SELECT_DR_SCAN },
+    /* SELECT_DR_SCAN */      { CAPTURE_DR, SELECT_IR_SCAN },
+    /* CAPTURE_DR */          { SHIFT_DR, EXIT1_DR },
+    /* SHIFT_DR */            { SHIFT_DR, EXIT1_DR },
+    /* EXIT1_DR */            { PAUSE_DR, UPDATE_DR },
+    /* PAUSE_DR */            { PAUSE_DR, EXIT2_DR },
+    /* EXIT2_DR */            { SHIFT_DR, UPDATE_DR },
+    /* UPDATE_DR */           { RUN_TEST_IDLE, SELECT_DR_SCAN },
+    /* SELECT_IR_SCAN */      { CAPTURE_IR, TEST_LOGIC_RESET },
+    /* CAPTURE_IR */          { SHIFT_IR, EXIT1_IR },
+    /* SHIFT_IR */            { SHIFT_IR, EXIT1_IR },
+    /* EXIT1_IR */            { PAUSE_IR, UPDATE_IR },
+    /* PAUSE_IR */            { PAUSE_IR, EXIT2_IR },
+    /* EXIT2_IR */            { SHIFT_IR, UPDATE_IR },
+    /* UPDATE_IR */           { RUN_TEST_IDLE, SELECT_DR_SCAN }
+  };
+
+  if (!_tck && tck) {
+    // Positive clock edge.
+
+    switch (_state) {
+      case SHIFT_DR:
+        dr >>= 1;
+        dr |= (uint64_t) _tdi << (dr_length-1);
+        break;
+      case SHIFT_IR:
+        ir >>= 1;
+        ir |= _tdi << (ir_length-1);
+        break;
+      default:
+        break;
+    }
+    _state = next[_state][_tms];
+    switch (_state) {
+      case TEST_LOGIC_RESET:
+        ir = IR_IDCODE;
+        break;
+      case CAPTURE_DR:
+        capture_dr();
+        break;
+      case SHIFT_DR:
+        _tdo = dr & 1;
+        break;
+      case UPDATE_DR:
+        update_dr();
+        break;
+      case CAPTURE_IR:
+        break;
+      case SHIFT_IR:
+        _tdo = ir & 1;
+        break;
+      //case UPDATE_IR:
+        //if (ir == IR_RESET) {
+          // Make a reset happen
+        //}
+        //break;
+      default:
+        break;
+    }
+  }
+
+  D(fprintf(stderr, "state=%2d, tdi=%d, tdo=%d, tms=%d, tck=%d, ir=0x%02x, "
+        "dr=0x%lx\n",
+        _state, _tdi, _tdo, _tms, _tck, ir, dr));
+
+  _tck = tck;
+  _tms = tms;
+  _tdi = tdi;
+}
+
+void jtag_dtm_t::capture_dr()
+{
+  switch (ir) {
+    case IR_IDCODE:
+      dr = idcode;
+      dr_length = 32;
+      break;
+    case IR_DTMCONTROL:
+      dr = dtmcontrol;
+      dr_length = 32;
+      break;
+    case IR_DBUS:
+      dr = dmi;
+      dr_length = abits + 34;
+      break;
+    default:
+      D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
+      break;
+  }
+  D(fprintf(stderr, "Capture DR; IR=0x%x, DR=0x%lx (%d bits)\n",
+        ir, dr, dr_length));
+}
+
+void jtag_dtm_t::update_dr()
+{
+  D(fprintf(stderr, "Update DR; IR=0x%x, DR=0x%lx (%d bits)\n",
+        ir, dr, dr_length));
+  switch (ir) {
+    case IR_DBUS:
+      {
+        unsigned op = get_field(dr, DMI_OP);
+        uint32_t data = get_field(dr, DMI_DATA);
+        unsigned address = get_field(dr, DMI_ADDRESS);
+
+        dmi = dr;
+
+        bool success = true;
+        if (op == DMI_OP_READ) {
+          uint32_t value;
+          if (dm->dmi_read(address, &value)) {
+            dmi = set_field(dmi, DMI_DATA, value);
+          } else {
+            success = false;
+          }
+        } else if (op == DMI_OP_WRITE) {
+          success = dm->dmi_write(address, data);
+        }
+
+        if (success) {
+          dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_SUCCESS);
+        } else {
+          dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_FAILED);
+        }
+        D(fprintf(stderr, "dmi=0x%lx\n", dmi));
+      }
+      break;
+  }
+}
diff --git a/tb/riscv-isa-sim/riscv/jtag_dtm.h b/tb/riscv-isa-sim/riscv/jtag_dtm.h
new file mode 100644
index 0000000000000000000000000000000000000000..063e3f40b3416271255699b9fd2dfee0c781f507
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/jtag_dtm.h
@@ -0,0 +1,61 @@
+#ifndef JTAG_DTM_H
+#define JTAG_DTM_H
+
+#include <stdint.h>
+
+class debug_module_t;
+
+typedef enum {
+  TEST_LOGIC_RESET,
+  RUN_TEST_IDLE,
+  SELECT_DR_SCAN,
+  CAPTURE_DR,
+  SHIFT_DR,
+  EXIT1_DR,
+  PAUSE_DR,
+  EXIT2_DR,
+  UPDATE_DR,
+  SELECT_IR_SCAN,
+  CAPTURE_IR,
+  SHIFT_IR,
+  EXIT1_IR,
+  PAUSE_IR,
+  EXIT2_IR,
+  UPDATE_IR
+} jtag_state_t;
+
+class jtag_dtm_t
+{
+  static const unsigned idcode = 0xdeadbeef;
+
+  public:
+    jtag_dtm_t(debug_module_t *dm);
+    void reset();
+
+    void set_pins(bool tck, bool tms, bool tdi);
+
+    bool tdo() const { return _tdo; }
+
+    jtag_state_t state() const { return _state; }
+
+  private:
+    debug_module_t *dm;
+    bool _tck, _tms, _tdi, _tdo;
+    uint32_t ir;
+    const unsigned ir_length = 5;
+    uint64_t dr;
+    unsigned dr_length;
+
+    // abits must come before dtmcontrol so it can easily be used in the
+    // constructor.
+    const unsigned abits = 6;
+    uint32_t dtmcontrol;
+    uint64_t dmi;
+
+    jtag_state_t _state;
+
+    void capture_dr();
+    void update_dr();
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/memtracer.h b/tb/riscv-isa-sim/riscv/memtracer.h
new file mode 100644
index 0000000000000000000000000000000000000000..6952e2f870b22db2f6d7e47ecf0ff73751e1a70f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/memtracer.h
@@ -0,0 +1,50 @@
+// See LICENSE for license details.
+
+#ifndef _MEMTRACER_H
+#define _MEMTRACER_H
+
+#include <cstdint>
+#include <string.h>
+#include <vector>
+
+enum access_type {
+  LOAD,
+  STORE,
+  FETCH,
+};
+
+class memtracer_t
+{
+ public:
+  memtracer_t() {}
+  virtual ~memtracer_t() {}
+
+  virtual bool interested_in_range(uint64_t begin, uint64_t end, access_type type) = 0;
+  virtual void trace(uint64_t addr, size_t bytes, access_type type) = 0;
+};
+
+class memtracer_list_t : public memtracer_t
+{
+ public:
+  bool empty() { return list.empty(); }
+  bool interested_in_range(uint64_t begin, uint64_t end, access_type type)
+  {
+    for (std::vector<memtracer_t*>::iterator it = list.begin(); it != list.end(); ++it)
+      if ((*it)->interested_in_range(begin, end, type))
+        return true;
+    return false;
+  }
+  void trace(uint64_t addr, size_t bytes, access_type type)
+  {
+    for (std::vector<memtracer_t*>::iterator it = list.begin(); it != list.end(); ++it)
+      (*it)->trace(addr, bytes, type);
+  }
+  void hook(memtracer_t* h)
+  {
+    list.push_back(h);
+  }
+ private:
+  std::vector<memtracer_t*> list;
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/mmu.cc b/tb/riscv-isa-sim/riscv/mmu.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3e1fc2555258773059d0d9f5db62a3f86b3a87d3
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/mmu.cc
@@ -0,0 +1,325 @@
+// See LICENSE for license details.
+
+#include "mmu.h"
+#include "simif.h"
+#include "processor.h"
+
+mmu_t::mmu_t(simif_t* sim, processor_t* proc)
+ : sim(sim), proc(proc),
+  check_triggers_fetch(false),
+  check_triggers_load(false),
+  check_triggers_store(false),
+  matched_trigger(NULL)
+{
+  flush_tlb();
+  yield_load_reservation();
+}
+
+mmu_t::~mmu_t()
+{
+}
+
+void mmu_t::flush_icache()
+{
+  for (size_t i = 0; i < ICACHE_ENTRIES; i++)
+    icache[i].tag = -1;
+}
+
+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();
+}
+
+static void throw_access_exception(reg_t addr, access_type type)
+{
+  switch (type) {
+    case FETCH: throw trap_instruction_access_fault(addr);
+    case LOAD: throw trap_load_access_fault(addr);
+    case STORE: throw trap_store_access_fault(addr);
+    default: abort();
+  }
+}
+
+reg_t mmu_t::translate(reg_t addr, reg_t len, access_type type)
+{
+  if (!proc)
+    return addr;
+
+  reg_t mode = proc->state.prv;
+  if (type != FETCH) {
+    if (!proc->state.dcsr.cause && get_field(proc->state.mstatus, MSTATUS_MPRV))
+      mode = get_field(proc->state.mstatus, MSTATUS_MPP);
+  }
+
+  reg_t paddr = walk(addr, type, mode) | (addr & (PGSIZE-1));
+  if (!pmp_ok(paddr, type, mode) || !pmp_homogeneous(paddr, len))
+    throw_access_exception(addr, type);
+  return paddr;
+}
+
+tlb_entry_t mmu_t::fetch_slow_path(reg_t vaddr)
+{
+  reg_t paddr = translate(vaddr, sizeof(fetch_temp), FETCH);
+
+  if (auto host_addr = sim->addr_to_mem(paddr)) {
+    return refill_tlb(vaddr, paddr, host_addr, FETCH);
+  } else {
+    if (!sim->mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp))
+      throw trap_instruction_access_fault(vaddr);
+    tlb_entry_t entry = {(char*)&fetch_temp - vaddr, paddr - vaddr};
+    return entry;
+  }
+}
+
+reg_t reg_from_bytes(size_t len, const uint8_t* bytes)
+{
+  switch (len) {
+    case 1:
+      return bytes[0];
+    case 2:
+      return bytes[0] |
+        (((reg_t) bytes[1]) << 8);
+    case 4:
+      return bytes[0] |
+        (((reg_t) bytes[1]) << 8) |
+        (((reg_t) bytes[2]) << 16) |
+        (((reg_t) bytes[3]) << 24);
+    case 8:
+      return bytes[0] |
+        (((reg_t) bytes[1]) << 8) |
+        (((reg_t) bytes[2]) << 16) |
+        (((reg_t) bytes[3]) << 24) |
+        (((reg_t) bytes[4]) << 32) |
+        (((reg_t) bytes[5]) << 40) |
+        (((reg_t) bytes[6]) << 48) |
+        (((reg_t) bytes[7]) << 56);
+  }
+  abort();
+}
+
+void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes)
+{
+  reg_t paddr = translate(addr, len, LOAD);
+
+  if (auto host_addr = sim->addr_to_mem(paddr)) {
+    memcpy(bytes, host_addr, len);
+    if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
+      tracer.trace(paddr, len, LOAD);
+    else
+      refill_tlb(addr, paddr, host_addr, LOAD);
+  } else if (!sim->mmio_load(paddr, len, bytes)) {
+    throw trap_load_access_fault(addr);
+  }
+
+  if (!matched_trigger) {
+    reg_t data = reg_from_bytes(len, bytes);
+    matched_trigger = trigger_exception(OPERATION_LOAD, addr, data);
+    if (matched_trigger)
+      throw *matched_trigger;
+  }
+}
+
+void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes)
+{
+  reg_t paddr = translate(addr, len, STORE);
+
+  if (!matched_trigger) {
+    reg_t data = reg_from_bytes(len, bytes);
+    matched_trigger = trigger_exception(OPERATION_STORE, addr, data);
+    if (matched_trigger)
+      throw *matched_trigger;
+  }
+
+  if (auto host_addr = sim->addr_to_mem(paddr)) {
+    memcpy(host_addr, bytes, len);
+    if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))
+      tracer.trace(paddr, len, STORE);
+    else
+      refill_tlb(addr, paddr, host_addr, STORE);
+  } else if (!sim->mmio_store(paddr, len, bytes)) {
+    throw trap_store_access_fault(addr);
+  }
+}
+
+tlb_entry_t mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type)
+{
+  reg_t idx = (vaddr >> PGSHIFT) % TLB_ENTRIES;
+  reg_t expected_tag = vaddr >> PGSHIFT;
+
+  if ((tlb_load_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag)
+    tlb_load_tag[idx] = -1;
+  if ((tlb_store_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag)
+    tlb_store_tag[idx] = -1;
+  if ((tlb_insn_tag[idx] & ~TLB_CHECK_TRIGGERS) != expected_tag)
+    tlb_insn_tag[idx] = -1;
+
+  if ((check_triggers_fetch && type == FETCH) ||
+      (check_triggers_load && type == LOAD) ||
+      (check_triggers_store && type == STORE))
+    expected_tag |= TLB_CHECK_TRIGGERS;
+
+  if (pmp_homogeneous(paddr & ~reg_t(PGSIZE - 1), PGSIZE)) {
+    if (type == FETCH) tlb_insn_tag[idx] = expected_tag;
+    else if (type == STORE) tlb_store_tag[idx] = expected_tag;
+    else tlb_load_tag[idx] = expected_tag;
+  }
+
+  tlb_entry_t entry = {host_addr - vaddr, paddr - vaddr};
+  tlb_data[idx] = entry;
+  return entry;
+}
+
+reg_t mmu_t::pmp_ok(reg_t addr, access_type type, reg_t mode)
+{
+  if (!proc)
+    return true;
+
+  reg_t base = 0;
+  for (size_t i = 0; i < proc->state.n_pmp; i++) {
+    reg_t tor = proc->state.pmpaddr[i] << PMP_SHIFT;
+    uint8_t cfg = proc->state.pmpcfg[i];
+
+    if (cfg & PMP_A) {
+      bool is_tor = (cfg & PMP_A) == PMP_TOR;
+      bool is_na4 = (cfg & PMP_A) == PMP_NA4;
+
+      reg_t mask = (proc->state.pmpaddr[i] << 1) | (!is_na4);
+      mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
+      bool napot_match = ((addr ^ tor) & mask) == 0;
+      bool tor_match = base <= addr && addr < tor;
+
+      if (is_tor ? tor_match : napot_match) {
+        return
+          (mode == PRV_M && !(cfg & PMP_L)) ||
+          (type == LOAD && (cfg & PMP_R)) ||
+          (type == STORE && (cfg & PMP_W)) ||
+          (type == FETCH && (cfg & PMP_X));
+      }
+    }
+
+    base = tor;
+  }
+
+  return mode == PRV_M;
+}
+
+reg_t mmu_t::pmp_homogeneous(reg_t addr, reg_t len)
+{
+  if ((addr | len) & (len - 1))
+    abort();
+
+  if (!proc)
+    return true;
+
+  reg_t base = 0;
+  for (size_t i = 0; i < proc->state.n_pmp; i++) {
+    reg_t tor = proc->state.pmpaddr[i] << PMP_SHIFT;
+    uint8_t cfg = proc->state.pmpcfg[i];
+
+    if (cfg & PMP_A) {
+      bool is_tor = (cfg & PMP_A) == PMP_TOR;
+      bool is_na4 = (cfg & PMP_A) == PMP_NA4;
+
+      bool begins_after_lower = addr >= base;
+      bool begins_after_upper = addr >= tor;
+      bool ends_before_lower = (addr & -len) < (base & -len);
+      bool ends_before_upper = (addr & -len) < (tor & -len);
+      bool tor_homogeneous = ends_before_lower || begins_after_upper ||
+        (begins_after_lower && ends_before_upper);
+
+      reg_t mask = (proc->state.pmpaddr[i] << 1) | (!is_na4);
+      mask = ~(mask & ~(mask + 1)) << PMP_SHIFT;
+      bool mask_homogeneous = ~(mask << 1) & len;
+      bool napot_homogeneous = mask_homogeneous || ((addr ^ tor) / len) != 0;
+
+      if (!(is_tor ? tor_homogeneous : napot_homogeneous))
+        return false;
+    }
+
+    base = tor;
+  }
+
+  return true;
+}
+
+reg_t mmu_t::walk(reg_t addr, access_type type, reg_t mode)
+{
+  vm_info vm = decode_vm_info(proc->max_xlen, mode, proc->get_state()->satp);
+  if (vm.levels == 0)
+    return addr & ((reg_t(2) << (proc->xlen-1))-1); // zero-extend from xlen
+
+  bool s_mode = mode == PRV_S;
+  bool sum = get_field(proc->state.mstatus, MSTATUS_SUM);
+  bool mxr = get_field(proc->state.mstatus, MSTATUS_MXR);
+
+  // verify bits xlen-1:va_bits-1 are all equal
+  int va_bits = PGSHIFT + vm.levels * vm.idxbits;
+  reg_t mask = (reg_t(1) << (proc->xlen - (va_bits-1))) - 1;
+  reg_t masked_msbs = (addr >> (va_bits-1)) & mask;
+  if (masked_msbs != 0 && masked_msbs != mask)
+    vm.levels = 0;
+
+  reg_t base = vm.ptbase;
+  for (int i = vm.levels - 1; i >= 0; i--) {
+    int ptshift = i * vm.idxbits;
+    reg_t idx = (addr >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1);
+
+    // check that physical address of PTE is legal
+    auto pte_paddr = base + idx * vm.ptesize;
+    auto ppte = sim->addr_to_mem(pte_paddr);
+    if (!ppte || !pmp_ok(pte_paddr, LOAD, PRV_S))
+      throw_access_exception(addr, type);
+
+    reg_t pte = vm.ptesize == 4 ? *(uint32_t*)ppte : *(uint64_t*)ppte;
+    reg_t ppn = pte >> PTE_PPN_SHIFT;
+
+    if (PTE_TABLE(pte)) { // next level of page table
+      base = ppn << PGSHIFT;
+    } else if ((pte & PTE_U) ? s_mode && (type == FETCH || !sum) : !s_mode) {
+      break;
+    } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) {
+      break;
+    } else if (type == FETCH ? !(pte & PTE_X) :
+               type == LOAD ?  !(pte & PTE_R) && !(mxr && (pte & PTE_X)) :
+                               !((pte & PTE_R) && (pte & PTE_W))) {
+      break;
+    } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) {
+      break;
+    } else {
+      reg_t ad = PTE_A | ((type == STORE) * PTE_D);
+#ifdef RISCV_ENABLE_DIRTY
+      // set accessed and possibly dirty bits.
+      if ((pte & ad) != ad) {
+        if (!pmp_ok(pte_paddr, STORE, PRV_S))
+          throw_access_exception(addr, type);
+        *(uint32_t*)ppte |= ad;
+      }
+#else
+      // take exception if access or possibly dirty bit is not set.
+      if ((pte & ad) != ad)
+        break;
+#endif
+      // for superpage mappings, make a fake leaf PTE for the TLB's benefit.
+      reg_t vpn = addr >> PGSHIFT;
+      reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT;
+      return value;
+    }
+  }
+
+  switch (type) {
+    case FETCH: throw trap_instruction_page_fault(addr);
+    case LOAD: throw trap_load_page_fault(addr);
+    case STORE: throw trap_store_page_fault(addr);
+    default: abort();
+  }
+}
+
+void mmu_t::register_memtracer(memtracer_t* t)
+{
+  flush_tlb();
+  tracer.hook(t);
+}
diff --git a/tb/riscv-isa-sim/riscv/mmu.h b/tb/riscv-isa-sim/riscv/mmu.h
new file mode 100644
index 0000000000000000000000000000000000000000..761736743658561d7413a46f5375b6c58aba8daa
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/mmu.h
@@ -0,0 +1,399 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_MMU_H
+#define _RISCV_MMU_H
+
+#include "decode.h"
+#include "trap.h"
+#include "common.h"
+#include "config.h"
+#include "simif.h"
+#include "processor.h"
+#include "memtracer.h"
+#include <stdlib.h>
+#include <vector>
+
+// virtual memory configuration
+#define PGSHIFT 12
+const reg_t PGSIZE = 1 << PGSHIFT;
+const reg_t PGMASK = ~(PGSIZE-1);
+
+struct insn_fetch_t
+{
+  insn_func_t func;
+  insn_t insn;
+};
+
+struct icache_entry_t {
+  reg_t tag;
+  struct icache_entry_t* next;
+  insn_fetch_t data;
+};
+
+struct tlb_entry_t {
+  char* host_offset;
+  reg_t target_offset;
+};
+
+class trigger_matched_t
+{
+  public:
+    trigger_matched_t(int index,
+        trigger_operation_t operation, reg_t address, reg_t data) :
+      index(index), operation(operation), address(address), data(data) {}
+
+    int index;
+    trigger_operation_t operation;
+    reg_t address;
+    reg_t data;
+};
+
+// 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(simif_t* sim, processor_t* proc);
+  ~mmu_t();
+
+  inline reg_t misaligned_load(reg_t addr, size_t size)
+  {
+#ifdef RISCV_ENABLE_MISALIGNED
+    reg_t res = 0;
+    for (size_t i = 0; i < size; i++)
+      res += (reg_t)load_uint8(addr + i) << (i * 8);
+    return res;
+#else
+    throw trap_load_address_misaligned(addr);
+#endif
+  }
+
+  inline void misaligned_store(reg_t addr, reg_t data, size_t size)
+  {
+#ifdef RISCV_ENABLE_MISALIGNED
+    for (size_t i = 0; i < size; i++)
+      store_uint8(addr + i, data >> (i * 8));
+#else
+    throw trap_store_address_misaligned(addr);
+#endif
+  }
+
+  // template for functions that load an aligned value from memory
+  #define load_func(type) \
+    inline type##_t load_##type(reg_t addr) { \
+      if (unlikely(addr & (sizeof(type##_t)-1))) \
+        return misaligned_load(addr, sizeof(type##_t)); \
+      reg_t vpn = addr >> PGSHIFT; \
+      if (likely(tlb_load_tag[vpn % TLB_ENTRIES] == vpn)) \
+        return *(type##_t*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr); \
+      if (unlikely(tlb_load_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \
+        type##_t data = *(type##_t*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr); \
+        if (!matched_trigger) { \
+          matched_trigger = trigger_exception(OPERATION_LOAD, addr, data); \
+          if (matched_trigger) \
+            throw *matched_trigger; \
+        } \
+        return data; \
+      } \
+      type##_t res; \
+      load_slow_path(addr, sizeof(type##_t), (uint8_t*)&res); \
+      return res; \
+    }
+
+  // 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)-1))) \
+        return misaligned_store(addr, val, sizeof(type##_t)); \
+      reg_t vpn = addr >> PGSHIFT; \
+      if (likely(tlb_store_tag[vpn % TLB_ENTRIES] == vpn)) \
+        *(type##_t*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = val; \
+      else if (unlikely(tlb_store_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) { \
+        if (!matched_trigger) { \
+          matched_trigger = trigger_exception(OPERATION_STORE, addr, val); \
+          if (matched_trigger) \
+            throw *matched_trigger; \
+        } \
+        *(type##_t*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = val; \
+      } \
+      else \
+        store_slow_path(addr, sizeof(type##_t), (const uint8_t*)&val); \
+    }
+
+  // template for functions that perform an atomic memory operation
+  #define amo_func(type) \
+    template<typename op> \
+    type##_t amo_##type(reg_t addr, op f) { \
+      if (addr & (sizeof(type##_t)-1)) \
+        throw trap_store_address_misaligned(addr); \
+      try { \
+        auto lhs = load_##type(addr); \
+        store_##type(addr, f(lhs)); \
+        return lhs; \
+      } catch (trap_load_page_fault& t) { \
+        /* AMO faults should be reported as store faults */ \
+        throw trap_store_page_fault(t.get_tval()); \
+      } catch (trap_load_access_fault& t) { \
+        /* AMO faults should be reported as store faults */ \
+        throw trap_store_access_fault(t.get_tval()); \
+      } \
+    }
+
+  void store_float128(reg_t addr, float128_t val)
+  {
+#ifndef RISCV_ENABLE_MISALIGNED
+    if (unlikely(addr & (sizeof(float128_t)-1)))
+      throw trap_store_address_misaligned(addr);
+#endif
+    store_uint64(addr, val.v[0]);
+    store_uint64(addr + 8, val.v[1]);
+  }
+
+  float128_t load_float128(reg_t addr)
+  {
+#ifndef RISCV_ENABLE_MISALIGNED
+    if (unlikely(addr & (sizeof(float128_t)-1)))
+      throw trap_load_address_misaligned(addr);
+#endif
+    return (float128_t){load_uint64(addr), load_uint64(addr + 8)};
+  }
+
+  // store value to memory at aligned address
+  store_func(uint8)
+  store_func(uint16)
+  store_func(uint32)
+  store_func(uint64)
+
+  // perform an atomic memory operation at an aligned address
+  amo_func(uint32)
+  amo_func(uint64)
+
+  inline void yield_load_reservation()
+  {
+    load_reservation_address = (reg_t)-1;
+  }
+
+  inline void acquire_load_reservation(reg_t vaddr)
+  {
+    reg_t paddr = translate(vaddr, 1, LOAD);
+    if (auto host_addr = sim->addr_to_mem(paddr))
+      load_reservation_address = refill_tlb(vaddr, paddr, host_addr, LOAD).target_offset + vaddr;
+    else
+      throw trap_load_access_fault(vaddr); // disallow LR to I/O space
+  }
+
+  inline bool check_load_reservation(reg_t vaddr)
+  {
+    reg_t paddr = translate(vaddr, 1, STORE);
+    if (auto host_addr = sim->addr_to_mem(paddr))
+      return load_reservation_address == refill_tlb(vaddr, paddr, host_addr, STORE).target_offset + vaddr;
+    else
+      throw trap_store_access_fault(vaddr); // disallow SC to I/O space
+  }
+
+  static const reg_t ICACHE_ENTRIES = 1024;
+
+  inline size_t icache_index(reg_t addr)
+  {
+    return (addr / PC_ALIGN) % ICACHE_ENTRIES;
+  }
+
+  inline icache_entry_t* refill_icache(reg_t addr, icache_entry_t* entry)
+  {
+    auto tlb_entry = translate_insn_addr(addr);
+    insn_bits_t insn = *(uint16_t*)(tlb_entry.host_offset + addr);
+    int length = insn_length(insn);
+
+    if (likely(length == 4)) {
+      insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr_to_host(addr + 2) << 16;
+    } else if (length == 2) {
+      insn = (int16_t)insn;
+    } else if (length == 6) {
+      insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr_to_host(addr + 4) << 32;
+      insn |= (insn_bits_t)*(const uint16_t*)translate_insn_addr_to_host(addr + 2) << 16;
+    } else {
+      static_assert(sizeof(insn_bits_t) == 8, "insn_bits_t must be uint64_t");
+      insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr_to_host(addr + 6) << 48;
+      insn |= (insn_bits_t)*(const uint16_t*)translate_insn_addr_to_host(addr + 4) << 32;
+      insn |= (insn_bits_t)*(const uint16_t*)translate_insn_addr_to_host(addr + 2) << 16;
+    }
+
+    insn_fetch_t fetch = {proc->decode_insn(insn), insn};
+    entry->tag = addr;
+    entry->next = &icache[icache_index(addr + length)];
+    entry->data = fetch;
+
+    reg_t paddr = tlb_entry.target_offset + addr;;
+    if (tracer.interested_in_range(paddr, paddr + 1, FETCH)) {
+      entry->tag = -1;
+      tracer.trace(paddr, length, FETCH);
+    }
+    return entry;
+  }
+
+  inline icache_entry_t* access_icache(reg_t addr)
+  {
+    icache_entry_t* entry = &icache[icache_index(addr)];
+    if (likely(entry->tag == addr))
+      return entry;
+    return refill_icache(addr, entry);
+  }
+
+  inline insn_fetch_t load_insn(reg_t addr)
+  {
+    icache_entry_t entry;
+    return refill_icache(addr, &entry)->data;
+  }
+
+  void flush_tlb();
+  void flush_icache();
+
+  void register_memtracer(memtracer_t*);
+
+  int is_dirty_enabled()
+  {
+#ifdef RISCV_ENABLE_DIRTY
+    return 1;
+#else
+    return 0;
+#endif
+  }
+
+  int is_misaligned_enabled()
+  {
+#ifdef RISCV_ENABLE_MISALIGNED
+    return 1;
+#else
+    return 0;
+#endif
+  }
+
+private:
+  simif_t* sim;
+  processor_t* proc;
+  memtracer_list_t tracer;
+  reg_t load_reservation_address;
+  uint16_t fetch_temp;
+
+  // implement an instruction cache for simulator performance
+  icache_entry_t icache[ICACHE_ENTRIES];
+
+  // implement a TLB for simulator performance
+  static const reg_t TLB_ENTRIES = 256;
+  // If a TLB tag has TLB_CHECK_TRIGGERS set, then the MMU must check for a
+  // trigger match before completing an access.
+  static const reg_t TLB_CHECK_TRIGGERS = reg_t(1) << 63;
+  tlb_entry_t 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];
+
+  // finish translation on a TLB miss and update the TLB
+  tlb_entry_t refill_tlb(reg_t vaddr, reg_t paddr, char* host_addr, access_type type);
+  const char* fill_from_mmio(reg_t vaddr, reg_t paddr);
+
+  // perform a page table walk for a given VA; set referenced/dirty bits
+  reg_t walk(reg_t addr, access_type type, reg_t prv);
+
+  // handle uncommon cases: TLB misses, page faults, MMIO
+  tlb_entry_t fetch_slow_path(reg_t addr);
+  void load_slow_path(reg_t addr, reg_t len, uint8_t* bytes);
+  void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes);
+  reg_t translate(reg_t addr, reg_t len, access_type type);
+
+  // ITLB lookup
+  inline tlb_entry_t translate_insn_addr(reg_t addr) {
+    reg_t vpn = addr >> PGSHIFT;
+    if (likely(tlb_insn_tag[vpn % TLB_ENTRIES] == vpn))
+      return tlb_data[vpn % TLB_ENTRIES];
+    tlb_entry_t result;
+    if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] != (vpn | TLB_CHECK_TRIGGERS))) {
+      result = fetch_slow_path(addr);
+    } else {
+      result = tlb_data[vpn % TLB_ENTRIES];
+    }
+    if (unlikely(tlb_insn_tag[vpn % TLB_ENTRIES] == (vpn | TLB_CHECK_TRIGGERS))) {
+      uint16_t* ptr = (uint16_t*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr);
+      int match = proc->trigger_match(OPERATION_EXECUTE, addr, *ptr);
+      if (match >= 0) {
+        throw trigger_matched_t(match, OPERATION_EXECUTE, addr, *ptr);
+      }
+    }
+    return result;
+  }
+
+  inline const uint16_t* translate_insn_addr_to_host(reg_t addr) {
+    return (uint16_t*)(translate_insn_addr(addr).host_offset + addr);
+  }
+
+  inline trigger_matched_t *trigger_exception(trigger_operation_t operation,
+      reg_t address, reg_t data)
+  {
+    if (!proc) {
+      return NULL;
+    }
+    int match = proc->trigger_match(operation, address, data);
+    if (match == -1)
+      return NULL;
+    if (proc->state.mcontrol[match].timing == 0) {
+      throw trigger_matched_t(match, operation, address, data);
+    }
+    return new trigger_matched_t(match, operation, address, data);
+  }
+
+  reg_t pmp_homogeneous(reg_t addr, reg_t len);
+  reg_t pmp_ok(reg_t addr, access_type type, reg_t mode);
+
+  bool check_triggers_fetch;
+  bool check_triggers_load;
+  bool check_triggers_store;
+  // The exception describing a matched trigger, or NULL.
+  trigger_matched_t *matched_trigger;
+
+  friend class processor_t;
+};
+
+struct vm_info {
+  int levels;
+  int idxbits;
+  int ptesize;
+  reg_t ptbase;
+};
+
+inline vm_info decode_vm_info(int xlen, reg_t prv, reg_t satp)
+{
+  if (prv == PRV_M) {
+    return {0, 0, 0, 0};
+  } else if (prv <= PRV_S && xlen == 32) {
+    switch (get_field(satp, SATP32_MODE)) {
+      case SATP_MODE_OFF: return {0, 0, 0, 0};
+      case SATP_MODE_SV32: return {2, 10, 4, (satp & SATP32_PPN) << PGSHIFT};
+      default: abort();
+    }
+  } else if (prv <= PRV_S && xlen == 64) {
+    switch (get_field(satp, SATP64_MODE)) {
+      case SATP_MODE_OFF: return {0, 0, 0, 0};
+      case SATP_MODE_SV39: return {3, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+      case SATP_MODE_SV48: return {4, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+      case SATP_MODE_SV57: return {5, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+      case SATP_MODE_SV64: return {6, 9, 8, (satp & SATP64_PPN) << PGSHIFT};
+      default: abort();
+    }
+  } else {
+    abort();
+  }
+}
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/mulhi.h b/tb/riscv-isa-sim/riscv/mulhi.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb4a484a6dee9210ce4d6ff28098e2c065f7adc6
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/mulhi.h
@@ -0,0 +1,43 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_MULHI_H
+#define _RISCV_MULHI_H
+
+#include <cstdint>
+
+inline uint64_t mulhu(uint64_t a, uint64_t b)
+{
+  uint64_t t;
+  uint32_t y1, y2, y3;
+  uint64_t a0 = (uint32_t)a, a1 = a >> 32;
+  uint64_t b0 = (uint32_t)b, b1 = b >> 32;
+
+  t = a1*b0 + ((a0*b0) >> 32);
+  y1 = t;
+  y2 = t >> 32;
+
+  t = a0*b1 + y1;
+  y1 = t;
+
+  t = a1*b1 + y2 + (t >> 32);
+  y2 = t;
+  y3 = t >> 32;
+
+  return ((uint64_t)y3 << 32) | y2;
+}
+
+inline int64_t mulh(int64_t a, int64_t b)
+{
+  int negate = (a < 0) != (b < 0);
+  uint64_t res = mulhu(a < 0 ? -a : a, b < 0 ? -b : b);
+  return negate ? ~res + (a * b == 0) : res;
+}
+
+inline int64_t mulhsu(int64_t a, uint64_t b)
+{
+  int negate = a < 0;
+  uint64_t res = mulhu(a < 0 ? -a : a, b);
+  return negate ? ~res + (a * b == 0) : res;
+}
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/opcodes.h b/tb/riscv-isa-sim/riscv/opcodes.h
new file mode 100644
index 0000000000000000000000000000000000000000..34c089ebb769a1c74d672034941fc0888b8e6243
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/opcodes.h
@@ -0,0 +1,244 @@
+#include "encoding.h"
+
+#define ZERO	0
+#define T0      5
+#define S0      8
+#define S1      9
+
+static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
+  return (value >> lo) & ((1 << (hi+1-lo)) - 1);
+}
+
+static uint32_t bit(uint32_t value, unsigned int b) {
+  return (value >> b) & 1;
+}
+
+static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused));
+static uint32_t jal(unsigned int rd, uint32_t imm) {
+  return (bit(imm, 20) << 31) |
+    (bits(imm, 10, 1) << 21) |
+    (bit(imm, 11) << 20) |
+    (bits(imm, 19, 12) << 12) |
+    (rd << 7) |
+    MATCH_JAL;
+}
+
+static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
+static uint32_t csrsi(unsigned int csr, uint16_t imm) {
+  return (csr << 20) |
+    (bits(imm, 4, 0) << 15) |
+    MATCH_CSRRSI;
+}
+
+static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (src << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_SW;
+}
+
+static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (src << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_SD;
+}
+
+static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (src << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_SH;
+}
+
+static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (src << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_SB;
+}
+
+static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 0) << 20) |
+    (base << 15) |
+    (bits(rd, 4, 0) << 7) |
+    MATCH_LD;
+}
+
+static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 0) << 20) |
+    (base << 15) |
+    (bits(rd, 4, 0) << 7) |
+    MATCH_LW;
+}
+
+static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 0) << 20) |
+    (base << 15) |
+    (bits(rd, 4, 0) << 7) |
+    MATCH_LH;
+}
+
+static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 0) << 20) |
+    (base << 15) |
+    (bits(rd, 4, 0) << 7) |
+    MATCH_LB;
+}
+
+static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused));
+static uint32_t csrw(unsigned int source, unsigned int csr) {
+  return (csr << 20) | (source << 15) | MATCH_CSRRW;
+}
+
+static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
+static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
+{
+  return (bits(imm, 11, 0) << 20) |
+    (src << 15) |
+    (dest << 7) |
+    MATCH_ADDI;
+}
+
+static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused));
+static uint32_t csrr(unsigned int rd, unsigned int csr) {
+  return (csr << 20) | (rd << 7) | MATCH_CSRRS;
+}
+
+static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (bits(src, 4, 0) << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_FSW;
+}
+
+static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (bits(src, 4, 0) << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_FSD;
+}
+
+static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 0) << 20) |
+    (base << 15) |
+    (bits(dest, 4, 0) << 7) |
+    MATCH_FLW;
+}
+
+static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 0) << 20) |
+    (base << 15) |
+    (bits(dest, 4, 0) << 7) |
+    MATCH_FLD;
+}
+
+static uint32_t ebreak(void) __attribute__ ((unused));
+static uint32_t ebreak(void) { return MATCH_EBREAK; }
+static uint32_t ebreak_c(void) __attribute__ ((unused));
+static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; }
+
+static uint32_t dret(void) __attribute__ ((unused));
+static uint32_t dret(void) { return MATCH_DRET; }
+
+static uint32_t fence_i(void) __attribute__ ((unused));
+static uint32_t fence_i(void)
+{
+  return MATCH_FENCE_I;
+}
+
+/*
+static uint32_t lui(unsigned int dest, uint32_t imm) __attribute__ ((unused));
+static uint32_t lui(unsigned int dest, uint32_t imm)
+{
+  return (bits(imm, 19, 0) << 12) |
+    (dest << 7) |
+    MATCH_LUI;
+}
+
+static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused));
+static uint32_t csrci(unsigned int csr, uint16_t imm) {
+  return (csr << 20) |
+    (bits(imm, 4, 0) << 15) |
+    MATCH_CSRRCI;
+}
+
+static uint32_t li(unsigned int dest, uint16_t imm) __attribute__ ((unused));
+static uint32_t li(unsigned int dest, uint16_t imm)
+{
+	return addi(dest, 0, imm);
+}
+
+static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
+static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (bits(src, 4, 0) << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_FSD;
+}
+
+static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
+static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm)
+{
+  return (bits(imm, 11, 0) << 20) |
+    (src << 15) |
+    (dest << 7) |
+    MATCH_ORI;
+}
+
+static uint32_t nop(void) __attribute__ ((unused));
+static uint32_t nop(void)
+{
+  return addi(0, 0, 0);
+}
+*/
+
+static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
+static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm)
+{
+  return (bits(imm, 11, 0) << 20) |
+    (src << 15) |
+    (dest << 7) |
+    MATCH_XORI;
+}
+
+static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) __attribute__ ((unused));
+static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt)
+{
+	return (bits(shamt, 4, 0) << 20) |
+		(src << 15) |
+		(dest << 7) |
+		MATCH_SRLI;
+}
diff --git a/tb/riscv-isa-sim/riscv/processor.cc b/tb/riscv-isa-sim/riscv/processor.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4a449fe377008c73182fe0433b121b991c05cc77
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/processor.cc
@@ -0,0 +1,862 @@
+// See LICENSE for license details.
+
+#include "processor.h"
+#include "extension.h"
+#include "common.h"
+#include "config.h"
+#include "simif.h"
+#include "mmu.h"
+#include "disasm.h"
+#include <cinttypes>
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <assert.h>
+#include <limits.h>
+#include <stdexcept>
+#include <algorithm>
+
+#undef STATE
+#define STATE state
+
+processor_t::processor_t(const char* isa, simif_t* sim, uint32_t id,
+        bool halt_on_reset)
+  : debug(false), halt_request(false), sim(sim), ext(NULL), id(id),
+  halt_on_reset(halt_on_reset), last_pc(1), executions(1)
+{
+  parse_isa_string(isa);
+  register_base_instructions();
+
+  mmu = new mmu_t(sim, this);
+
+  disassembler = new disassembler_t(max_xlen);
+  if (ext)
+    for (auto disasm_insn : ext->get_disasms())
+      disassembler->add_insn(disasm_insn);
+
+  reset();
+}
+
+processor_t::~processor_t()
+{
+#ifdef RISCV_ENABLE_HISTOGRAM
+  if (histogram_enabled)
+  {
+    fprintf(stderr, "PC Histogram size:%zu\n", pc_histogram.size());
+    for (auto it : pc_histogram)
+      fprintf(stderr, "%0" PRIx64 " %" PRIu64 "\n", it.first, it.second);
+  }
+#endif
+
+  delete mmu;
+  delete disassembler;
+}
+
+static void bad_isa_string(const char* isa)
+{
+  fprintf(stderr, "error: bad --isa option %s\n", isa);
+  abort();
+}
+
+void processor_t::parse_isa_string(const char* str)
+{
+  std::string lowercase, tmp;
+  for (const char *r = str; *r; r++)
+    lowercase += std::tolower(*r);
+
+  const char* p = lowercase.c_str();
+  const char* all_subsets = "imafdqc";
+
+  max_xlen = 64;
+  state.misa = reg_t(2) << 62;
+
+  if (strncmp(p, "rv32", 4) == 0)
+    max_xlen = 32, state.misa = reg_t(1) << 30, p += 4;
+  else if (strncmp(p, "rv64", 4) == 0)
+    p += 4;
+  else if (strncmp(p, "rv", 2) == 0)
+    p += 2;
+
+  if (!*p) {
+    p = "imafdc";
+  } else if (*p == 'g') { // treat "G" as "IMAFD"
+    tmp = std::string("imafd") + (p+1);
+    p = &tmp[0];
+  } else if (*p != 'i') {
+    bad_isa_string(str);
+  }
+
+  isa_string = "rv" + std::to_string(max_xlen) + p;
+  state.misa |= 1L << ('s' - 'a'); // advertise support for supervisor mode
+  state.misa |= 1L << ('u' - 'a'); // advertise support for user mode
+
+  while (*p) {
+    state.misa |= 1L << (*p - 'a');
+
+    if (auto next = strchr(all_subsets, *p)) {
+      all_subsets = next + 1;
+      p++;
+    } else if (*p == 'x') {
+      const char* ext = p+1, *end = ext;
+      while (islower(*end))
+        end++;
+      register_extension(find_extension(std::string(ext, end - ext).c_str())());
+      p = end;
+    } else {
+      bad_isa_string(str);
+    }
+  }
+
+  if (supports_extension('D') && !supports_extension('F'))
+    bad_isa_string(str);
+
+  if (supports_extension('Q') && !supports_extension('D'))
+    bad_isa_string(str);
+
+  if (supports_extension('Q') && max_xlen < 64)
+    bad_isa_string(str);
+
+  max_isa = state.misa;
+}
+
+void state_t::reset(reg_t max_isa)
+{
+  memset(this, 0, sizeof(*this));
+  misa = max_isa;
+  prv = PRV_M;
+  mstatus = 0;
+  pc = DEFAULT_RSTVEC;
+  tselect = 0;
+  for (unsigned int i = 0; i < num_triggers; i++)
+    mcontrol[i].type = 2;
+
+  pmpcfg[0] = PMP_R | PMP_W | PMP_X | PMP_NAPOT;
+  pmpaddr[0] = ~reg_t(0);
+}
+
+void processor_t::set_debug(bool value)
+{
+  debug = value;
+  if (ext)
+    ext->set_debug(value);
+}
+
+void processor_t::set_histogram(bool value)
+{
+  histogram_enabled = value;
+#ifndef RISCV_ENABLE_HISTOGRAM
+  if (value) {
+    fprintf(stderr, "PC Histogram support has not been properly enabled;");
+    fprintf(stderr, " please re-build the riscv-isa-run project using \"configure --enable-histogram\".\n");
+  }
+#endif
+}
+
+void processor_t::reset()
+{
+  state.reset(max_isa);
+  state.dcsr.halt = halt_on_reset;
+  halt_on_reset = false;
+  set_csr(CSR_MSTATUS, state.mstatus);
+
+  if (ext)
+    ext->reset(); // reset the extension
+
+  if (sim)
+    sim->proc_reset(id);
+}
+
+// Count number of contiguous 0 bits starting from the LSB.
+static int ctz(reg_t val)
+{
+  int res = 0;
+  if (val)
+    while ((val & 1) == 0)
+      val >>= 1, res++;
+  return res;
+}
+
+void processor_t::take_interrupt(reg_t pending_interrupts)
+{
+  reg_t mie = get_field(state.mstatus, MSTATUS_MIE);
+  reg_t m_enabled = state.prv < PRV_M || (state.prv == PRV_M && mie);
+  reg_t enabled_interrupts = pending_interrupts & ~state.mideleg & -m_enabled;
+
+  reg_t sie = get_field(state.mstatus, MSTATUS_SIE);
+  reg_t s_enabled = state.prv < PRV_S || (state.prv == PRV_S && sie);
+  // M-ints have highest priority; consider S-ints only if no M-ints pending
+  if (enabled_interrupts == 0)
+    enabled_interrupts = pending_interrupts & state.mideleg & -s_enabled;
+
+  if (state.dcsr.cause == 0 && enabled_interrupts) {
+    // nonstandard interrupts have highest priority
+    if (enabled_interrupts >> IRQ_M_EXT)
+      enabled_interrupts = enabled_interrupts >> IRQ_M_EXT << IRQ_M_EXT;
+    // external interrupts have next-highest priority
+    else if (enabled_interrupts & (MIP_MEIP | MIP_SEIP))
+      enabled_interrupts = enabled_interrupts & (MIP_MEIP | MIP_SEIP);
+    // software interrupts have next-highest priority
+    else if (enabled_interrupts & (MIP_MSIP | MIP_SSIP))
+      enabled_interrupts = enabled_interrupts & (MIP_MSIP | MIP_SSIP);
+    // timer interrupts have next-highest priority
+    else if (enabled_interrupts & (MIP_MTIP | MIP_STIP))
+      enabled_interrupts = enabled_interrupts & (MIP_MTIP | MIP_STIP);
+    else
+      abort();
+
+    throw trap_t(((reg_t)1 << (max_xlen-1)) | ctz(enabled_interrupts));
+  }
+}
+
+static int xlen_to_uxl(int xlen)
+{
+  if (xlen == 32)
+    return 1;
+  if (xlen == 64)
+    return 2;
+  abort();
+}
+
+reg_t processor_t::legalize_privilege(reg_t prv)
+{
+  assert(prv <= PRV_M);
+
+  if (!supports_extension('U'))
+    return PRV_M;
+
+  if (prv == PRV_H || !supports_extension('S'))
+    return PRV_U;
+
+  return prv;
+}
+
+void processor_t::set_privilege(reg_t prv)
+{
+  // mmu->flush_tlb();
+  state.prv = legalize_privilege(prv);
+}
+
+void processor_t::enter_debug_mode(uint8_t cause)
+{
+  state.dcsr.cause = cause;
+  state.dcsr.prv = state.prv;
+  set_privilege(PRV_M);
+  state.dpc = state.pc;
+  state.pc = DEBUG_ROM_ENTRY;
+}
+
+void processor_t::take_trap(trap_t& t, reg_t epc)
+{
+  if (debug) {
+    fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
+            id, t.name(), epc);
+    if (t.has_tval())
+      fprintf(stderr, "core %3d:           tval 0x%016" PRIx64 "\n", id,
+          t.get_tval());
+  }
+
+  if (state.dcsr.cause) {
+    if (t.cause() == CAUSE_BREAKPOINT) {
+      state.pc = DEBUG_ROM_ENTRY;
+    } else {
+      state.pc = DEBUG_ROM_TVEC;
+    }
+    return;
+  }
+
+  if (t.cause() == CAUSE_BREAKPOINT && (
+              (state.prv == PRV_M && state.dcsr.ebreakm) ||
+              (state.prv == PRV_S && state.dcsr.ebreaks) ||
+              (state.prv == PRV_U && state.dcsr.ebreaku))) {
+    enter_debug_mode(DCSR_CAUSE_SWBP);
+    return;
+  }
+
+  // by default, trap to M-mode, unless delegated to S-mode
+  reg_t bit = t.cause();
+  reg_t deleg = state.medeleg;
+  bool interrupt = (bit & ((reg_t)1 << (max_xlen-1))) != 0;
+  if (interrupt)
+    deleg = state.mideleg, bit &= ~((reg_t)1 << (max_xlen-1));
+  if (state.prv <= PRV_S && bit < max_xlen && ((deleg >> bit) & 1)) {
+    // handle the trap in S-mode
+    state.pc = state.stvec;
+    state.scause = t.cause();
+    state.sepc = epc;
+    state.stval = t.get_tval();
+
+    reg_t s = state.mstatus;
+    s = set_field(s, MSTATUS_SPIE, get_field(s, MSTATUS_SIE));
+    s = set_field(s, MSTATUS_SPP, state.prv);
+    s = set_field(s, MSTATUS_SIE, 0);
+    set_csr(CSR_MSTATUS, s);
+    set_privilege(PRV_S);
+  } else {
+    reg_t vector = (state.mtvec & 1) && interrupt ? 4*bit : 0;
+    state.pc = (state.mtvec & ~(reg_t)1) + vector;
+    state.mepc = epc;
+    state.mcause = t.cause();
+    state.mtval = t.get_tval();
+
+    reg_t s = state.mstatus;
+    s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
+    s = set_field(s, MSTATUS_MPP, state.prv);
+    s = set_field(s, MSTATUS_MIE, 0);
+    set_csr(CSR_MSTATUS, s);
+    set_privilege(PRV_M);
+  }
+}
+
+void processor_t::disasm(insn_t insn)
+{
+  uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
+  if (last_pc != state.pc || last_bits != bits) {
+    if (executions != 1) {
+      fprintf(stderr, "core %3d: Executed %" PRIx64 " times\n", id, executions);
+    }
+
+    fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
+            id, state.pc, bits, disassembler->disassemble(insn).c_str());
+    last_pc = state.pc;
+    last_bits = bits;
+    executions = 1;
+  } else {
+    executions++;
+  }
+}
+
+int processor_t::paddr_bits()
+{
+  assert(xlen == max_xlen);
+  return max_xlen == 64 ? 50 : 34;
+}
+
+void processor_t::set_csr(int which, reg_t val)
+{
+  val = zext_xlen(val);
+  reg_t delegable_ints = MIP_SSIP | MIP_STIP | MIP_SEIP
+                       | ((ext != NULL) << IRQ_COP);
+  reg_t all_ints = delegable_ints | MIP_MSIP | MIP_MTIP;
+
+  // if (which >= CSR_PMPADDR0 && which < CSR_PMPADDR0 + state.n_pmp) {
+  //   size_t i = which - CSR_PMPADDR0;
+  //   bool locked = state.pmpcfg[i] & PMP_L;
+  //   bool next_locked = i+1 < state.n_pmp && (state.pmpcfg[i+1] & PMP_L);
+  //   bool next_tor = i+1 < state.n_pmp && (state.pmpcfg[i+1] & PMP_A) == PMP_TOR;
+  //   if (!locked && !(next_locked && next_tor))
+  //     state.pmpaddr[i] = val;
+
+  //   // mmu->flush_tlb();
+  // }
+
+  // if (which >= CSR_PMPCFG0 && which < CSR_PMPCFG0 + state.n_pmp / 4) {
+  //   for (size_t i0 = (which - CSR_PMPCFG0) * 4, i = i0; i < i0 + xlen / 8; i++) {
+  //     if (!(state.pmpcfg[i] & PMP_L))
+  //       state.pmpcfg[i] = (val >> (8 * (i - i0))) & (PMP_R | PMP_W | PMP_X | PMP_A | PMP_L);
+  //   }
+  //   // mmu->flush_tlb();
+  // }
+
+  switch (which)
+  {
+    case CSR_FFLAGS:
+      dirty_fp_state;
+      state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT);
+      break;
+    case CSR_FRM:
+      dirty_fp_state;
+      state.frm = val & (FSR_RD >> FSR_RD_SHIFT);
+      break;
+    case CSR_FCSR:
+      dirty_fp_state;
+      state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT;
+      state.frm = (val & FSR_RD) >> FSR_RD_SHIFT;
+      break;
+    case CSR_MSTATUS: {
+      // if ((val ^ state.mstatus) &
+      //     (MSTATUS_MPP | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MXR))
+        // mmu->flush_tlb();
+
+      reg_t mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE
+                 | MSTATUS_MPRV | MSTATUS_SUM
+                 | MSTATUS_MXR | MSTATUS_TW | MSTATUS_TVM
+                 | MSTATUS_TSR | MSTATUS_UXL | MSTATUS_SXL |
+                 (ext ? MSTATUS_XS : 0);
+
+      reg_t requested_mpp = legalize_privilege(get_field(val, MSTATUS_MPP));
+      state.mstatus = set_field(state.mstatus, MSTATUS_MPP, requested_mpp);
+      if (supports_extension('S'))
+        mask |= MSTATUS_SPP;
+
+      state.mstatus = (state.mstatus & ~mask) | (val & mask);
+
+      bool dirty = (state.mstatus & MSTATUS_FS) == MSTATUS_FS;
+      dirty |= (state.mstatus & MSTATUS_XS) == MSTATUS_XS;
+      dirty = 0;
+      if (max_xlen == 32)
+        state.mstatus = set_field(state.mstatus, MSTATUS32_SD, dirty);
+      else
+        state.mstatus = set_field(state.mstatus, MSTATUS64_SD, dirty);
+
+      state.mstatus = set_field(state.mstatus, MSTATUS_UXL, xlen_to_uxl(max_xlen));
+      state.mstatus = set_field(state.mstatus, MSTATUS_UXL, xlen_to_uxl(max_xlen));
+      state.mstatus = set_field(state.mstatus, MSTATUS_SXL, xlen_to_uxl(max_xlen));
+      // U-XLEN == S-XLEN == M-XLEN
+      xlen = max_xlen;
+      break;
+    }
+    case CSR_MIP: {
+      reg_t mask = MIP_SSIP | MIP_STIP;
+      state.mip = (state.mip & ~mask) | (val & mask);
+      break;
+    }
+    case CSR_MIE:
+      state.mie = (state.mie & ~all_ints) | (val & all_ints);
+      break;
+    case CSR_MIDELEG:
+      state.mideleg = (state.mideleg & ~delegable_ints) | (val & delegable_ints);
+      break;
+    case CSR_MEDELEG: {
+      reg_t mask =
+        (1 << CAUSE_MISALIGNED_FETCH) |
+        (1 << CAUSE_BREAKPOINT) |
+        (1 << CAUSE_USER_ECALL) |
+        (1 << CAUSE_FETCH_PAGE_FAULT) |
+        (1 << CAUSE_LOAD_PAGE_FAULT) |
+        (1 << CAUSE_STORE_PAGE_FAULT);
+      state.medeleg = (state.medeleg & ~mask) | (val & mask);
+      break;
+    }
+    case CSR_MINSTRET:
+    case CSR_MCYCLE:
+      if (xlen == 32)
+        state.minstret = (state.minstret >> 32 << 32) | (val & 0xffffffffU);
+      else
+        state.minstret = val;
+      // The ISA mandates that if an instruction writes instret, the write
+      // takes precedence over the increment to instret.  However, Spike
+      // unconditionally increments instret after executing an instruction.
+      // Correct for this artifact by decrementing instret here.
+      state.minstret--;
+      break;
+    case CSR_MINSTRETH:
+    case CSR_MCYCLEH:
+      state.minstret = (val << 32) | (state.minstret << 32 >> 32);
+      state.minstret--; // See comment above.
+      break;
+    case CSR_SCOUNTEREN:
+      state.scounteren = val;
+      break;
+    case CSR_MCOUNTEREN:
+      state.mcounteren = val;
+      break;
+    case CSR_SSTATUS: {
+      reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
+                 | SSTATUS_XS | SSTATUS_SUM | SSTATUS_MXR;
+      return set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask));
+    }
+    case CSR_SIP: {
+      reg_t mask = MIP_SSIP & state.mideleg;
+      return set_csr(CSR_MIP, (state.mip & ~mask) | (val & mask));
+    }
+    case CSR_SIE:
+      return set_csr(CSR_MIE,
+                     (state.mie & ~state.mideleg) | (val & state.mideleg));
+    case CSR_SATP: {
+      mmu->flush_tlb();
+      if (max_xlen == 32)
+        state.satp = val & (SATP32_PPN | SATP32_MODE);
+      if (max_xlen == 64 && (get_field(val, SATP64_MODE) == SATP_MODE_OFF ||
+                             get_field(val, SATP64_MODE) == SATP_MODE_SV39 ||
+                             get_field(val, SATP64_MODE) == SATP_MODE_SV48))
+        state.satp = val & (SATP64_PPN | SATP64_MODE);
+      break;
+    }
+    case CSR_SEPC: state.sepc = val & ~(reg_t)1; break;
+    case CSR_STVEC: state.stvec = val >> 2 << 2; break;
+    case CSR_SSCRATCH: state.sscratch = val; break;
+    case CSR_SCAUSE: state.scause = val; break;
+    case CSR_STVAL: state.stval = val; break;
+    case CSR_MEPC: state.mepc = val & ~(reg_t)1; break;
+    case CSR_MTVEC: state.mtvec = val & ~(reg_t)2; break;
+    case CSR_MSCRATCH: state.mscratch = val; break;
+    case CSR_MCAUSE: state.mcause = val; break;
+    case CSR_MTVAL: state.mtval = val; break;
+    case CSR_MISA: {
+      // the write is ignored if increasing IALIGN would misalign the PC
+      if (!(val & (1L << ('C' - 'A'))) && (state.pc & 2))
+        break;
+
+      if (!(val & (1L << ('F' - 'A'))))
+        val &= ~(1L << ('D' - 'A'));
+
+      // allow MAFDC bits in MISA to be modified
+      reg_t mask = 0;
+      mask |= 1L << ('M' - 'A');
+      mask |= 1L << ('A' - 'A');
+      mask |= 1L << ('F' - 'A');
+      mask |= 1L << ('D' - 'A');
+      mask |= 1L << ('C' - 'A');
+      mask &= max_isa;
+
+      state.misa = (val & mask) | (state.misa & ~mask);
+      break;
+    }
+    case CSR_TSELECT:
+      if (val < state.num_triggers) {
+        state.tselect = val;
+      }
+      break;
+    case CSR_TDATA1:
+      {
+        mcontrol_t *mc = &state.mcontrol[state.tselect];
+        if (mc->dmode && !state.dcsr.cause) {
+          break;
+        }
+        mc->dmode = get_field(val, MCONTROL_DMODE(xlen));
+        mc->select = get_field(val, MCONTROL_SELECT);
+        mc->timing = get_field(val, MCONTROL_TIMING);
+        mc->action = (mcontrol_action_t) get_field(val, MCONTROL_ACTION);
+        mc->chain = get_field(val, MCONTROL_CHAIN);
+        mc->match = (mcontrol_match_t) get_field(val, MCONTROL_MATCH);
+        mc->m = get_field(val, MCONTROL_M);
+        mc->h = get_field(val, MCONTROL_H);
+        mc->s = get_field(val, MCONTROL_S);
+        mc->u = get_field(val, MCONTROL_U);
+        mc->execute = get_field(val, MCONTROL_EXECUTE);
+        mc->store = get_field(val, MCONTROL_STORE);
+        mc->load = get_field(val, MCONTROL_LOAD);
+        // Assume we're here because of csrw.
+        if (mc->execute)
+          mc->timing = 0;
+        trigger_updated();
+      }
+      break;
+    case CSR_TDATA2:
+      if (state.mcontrol[state.tselect].dmode && !state.dcsr.cause) {
+        break;
+      }
+      if (state.tselect < state.num_triggers) {
+        state.tdata2[state.tselect] = val;
+      }
+      break;
+    case CSR_DCSR:
+      state.dcsr.prv = get_field(val, DCSR_PRV);
+      state.dcsr.step = get_field(val, DCSR_STEP);
+      // TODO: ndreset and fullreset
+      state.dcsr.ebreakm = get_field(val, DCSR_EBREAKM);
+      state.dcsr.ebreakh = get_field(val, DCSR_EBREAKH);
+      state.dcsr.ebreaks = get_field(val, DCSR_EBREAKS);
+      state.dcsr.ebreaku = get_field(val, DCSR_EBREAKU);
+      state.dcsr.halt = get_field(val, DCSR_HALT);
+      break;
+    case CSR_DPC:
+      state.dpc = val & ~(reg_t)1;
+      break;
+    case CSR_DSCRATCH:
+      state.dscratch = val;
+      break;
+  }
+}
+
+// Note that get_csr is sometimes called when read side-effects should not
+// be actioned.  In other words, Spike cannot currently support CSRs with
+// side effects on reads.
+reg_t processor_t::get_csr(int which)
+{
+  uint32_t ctr_en = -1;
+  if (state.prv < PRV_M)
+    ctr_en &= state.mcounteren;
+  if (state.prv < PRV_S)
+    ctr_en &= state.scounteren;
+  bool ctr_ok = (ctr_en >> (which & 31)) & 1;
+
+  if (ctr_ok) {
+    if (which >= CSR_HPMCOUNTER3 && which <= CSR_HPMCOUNTER31)
+      return 0;
+    if (xlen == 32 && which >= CSR_HPMCOUNTER3H && which <= CSR_HPMCOUNTER31H)
+      return 0;
+  }
+  if (which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31)
+    return 0;
+  if (xlen == 32 && which >= CSR_MHPMCOUNTER3H && which <= CSR_MHPMCOUNTER31H)
+    return 0;
+  if (which >= CSR_MHPMEVENT3 && which <= CSR_MHPMEVENT31)
+    return 0;
+
+  // if (which >= CSR_PMPADDR0 && which < CSR_PMPADDR0 + state.n_pmp)
+  //   return state.pmpaddr[which - CSR_PMPADDR0];
+
+  // if (which >= CSR_PMPCFG0 && which < CSR_PMPCFG0 + state.n_pmp / 4) {
+  //   require((which & ((xlen / 32) - 1)) == 0);
+
+  //   reg_t res = 0;
+  //   for (size_t i0 = (which - CSR_PMPCFG0) * 4, i = i0; i < i0 + xlen / 8 && i < state.n_pmp; i++)
+  //     res |= reg_t(state.pmpcfg[i]) << (8 * (i - i0));
+  //   return res;
+  // }
+
+  switch (which)
+  {
+    case CSR_FFLAGS:
+      require_fp;
+      if (!supports_extension('F'))
+        break;
+      return state.fflags;
+    case CSR_FRM:
+      require_fp;
+      if (!supports_extension('F'))
+        break;
+      return state.frm;
+    case CSR_FCSR:
+      require_fp;
+      if (!supports_extension('F'))
+        break;
+      return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
+    case CSR_INSTRET:
+    case CSR_CYCLE:
+      if (ctr_ok)
+        return state.minstret;
+      break;
+    case CSR_MINSTRET:
+    case CSR_MCYCLE:
+      return state.minstret;
+    case CSR_INSTRETH:
+    case CSR_CYCLEH:
+      if (ctr_ok && xlen == 32)
+        return state.minstret >> 32;
+      break;
+    case CSR_MINSTRETH:
+    case CSR_MCYCLEH:
+      if (xlen == 32)
+        return state.minstret >> 32;
+      break;
+    case CSR_SCOUNTEREN: return state.scounteren;
+    case CSR_MCOUNTEREN: return state.mcounteren;
+    case CSR_SSTATUS: {
+      reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
+                 | SSTATUS_XS | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_UXL;
+      reg_t sstatus = state.mstatus & mask;
+      if ((sstatus & SSTATUS_FS) == SSTATUS_FS ||
+          (sstatus & SSTATUS_XS) == SSTATUS_XS)
+        sstatus |= (xlen == 32 ? SSTATUS32_SD : SSTATUS64_SD);
+      return sstatus;
+    }
+    case CSR_SIP: return state.mip & state.mideleg;
+    case CSR_SIE: return state.mie & state.mideleg;
+    case CSR_SEPC: return state.sepc & pc_alignment_mask();
+    case CSR_STVAL: return state.stval;
+    case CSR_STVEC: return state.stvec;
+    case CSR_SCAUSE:
+      if (max_xlen > xlen)
+        return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1));
+      return state.scause;
+    case CSR_SATP:
+      if (get_field(state.mstatus, MSTATUS_TVM))
+        require_privilege(PRV_M);
+      return state.satp;
+    case CSR_SSCRATCH: return state.sscratch;
+    case CSR_MSTATUS: return state.mstatus;
+    case CSR_MIP: return state.mip;
+    case CSR_MIE: return state.mie;
+    case CSR_MEPC: return state.mepc & pc_alignment_mask();
+    case CSR_MSCRATCH: return state.mscratch;
+    case CSR_MCAUSE: return state.mcause;
+    case CSR_MTVAL: return state.mtval;
+    case CSR_MISA: return state.misa;
+    case CSR_MARCHID: return 5;
+    case CSR_MIMPID: return 0;
+    case CSR_MVENDORID: return 0;
+    case CSR_MHARTID: return id;
+    case CSR_MTVEC: return state.mtvec;
+    case CSR_MEDELEG: return state.medeleg;
+    case CSR_MIDELEG: return state.mideleg;
+    case CSR_TSELECT: return state.tselect;
+    case CSR_TDATA1:
+      if (state.tselect < state.num_triggers) {
+        reg_t v = 0;
+        mcontrol_t *mc = &state.mcontrol[state.tselect];
+        v = set_field(v, MCONTROL_TYPE(xlen), mc->type);
+        v = set_field(v, MCONTROL_DMODE(xlen), mc->dmode);
+        v = set_field(v, MCONTROL_MASKMAX(xlen), mc->maskmax);
+        v = set_field(v, MCONTROL_SELECT, mc->select);
+        v = set_field(v, MCONTROL_TIMING, mc->timing);
+        v = set_field(v, MCONTROL_ACTION, mc->action);
+        v = set_field(v, MCONTROL_CHAIN, mc->chain);
+        v = set_field(v, MCONTROL_MATCH, mc->match);
+        v = set_field(v, MCONTROL_M, mc->m);
+        v = set_field(v, MCONTROL_H, mc->h);
+        v = set_field(v, MCONTROL_S, mc->s);
+        v = set_field(v, MCONTROL_U, mc->u);
+        v = set_field(v, MCONTROL_EXECUTE, mc->execute);
+        v = set_field(v, MCONTROL_STORE, mc->store);
+        v = set_field(v, MCONTROL_LOAD, mc->load);
+        return v;
+      } else {
+        return 0;
+      }
+      break;
+    case CSR_TDATA2:
+      if (state.tselect < state.num_triggers) {
+        return state.tdata2[state.tselect];
+      } else {
+        return 0;
+      }
+      break;
+    case CSR_TDATA3: return 0;
+    case CSR_DCSR:
+      {
+        uint32_t v = 0;
+        v = set_field(v, DCSR_XDEBUGVER, 1);
+        v = set_field(v, DCSR_EBREAKM, state.dcsr.ebreakm);
+        v = set_field(v, DCSR_EBREAKH, state.dcsr.ebreakh);
+        v = set_field(v, DCSR_EBREAKS, state.dcsr.ebreaks);
+        v = set_field(v, DCSR_EBREAKU, state.dcsr.ebreaku);
+        v = set_field(v, DCSR_STOPCYCLE, 0);
+        v = set_field(v, DCSR_STOPTIME, 0);
+        v = set_field(v, DCSR_CAUSE, state.dcsr.cause);
+        v = set_field(v, DCSR_STEP, state.dcsr.step);
+        v = set_field(v, DCSR_PRV, state.dcsr.prv);
+        return v;
+      }
+    case CSR_DPC:
+      return state.dpc & pc_alignment_mask();
+    case CSR_DSCRATCH:
+      return state.dscratch;
+  }
+  throw trap_illegal_instruction(0);
+}
+
+reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
+{
+  throw trap_illegal_instruction(0);
+}
+
+insn_func_t processor_t::decode_insn(insn_t insn)
+{
+  // look up opcode in hash table
+  size_t idx = insn.bits() % OPCODE_CACHE_SIZE;
+  insn_desc_t desc = opcode_cache[idx];
+
+  if (unlikely(insn.bits() != desc.match)) {
+    // fall back to linear search
+    insn_desc_t* p = &instructions[0];
+    while ((insn.bits() & p->mask) != p->match)
+      p++;
+    desc = *p;
+
+    if (p->mask != 0 && p > &instructions[0]) {
+      if (p->match != (p-1)->match && p->match != (p+1)->match) {
+        // move to front of opcode list to reduce miss penalty
+        while (--p >= &instructions[0])
+          *(p+1) = *p;
+        instructions[0] = desc;
+      }
+    }
+
+    opcode_cache[idx] = desc;
+    opcode_cache[idx].match = insn.bits();
+  }
+
+  return xlen == 64 ? desc.rv64 : desc.rv32;
+}
+
+void processor_t::register_insn(insn_desc_t desc)
+{
+  instructions.push_back(desc);
+}
+
+void processor_t::build_opcode_map()
+{
+  struct cmp {
+    bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) {
+      if (lhs.match == rhs.match)
+        return lhs.mask > rhs.mask;
+      return lhs.match > rhs.match;
+    }
+  };
+  std::sort(instructions.begin(), instructions.end(), cmp());
+
+  for (size_t i = 0; i < OPCODE_CACHE_SIZE; i++)
+    opcode_cache[i] = {0, 0, &illegal_instruction, &illegal_instruction};
+}
+
+void processor_t::register_extension(extension_t* x)
+{
+  for (auto insn : x->get_instructions())
+    register_insn(insn);
+  build_opcode_map();
+  for (auto disasm_insn : x->get_disasms())
+    disassembler->add_insn(disasm_insn);
+  if (ext != NULL)
+    throw std::logic_error("only one extension may be registered");
+  ext = x;
+  x->set_processor(this);
+}
+
+void processor_t::register_base_instructions()
+{
+  #define DECLARE_INSN(name, match, mask) \
+    insn_bits_t name##_match = (match), name##_mask = (mask);
+  #include "encoding.h"
+  #undef DECLARE_INSN
+
+  #define DEFINE_INSN(name) \
+    REGISTER_INSN(this, name, name##_match, name##_mask)
+  #include "insn_list.h"
+  #undef DEFINE_INSN
+
+  register_insn({0, 0, &illegal_instruction, &illegal_instruction});
+  build_opcode_map();
+}
+
+bool processor_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  switch (addr)
+  {
+    case 0:
+      if (len <= 4) {
+        memset(bytes, 0, len);
+        bytes[0] = get_field(state.mip, MIP_MSIP);
+        return true;
+      }
+      break;
+  }
+
+  return false;
+}
+
+bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  switch (addr)
+  {
+    case 0:
+      if (len <= 4) {
+        state.mip = set_field(state.mip, MIP_MSIP, bytes[0]);
+        return true;
+      }
+      break;
+  }
+
+  return false;
+}
+
+void processor_t::trigger_updated()
+{
+  // mmu->flush_tlb();
+  mmu->check_triggers_fetch = false;
+  mmu->check_triggers_load = false;
+  mmu->check_triggers_store = false;
+
+  for (unsigned i = 0; i < state.num_triggers; i++) {
+    if (state.mcontrol[i].execute) {
+      mmu->check_triggers_fetch = true;
+    }
+    if (state.mcontrol[i].load) {
+      mmu->check_triggers_load = true;
+    }
+    if (state.mcontrol[i].store) {
+      mmu->check_triggers_store = true;
+    }
+  }
+}
diff --git a/tb/riscv-isa-sim/riscv/processor.h b/tb/riscv-isa-sim/riscv/processor.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1e92a76f7bfe3288ad7f17dbff25918db2e011e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/processor.h
@@ -0,0 +1,350 @@
+// See LICENSE for license details.
+#ifndef _RISCV_PROCESSOR_H
+#define _RISCV_PROCESSOR_H
+
+#include "decode.h"
+#include "config.h"
+#include "devices.h"
+#include "trap.h"
+#include <string>
+#include <vector>
+#include <map>
+#include "debug_rom_defines.h"
+
+class processor_t;
+class mmu_t;
+typedef reg_t (*insn_func_t)(processor_t*, insn_t, reg_t);
+class simif_t;
+class trap_t;
+class extension_t;
+class disassembler_t;
+
+struct insn_desc_t
+{
+  insn_bits_t match;
+  insn_bits_t mask;
+  insn_func_t rv32;
+  insn_func_t rv64;
+};
+
+struct commit_log_reg_t
+{
+  reg_t addr;
+  freg_t data;
+};
+
+typedef struct
+{
+  uint8_t prv;
+  bool step;
+  bool ebreakm;
+  bool ebreakh;
+  bool ebreaks;
+  bool ebreaku;
+  bool halt;
+  uint8_t cause;
+} dcsr_t;
+
+typedef enum
+{
+  ACTION_DEBUG_EXCEPTION = MCONTROL_ACTION_DEBUG_EXCEPTION,
+  ACTION_DEBUG_MODE = MCONTROL_ACTION_DEBUG_MODE,
+  ACTION_TRACE_START = MCONTROL_ACTION_TRACE_START,
+  ACTION_TRACE_STOP = MCONTROL_ACTION_TRACE_STOP,
+  ACTION_TRACE_EMIT = MCONTROL_ACTION_TRACE_EMIT
+} mcontrol_action_t;
+
+typedef enum
+{
+  MATCH_EQUAL = MCONTROL_MATCH_EQUAL,
+  MATCH_NAPOT = MCONTROL_MATCH_NAPOT,
+  MATCH_GE = MCONTROL_MATCH_GE,
+  MATCH_LT = MCONTROL_MATCH_LT,
+  MATCH_MASK_LOW = MCONTROL_MATCH_MASK_LOW,
+  MATCH_MASK_HIGH = MCONTROL_MATCH_MASK_HIGH
+} mcontrol_match_t;
+
+typedef struct
+{
+  uint8_t type;
+  bool dmode;
+  uint8_t maskmax;
+  bool select;
+  bool timing;
+  mcontrol_action_t action;
+  bool chain;
+  mcontrol_match_t match;
+  bool m;
+  bool h;
+  bool s;
+  bool u;
+  bool execute;
+  bool store;
+  bool load;
+} mcontrol_t;
+
+// architectural state of a RISC-V hart
+struct state_t
+{
+  void reset(reg_t max_isa);
+
+  static const int num_triggers = 4;
+
+  reg_t pc;
+  regfile_t<reg_t, NXPR, true> XPR;
+  regfile_t<freg_t, NFPR, false> FPR;
+  // control and status registers
+  reg_t prv;    // TODO: Can this be an enum instead?
+  reg_t misa;
+  reg_t mstatus;
+  reg_t mepc;
+  reg_t mtval;
+  reg_t mscratch;
+  reg_t mtvec;
+  reg_t mcause;
+  reg_t minstret;
+  reg_t mie;
+  reg_t mip;
+  reg_t medeleg;
+  reg_t mideleg;
+  uint32_t mcounteren;
+  uint32_t scounteren;
+  reg_t sepc;
+  reg_t stval;
+  reg_t sscratch;
+  reg_t stvec;
+  reg_t satp;
+  reg_t scause;
+  reg_t dpc;
+  reg_t dscratch;
+  dcsr_t dcsr;
+  reg_t tselect;
+  mcontrol_t mcontrol[num_triggers];
+  reg_t tdata2[num_triggers];
+
+  static const int n_pmp = 16;
+  uint8_t pmpcfg[n_pmp];
+  reg_t pmpaddr[n_pmp];
+
+  uint32_t fflags;
+  uint32_t frm;
+  bool serialized; // whether timer CSRs are in a well-defined state
+
+  // When true, execute a single instruction and then enter debug mode.  This
+  // can only be set by executing dret.
+  enum {
+      STEP_NONE,
+      STEP_STEPPING,
+      STEP_STEPPED
+  } single_step;
+
+#ifdef RISCV_ENABLE_COMMITLOG
+  commit_log_reg_t log_reg_write;
+  reg_t last_inst_priv;
+  int last_inst_xlen;
+  int last_inst_flen;
+  uint32_t last_insn;
+  bool     was_exception;
+#endif
+};
+
+typedef enum {
+  OPERATION_EXECUTE,
+  OPERATION_STORE,
+  OPERATION_LOAD,
+} trigger_operation_t;
+
+// Count number of contiguous 1 bits starting from the LSB.
+static int cto(reg_t val)
+{
+  int res = 0;
+  while ((val & 1) == 1)
+    val >>= 1, res++;
+  return res;
+}
+
+// this class represents one processor in a RISC-V machine.
+class processor_t : public abstract_device_t
+{
+public:
+  processor_t(const char* isa, simif_t* sim, uint32_t id, bool halt_on_reset=false);
+  ~processor_t();
+
+  void set_debug(bool value);
+  void set_histogram(bool value);
+  void reset();
+  void step(size_t n); // run for n cycles
+  void set_csr(int which, reg_t val);
+  reg_t get_csr(int which);
+  mmu_t* get_mmu() { return mmu; }
+  state_t* get_state() { return &state; }
+  unsigned get_xlen() { return xlen; }
+  unsigned get_max_xlen() { return max_xlen; }
+  std::string get_isa_string() { return isa_string; }
+  unsigned get_flen() {
+    return supports_extension('Q') ? 128 :
+           supports_extension('D') ? 64 :
+           supports_extension('F') ? 32 : 0;
+  }
+  extension_t* get_extension() { return ext; }
+  bool supports_extension(unsigned char ext) {
+    if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a';
+    return ext >= 'A' && ext <= 'Z' && ((state.misa >> (ext - 'A')) & 1);
+  }
+  reg_t pc_alignment_mask() {
+    return ~(reg_t)(supports_extension('C') ? 0 : 2);
+  }
+  void check_pc_alignment(reg_t pc) {
+    if (unlikely(pc & ~pc_alignment_mask()))
+      throw trap_instruction_address_misaligned(pc);
+  }
+  reg_t legalize_privilege(reg_t);
+  void set_privilege(reg_t);
+  void update_histogram(reg_t pc);
+  const disassembler_t* get_disassembler() { return disassembler; }
+
+  void register_insn(insn_desc_t);
+  void register_extension(extension_t*);
+
+  // MMIO slave interface
+  bool load(reg_t addr, size_t len, uint8_t* bytes);
+  bool store(reg_t addr, size_t len, const uint8_t* bytes);
+
+  // When true, display disassembly of each instruction that's executed.
+  bool debug;
+  // When true, take the slow simulation path.
+  bool slow_path();
+  bool halted() { return state.dcsr.cause ? true : false; }
+  bool halt_request;
+
+  // Return the index of a trigger that matched, or -1.
+  inline int trigger_match(trigger_operation_t operation, reg_t address, reg_t data)
+  {
+    if (state.dcsr.cause)
+      return -1;
+
+    bool chain_ok = true;
+
+    for (unsigned int i = 0; i < state.num_triggers; i++) {
+      if (!chain_ok) {
+        chain_ok |= !state.mcontrol[i].chain;
+        continue;
+      }
+
+      if ((operation == OPERATION_EXECUTE && !state.mcontrol[i].execute) ||
+          (operation == OPERATION_STORE && !state.mcontrol[i].store) ||
+          (operation == OPERATION_LOAD && !state.mcontrol[i].load) ||
+          (state.prv == PRV_M && !state.mcontrol[i].m) ||
+          (state.prv == PRV_S && !state.mcontrol[i].s) ||
+          (state.prv == PRV_U && !state.mcontrol[i].u)) {
+        continue;
+      }
+
+      reg_t value;
+      if (state.mcontrol[i].select) {
+        value = data;
+      } else {
+        value = address;
+      }
+
+      // We need this because in 32-bit mode sometimes the PC bits get sign
+      // extended.
+      if (xlen == 32) {
+        value &= 0xffffffff;
+      }
+
+      switch (state.mcontrol[i].match) {
+        case MATCH_EQUAL:
+          if (value != state.tdata2[i])
+            continue;
+          break;
+        case MATCH_NAPOT:
+          {
+            reg_t mask = ~((1 << cto(state.tdata2[i])) - 1);
+            if ((value & mask) != (state.tdata2[i] & mask))
+              continue;
+          }
+          break;
+        case MATCH_GE:
+          if (value < state.tdata2[i])
+            continue;
+          break;
+        case MATCH_LT:
+          if (value >= state.tdata2[i])
+            continue;
+          break;
+        case MATCH_MASK_LOW:
+          {
+            reg_t mask = state.tdata2[i] >> (xlen/2);
+            if ((value & mask) != (state.tdata2[i] & mask))
+              continue;
+          }
+          break;
+        case MATCH_MASK_HIGH:
+          {
+            reg_t mask = state.tdata2[i] >> (xlen/2);
+            if (((value >> (xlen/2)) & mask) != (state.tdata2[i] & mask))
+              continue;
+          }
+          break;
+      }
+
+      if (!state.mcontrol[i].chain) {
+        return i;
+      }
+      chain_ok = true;
+    }
+    return -1;
+  }
+
+  void trigger_updated();
+
+private:
+  simif_t* sim;
+  mmu_t* mmu; // main memory is always accessed via the mmu
+  extension_t* ext;
+  disassembler_t* disassembler;
+  state_t state;
+  uint32_t id;
+  unsigned max_xlen;
+  unsigned xlen;
+  reg_t max_isa;
+  std::string isa_string;
+  bool histogram_enabled;
+  bool halt_on_reset;
+
+  std::vector<insn_desc_t> instructions;
+  std::map<reg_t,uint64_t> pc_histogram;
+
+  static const size_t OPCODE_CACHE_SIZE = 8191;
+  insn_desc_t opcode_cache[OPCODE_CACHE_SIZE];
+
+  void take_pending_interrupt() { take_interrupt(state.mip & state.mie); }
+  void take_interrupt(reg_t mask); // take first enabled interrupt in mask
+  void take_trap(trap_t& t, reg_t epc); // take an exception
+  void disasm(insn_t insn); // disassemble and print an instruction
+  int paddr_bits();
+
+  void enter_debug_mode(uint8_t cause);
+
+  friend class mmu_t;
+  friend class clint_t;
+  friend class extension_t;
+
+  void parse_isa_string(const char* isa);
+  void build_opcode_map();
+  void register_base_instructions();
+  insn_func_t decode_insn(insn_t insn);
+
+  // Track repeated executions for processor_t::disasm()
+  uint64_t last_pc, last_bits, executions;
+};
+
+reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc);
+
+#define REGISTER_INSN(proc, name, match, mask) \
+  extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
+  extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
+  proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name});
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/regnames.cc b/tb/riscv-isa-sim/riscv/regnames.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0bf8d9c6e990f0424a1c2cb3dc07f9e0364d5d72
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/regnames.cc
@@ -0,0 +1,26 @@
+// See LICENSE for license details.
+
+#include "disasm.h"
+
+const char* xpr_name[] = {
+  "zero", "ra", "sp",  "gp",  "tp", "t0",  "t1",  "t2",
+  "s0",   "s1", "a0",  "a1",  "a2", "a3",  "a4",  "a5",
+  "a6",   "a7", "s2",  "s3",  "s4", "s5",  "s6",  "s7",
+  "s8",   "s9", "s10", "s11", "t3", "t4",  "t5",  "t6"
+};
+
+const char* fpr_name[] = {
+  "ft0", "ft1", "ft2",  "ft3",  "ft4", "ft5", "ft6",  "ft7",
+  "fs0", "fs1", "fa0",  "fa1",  "fa2", "fa3", "fa4",  "fa5",
+  "fa6", "fa7", "fs2",  "fs3",  "fs4", "fs5", "fs6",  "fs7",
+  "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
+};
+
+const char* csr_name(int which) {
+  switch (which) {
+    #define DECLARE_CSR(name, number)  case number: return #name;
+    #include "encoding.h"
+    #undef DECLARE_CSR
+  }
+  return "unknown-csr";
+}
diff --git a/tb/riscv-isa-sim/riscv/remote_bitbang.cc b/tb/riscv-isa-sim/riscv/remote_bitbang.cc
new file mode 100644
index 0000000000000000000000000000000000000000..21306dd166f46fd3ebed2d1bf034550b1e6f5ed4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/remote_bitbang.cc
@@ -0,0 +1,180 @@
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+
+#include "remote_bitbang.h"
+
+#if 1
+#  define D(x) x
+#else
+#  define D(x)
+#endif
+
+/////////// remote_bitbang_t
+
+remote_bitbang_t::remote_bitbang_t(uint16_t port, jtag_dtm_t *tap) :
+  tap(tap),
+  socket_fd(0),
+  client_fd(0),
+  recv_start(0),
+  recv_end(0)
+{
+  socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (socket_fd == -1) {
+    fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
+        strerror(errno), errno);
+    abort();
+  }
+
+  fcntl(socket_fd, F_SETFL, O_NONBLOCK);
+  int reuseaddr = 1;
+  if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
+        sizeof(int)) == -1) {
+    fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
+        strerror(errno), errno);
+    abort();
+  }
+
+  struct sockaddr_in addr;
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = INADDR_ANY;
+  addr.sin_port = htons(port);
+
+  if (bind(socket_fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
+    fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
+        strerror(errno), errno);
+    abort();
+  }
+
+  if (listen(socket_fd, 1) == -1) {
+    fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
+        strerror(errno), errno);
+    abort();
+  }
+
+  socklen_t addrlen = sizeof(addr);
+  if (getsockname(socket_fd, (struct sockaddr *) &addr, &addrlen) == -1) {
+    fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
+        strerror(errno), errno);
+    abort();
+  }
+
+  printf("Listening for remote bitbang connection on port %d.\n",
+      ntohs(addr.sin_port));
+  fflush(stdout);
+}
+
+void remote_bitbang_t::accept()
+{
+  client_fd = ::accept(socket_fd, NULL, NULL);
+  if (client_fd == -1) {
+    if (errno == EAGAIN) {
+      // No client waiting to connect right now.
+    } else {
+      fprintf(stderr, "failed to accept on socket: %s (%d)\n", strerror(errno),
+          errno);
+      abort();
+    }
+  } else {
+    fcntl(client_fd, F_SETFL, O_NONBLOCK);
+  }
+}
+
+void remote_bitbang_t::tick()
+{
+  if (client_fd > 0) {
+    execute_commands();
+  } else {
+    this->accept();
+  }
+}
+
+void remote_bitbang_t::execute_commands()
+{
+  static char send_buf[buf_size];
+  unsigned total_processed = 0;
+  bool quit = false;
+  bool in_rti = tap->state() == RUN_TEST_IDLE;
+  bool entered_rti = false;
+  while (1) {
+    if (recv_start < recv_end) {
+      unsigned send_offset = 0;
+      while (recv_start < recv_end) {
+        uint8_t command = recv_buf[recv_start];
+
+        switch (command) {
+          case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
+          case 'b': /* fprintf(stderr, "_______\n"); */ break;
+          case 'r': tap->reset(); break;
+          case '0': tap->set_pins(0, 0, 0); break;
+          case '1': tap->set_pins(0, 0, 1); break;
+          case '2': tap->set_pins(0, 1, 0); break;
+          case '3': tap->set_pins(0, 1, 1); break;
+          case '4': tap->set_pins(1, 0, 0); break;
+          case '5': tap->set_pins(1, 0, 1); break;
+          case '6': tap->set_pins(1, 1, 0); break;
+          case '7': tap->set_pins(1, 1, 1); break;
+          case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
+          case 'Q': quit = true; break;
+          default:
+                    fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
+                        command);
+        }
+        recv_start++;
+        total_processed++;
+        if (!in_rti && tap->state() == RUN_TEST_IDLE) {
+          entered_rti = true;
+          break;
+        }
+        in_rti = false;
+      }
+      unsigned sent = 0;
+      while (sent < send_offset) {
+        ssize_t bytes = write(client_fd, send_buf + sent, send_offset);
+        if (bytes == -1) {
+          fprintf(stderr, "failed to write to socket: %s (%d)\n", strerror(errno), errno);
+          abort();
+        }
+        sent += bytes;
+      }
+    }
+
+    if (total_processed > buf_size || quit || entered_rti) {
+      // Don't go forever, because that could starve the main simulation.
+      break;
+    }
+
+    recv_start = 0;
+    recv_end = read(client_fd, recv_buf, buf_size);
+
+    if (recv_end == -1) {
+      if (errno == EAGAIN) {
+        break;
+      } else {
+        fprintf(stderr, "remote_bitbang failed to read on socket: %s (%d)\n",
+            strerror(errno), errno);
+        abort();
+      }
+    }
+
+    if (quit) {
+      fprintf(stderr, "Remote Bitbang received 'Q'\n");
+    }
+
+    if (recv_end == 0 || quit) {
+      // The remote disconnected.
+      fprintf(stderr, "Received nothing. Quitting.\n");
+      close(client_fd);
+      client_fd = 0;
+      break;
+    }
+  }
+}
diff --git a/tb/riscv-isa-sim/riscv/remote_bitbang.h b/tb/riscv-isa-sim/riscv/remote_bitbang.h
new file mode 100644
index 0000000000000000000000000000000000000000..1db4d550140ea8bad605663911579bbe8e857501
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/remote_bitbang.h
@@ -0,0 +1,34 @@
+#ifndef REMOTE_BITBANG_H
+#define REMOTE_BITBANG_H
+
+#include <stdint.h>
+
+#include "jtag_dtm.h"
+
+class remote_bitbang_t
+{
+public:
+  // Create a new server, listening for connections from localhost on the given
+  // port.
+  remote_bitbang_t(uint16_t port, jtag_dtm_t *tap);
+
+  // Do a bit of work.
+  void tick();
+
+private:
+  jtag_dtm_t *tap;
+
+  int socket_fd;
+  int client_fd;
+
+  static const ssize_t buf_size = 64 * 1024;
+  char recv_buf[buf_size];
+  ssize_t recv_start, recv_end;
+
+  // Check for a client connecting, and accept if there is one.
+  void accept();
+  // Execute any commands the client has for us.
+  void execute_commands();
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/riscv.ac b/tb/riscv-isa-sim/riscv/riscv.ac
new file mode 100644
index 0000000000000000000000000000000000000000..68bcdb55d17f175ca1c8a52a0d2df768375d475d
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/riscv.ac
@@ -0,0 +1,44 @@
+AC_LANG_CPLUSPLUS
+
+AC_ARG_WITH(isa,
+	[AS_HELP_STRING([--with-isa=RV64IMAFDC],
+		[Sets the default RISC-V ISA])],
+  AC_DEFINE_UNQUOTED([DEFAULT_ISA], "$withval", [Default value for --isa switch]),
+  AC_DEFINE_UNQUOTED([DEFAULT_ISA], "RV64IMAFDC", [Default value for --isa switch]))
+
+AC_SEARCH_LIBS([dlopen], [dl dld], [], [
+  AC_MSG_ERROR([unable to find the dlopen() function])
+])
+
+AC_ARG_WITH([fesvr],
+  [AS_HELP_STRING([--with-fesvr],
+    [path to your fesvr installation if not in a standard location])],
+  [
+    LDFLAGS="-L$withval/lib $LDFLAGS"
+    CPPFLAGS="-I$withval/include $CPPFLAGS"
+  ]
+)
+
+AC_CHECK_LIB(fesvr, libfesvr_is_present, [], [AC_MSG_ERROR([libfesvr is required])], [-pthread])
+
+AC_CHECK_LIB(pthread, pthread_create, [], [AC_MSG_ERROR([libpthread is required])])
+
+AC_ARG_ENABLE([commitlog], AS_HELP_STRING([--enable-commitlog], [Enable commit log generation]))
+AS_IF([test "x$enable_commitlog" = "xyes"], [
+  AC_DEFINE([RISCV_ENABLE_COMMITLOG],,[Enable commit log generation])
+])
+
+AC_ARG_ENABLE([histogram], AS_HELP_STRING([--enable-histogram], [Enable PC histogram generation]))
+AS_IF([test "x$enable_histogram" = "xyes"], [
+  AC_DEFINE([RISCV_ENABLE_HISTOGRAM],,[Enable PC histogram generation])
+])
+
+AC_ARG_ENABLE([dirty], AS_HELP_STRING([--enable-dirty], [Enable hardware management of PTE accessed and dirty bits]))
+AS_IF([test "x$enable_dirty" = "xyes"], [
+  AC_DEFINE([RISCV_ENABLE_DIRTY],,[Enable hardware management of PTE accessed and dirty bits])
+])
+
+AC_ARG_ENABLE([misaligned], AS_HELP_STRING([--enable-misaligned], [Enable hardware support for misaligned loads and stores]))
+AS_IF([test "x$enable_misaligned" = "xyes"], [
+  AC_DEFINE([RISCV_ENABLE_MISALIGNED],,[Enable hardware support for misaligned loads and stores])
+])
diff --git a/tb/riscv-isa-sim/riscv/riscv.mk.in b/tb/riscv-isa-sim/riscv/riscv.mk.in
new file mode 100644
index 0000000000000000000000000000000000000000..2b04b5431e6528bda3e6321a03f4fe140e27be4b
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/riscv.mk.in
@@ -0,0 +1,315 @@
+get_insn_list = $(shell grep ^DECLARE_INSN $(1) | sed 's/DECLARE_INSN(\(.*\),.*,.*)/\1/')
+get_opcode = $(shell grep ^DECLARE_INSN.*\\\<$(2)\\\> $(1) | sed 's/DECLARE_INSN(.*,\(.*\),.*)/\1/')
+
+riscv_subproject_deps = \
+	softfloat \
+
+riscv_install_prog_srcs = \
+
+riscv_hdrs = \
+	common.h \
+	decode.h \
+	devices.h \
+	disasm.h \
+	dts.h \
+	mmu.h \
+	processor.h \
+	sim.h \
+	simif.h \
+	trap.h \
+	encoding.h \
+	cachesim.h \
+	memtracer.h \
+	tracer.h \
+	extension.h \
+	rocc.h \
+	insn_template.h \
+	mulhi.h \
+	debug_module.h \
+	debug_rom_defines.h \
+	remote_bitbang.h \
+	jtag_dtm.h \
+
+riscv_precompiled_hdrs = \
+	insn_template.h \
+
+riscv_srcs = \
+	processor.cc \
+	execute.cc \
+	dts.cc \
+	sim.cc \
+	interactive.cc \
+	trap.cc \
+	cachesim.cc \
+	mmu.cc \
+	disasm.cc \
+	extension.cc \
+	extensions.cc \
+	rocc.cc \
+	regnames.cc \
+	devices.cc \
+	rom.cc \
+    clint.cc \
+	uart.cc \
+	dump.cc \
+	debug_module.cc \
+	remote_bitbang.cc \
+	jtag_dtm.cc \
+	$(riscv_gen_srcs) \
+
+riscv_test_srcs =
+
+riscv_gen_hdrs = \
+	icache.h \
+	insn_list.h \
+
+riscv_insn_list = \
+	add \
+	addi \
+	addiw \
+	addw \
+	amoadd_d \
+	amoadd_w \
+	amoand_d \
+	amoand_w \
+	amomax_d \
+	amomaxu_d \
+	amomaxu_w \
+	amomax_w \
+	amomin_d \
+	amominu_d \
+	amominu_w \
+	amomin_w \
+	amoor_d \
+	amoor_w \
+	amoswap_d \
+	amoswap_w \
+	amoxor_d \
+	amoxor_w \
+	and \
+	andi \
+	auipc \
+	beq \
+	bge \
+	bgeu \
+	blt \
+	bltu \
+	bne \
+	c_add \
+	c_addi4spn \
+	c_addi \
+	c_addw \
+	c_and \
+	c_andi \
+	c_beqz \
+	c_bnez \
+	c_ebreak \
+	c_fld \
+	c_fldsp \
+	c_flw \
+	c_flwsp \
+	c_fsd \
+	c_fsdsp \
+	c_fsw \
+	c_fswsp \
+	c_jal \
+	c_jalr \
+	c_j \
+	c_jr \
+	c_li \
+	c_lui \
+	c_lw \
+	c_lwsp \
+	c_mv \
+	c_or \
+	c_slli \
+	c_srai \
+	c_srli \
+	c_sub \
+	c_subw \
+	c_xor \
+	csrrc \
+	csrrci \
+	csrrs \
+	csrrsi \
+	csrrw \
+	csrrwi \
+	c_sw \
+	c_swsp \
+	div \
+	divu \
+	divuw \
+	divw \
+	dret \
+	ebreak \
+	ecall \
+	fadd_d \
+	fadd_q \
+	fadd_s \
+	fclass_d \
+	fclass_q \
+	fclass_s \
+	fcvt_d_l \
+	fcvt_d_lu \
+	fcvt_d_q \
+	fcvt_d_s \
+	fcvt_d_w \
+	fcvt_d_wu \
+	fcvt_l_d \
+	fcvt_l_q \
+	fcvt_l_s \
+	fcvt_lu_d \
+	fcvt_lu_q \
+	fcvt_lu_s \
+	fcvt_q_d \
+	fcvt_q_l \
+	fcvt_q_lu \
+	fcvt_q_s \
+	fcvt_q_w \
+	fcvt_q_wu \
+	fcvt_s_d \
+	fcvt_s_l \
+	fcvt_s_lu \
+	fcvt_s_q \
+	fcvt_s_w \
+	fcvt_s_wu \
+	fcvt_w_d \
+	fcvt_w_q \
+	fcvt_w_s \
+	fcvt_wu_d \
+	fcvt_wu_q \
+	fcvt_wu_s \
+	fdiv_d \
+	fdiv_q \
+	fdiv_s \
+	fence \
+	fence_i \
+	feq_d \
+	feq_q \
+	feq_s \
+	fld \
+	fle_d \
+	fle_q \
+	fle_s \
+	flq \
+	flt_d \
+	flt_q \
+	flt_s \
+	flw \
+	fmadd_d \
+	fmadd_q \
+	fmadd_s \
+	fmax_d \
+	fmax_q \
+	fmax_s \
+	fmin_d \
+	fmin_q \
+	fmin_s \
+	fmsub_d \
+	fmsub_q \
+	fmsub_s \
+	fmul_d \
+	fmul_q \
+	fmul_s \
+	fmv_d_x \
+	fmv_w_x \
+	fmv_x_d \
+	fmv_x_w \
+	fnmadd_d \
+	fnmadd_q \
+	fnmadd_s \
+	fnmsub_d \
+	fnmsub_q \
+	fnmsub_s \
+	fsd \
+	fsgnj_d \
+	fsgnj_q \
+	fsgnjn_d \
+	fsgnjn_q \
+	fsgnjn_s \
+	fsgnj_s \
+	fsgnjx_d \
+	fsgnjx_q \
+	fsgnjx_s \
+	fsq \
+	fsqrt_d \
+	fsqrt_q \
+	fsqrt_s \
+	fsub_d \
+	fsub_q \
+	fsub_s \
+	fsw \
+	jal \
+	jalr \
+	lb \
+	lbu \
+	ld \
+	lh \
+	lhu \
+	lr_d \
+	lr_w \
+	lui \
+	lw \
+	lwu \
+	mret \
+	mul \
+	mulh \
+	mulhsu \
+	mulhu \
+	mulw \
+	or \
+	ori \
+	rem \
+	remu \
+	remuw \
+	remw \
+	sb \
+	sc_d \
+	sc_w \
+	sd \
+	sfence_vma \
+	sh \
+	sll \
+	slli \
+	slliw \
+	sllw \
+	slt \
+	slti \
+	sltiu \
+	sltu \
+	sra \
+	srai \
+	sraiw \
+	sraw \
+	sret \
+	srl \
+	srli \
+	srliw \
+	srlw \
+	sub \
+	subw \
+	sw \
+	wfi \
+	xor \
+	xori \
+
+riscv_gen_srcs = \
+	$(addsuffix .cc,$(riscv_insn_list))
+
+icache_entries := `grep "ICACHE_ENTRIES =" $(src_dir)/riscv/mmu.h | sed 's/.* = \(.*\);/\1/'`
+
+icache.h: mmu.h
+	$(src_dir)/riscv/gen_icache $(icache_entries) > $@.tmp
+	mv $@.tmp $@
+
+insn_list.h: $(src_dir)/riscv/riscv.mk.in
+	for insn in $(foreach insn,$(riscv_insn_list),$(subst .,_,$(insn))) ; do \
+		printf 'DEFINE_INSN(%s)\n' "$${insn}" ; \
+	done > $@.tmp
+	mv $@.tmp $@
+
+$(riscv_gen_srcs): %.cc: insns/%.h insn_template.cc
+	sed 's/NAME/$(subst .cc,,$@)/' $(src_dir)/riscv/insn_template.cc | sed 's/OPCODE/$(call get_opcode,$(src_dir)/riscv/encoding.h,$(subst .cc,,$@))/' > $@
+
+riscv_junk = \
+	$(riscv_gen_srcs) \
diff --git a/tb/riscv-isa-sim/riscv/rocc.cc b/tb/riscv-isa-sim/riscv/rocc.cc
new file mode 100644
index 0000000000000000000000000000000000000000..db03e37c4869e39f5a96808706dac09a3e25b266
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/rocc.cc
@@ -0,0 +1,46 @@
+// See LICENSE for license details.
+
+#include "rocc.h"
+#include "trap.h"
+#include <cstdlib>
+
+#define customX(n) \
+  static reg_t c##n(processor_t* p, insn_t insn, reg_t pc) \
+  { \
+    rocc_t* rocc = static_cast<rocc_t*>(p->get_extension()); \
+    rocc_insn_union_t u; \
+    u.i = insn; \
+    reg_t xs1 = u.r.xs1 ? RS1 : -1; \
+    reg_t xs2 = u.r.xs2 ? RS2 : -1; \
+    reg_t xd = rocc->custom##n(u.r, xs1, xs2); \
+    if (u.r.xd) \
+      WRITE_RD(xd); \
+    return pc+4; \
+  } \
+  \
+  reg_t rocc_t::custom##n(rocc_insn_t insn, reg_t xs1, reg_t xs2) \
+  { \
+    illegal_instruction(); \
+    return 0; \
+  }
+
+customX(0)
+customX(1)
+customX(2)
+customX(3)
+
+std::vector<insn_desc_t> rocc_t::get_instructions()
+{
+  std::vector<insn_desc_t> insns;
+  insns.push_back((insn_desc_t){0x0b, 0x7f, &::illegal_instruction, c0});
+  insns.push_back((insn_desc_t){0x2b, 0x7f, &::illegal_instruction, c1});
+  insns.push_back((insn_desc_t){0x5b, 0x7f, &::illegal_instruction, c2});
+  insns.push_back((insn_desc_t){0x7b, 0x7f, &::illegal_instruction, c3});
+  return insns;
+}
+
+std::vector<disasm_insn_t*> rocc_t::get_disasms()
+{
+  std::vector<disasm_insn_t*> insns;
+  return insns;
+}
diff --git a/tb/riscv-isa-sim/riscv/rocc.h b/tb/riscv-isa-sim/riscv/rocc.h
new file mode 100644
index 0000000000000000000000000000000000000000..63d074d41c084ef58402152a926656e38121815f
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/rocc.h
@@ -0,0 +1,35 @@
+#ifndef _RISCV_ROCC_H
+#define _RISCV_ROCC_H
+
+#include "extension.h"
+
+struct rocc_insn_t
+{
+  unsigned opcode : 7;
+  unsigned rd : 5;
+  unsigned xs2 : 1;
+  unsigned xs1 : 1;
+  unsigned xd : 1;
+  unsigned rs1 : 5;
+  unsigned rs2 : 5;
+  unsigned funct : 7;
+};
+
+union rocc_insn_union_t
+{
+  rocc_insn_t r;
+  insn_t i;
+};
+
+class rocc_t : public extension_t
+{
+ public:
+  virtual reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2);
+  virtual reg_t custom1(rocc_insn_t insn, reg_t xs1, reg_t xs2);
+  virtual reg_t custom2(rocc_insn_t insn, reg_t xs1, reg_t xs2);
+  virtual reg_t custom3(rocc_insn_t insn, reg_t xs1, reg_t xs2);
+  std::vector<insn_desc_t> get_instructions();
+  std::vector<disasm_insn_t*> get_disasms();
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/rom.cc b/tb/riscv-isa-sim/riscv/rom.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b8528621aa673fb299e2b561dd4e148a919e3d84
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/rom.cc
@@ -0,0 +1,19 @@
+#include "devices.h"
+
+rom_device_t::rom_device_t(std::vector<char> data)
+  : data(data)
+{
+}
+
+bool rom_device_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  if (addr + len > data.size())
+    return false;
+  memcpy(bytes, &data[addr], len);
+  return true;
+}
+
+bool rom_device_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  return false;
+}
diff --git a/tb/riscv-isa-sim/riscv/sim.cc b/tb/riscv-isa-sim/riscv/sim.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e82e84e18b1014b4886caf83a02b626e11a27196
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/sim.cc
@@ -0,0 +1,226 @@
+// See LICENSE for license details.
+
+#include "sim.h"
+#include "mmu.h"
+#include "dts.h"
+#include "remote_bitbang.h"
+#include <map>
+#include <iostream>
+#include <sstream>
+#include <climits>
+#include <cstdlib>
+#include <cassert>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+
+volatile bool ctrlc_pressed = false;
+static void handle_signal(int sig)
+{
+  if (ctrlc_pressed)
+    exit(-1);
+  ctrlc_pressed = true;
+  signal(sig, &handle_signal);
+}
+
+sim_t::sim_t(const char* isa, size_t nprocs, bool halted, reg_t start_pc,
+             std::vector<std::pair<reg_t, mem_t*>> mems,
+             const std::vector<std::string>& args,
+             std::vector<int> const hartids, unsigned progsize,
+             unsigned max_bus_master_bits, bool require_authentication)
+  : htif_t(args), mems(mems), procs(std::max(nprocs, size_t(1))),
+    start_pc(start_pc), current_step(0), current_proc(0), debug(false),
+    histogram_enabled(false), dtb_enabled(true), remote_bitbang(NULL),
+    debug_module(this, progsize, max_bus_master_bits, require_authentication)
+{
+  signal(SIGINT, &handle_signal);
+
+  for (auto& x : mems)
+    bus.add_device(x.first, x.second);
+
+  debug_module.add_device(&bus);
+
+  debug_mmu = new mmu_t(this, NULL);
+
+  if (hartids.size() == 0) {
+    for (size_t i = 0; i < procs.size(); i++) {
+      procs[i] = new processor_t(isa, this, i, halted);
+    }
+  }
+  else {
+    if (hartids.size() != procs.size()) {
+      std::cerr << "Number of specified hartids doesn't match number of processors" << strerror(errno) << std::endl;
+      exit(1);
+    }
+    for (size_t i = 0; i < procs.size(); i++) {
+      procs[i] = new processor_t(isa, this, hartids[i], halted);
+    }
+  }
+
+  clint.reset(new clint_t(procs));
+  bus.add_device(CLINT_BASE, clint.get());
+
+  uart.reset(new uart_t());
+  bus.add_device(UART_BASE, uart.get());
+
+  dump.reset(new dump_t());
+  bus.add_device(DUMP_BASE, dump.get());
+}
+
+sim_t::~sim_t()
+{
+  for (size_t i = 0; i < procs.size(); i++)
+    delete procs[i];
+  delete debug_mmu;
+}
+
+void sim_thread_main(void* arg)
+{
+  ((sim_t*)arg)->main();
+}
+
+void sim_t::main()
+{
+  if (!debug && log)
+    set_procs_debug(true);
+
+  while (!done())
+  {
+    if (debug || ctrlc_pressed)
+      interactive();
+    else
+      step(INTERLEAVE);
+    if (remote_bitbang) {
+      remote_bitbang->tick();
+    }
+  }
+}
+
+int sim_t::run()
+{
+  host = context_t::current();
+  target.init(sim_thread_main, this);
+  return htif_t::run();
+}
+
+void sim_t::step(size_t n)
+{
+  for (size_t i = 0, steps = 0; i < n; i += steps)
+  {
+    steps = std::min(n - i, INTERLEAVE - current_step);
+    procs[current_proc]->step(steps);
+
+    current_step += steps;
+    if (current_step == INTERLEAVE)
+    {
+      current_step = 0;
+      procs[current_proc]->get_mmu()->yield_load_reservation();
+      if (++current_proc == procs.size()) {
+        current_proc = 0;
+        clint->increment(INTERLEAVE / INSNS_PER_RTC_TICK);
+      }
+
+      host->switch_to();
+    }
+  }
+}
+
+void sim_t::set_debug(bool value)
+{
+  debug = value;
+}
+
+void sim_t::set_log(bool value)
+{
+  log = value;
+}
+
+void sim_t::set_histogram(bool value)
+{
+  histogram_enabled = value;
+  for (size_t i = 0; i < procs.size(); i++) {
+    procs[i]->set_histogram(histogram_enabled);
+  }
+}
+
+void sim_t::set_procs_debug(bool value)
+{
+  for (size_t i=0; i< procs.size(); i++)
+    procs[i]->set_debug(value);
+}
+
+bool sim_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  if (addr + len < addr)
+    return false;
+  return bus.load(addr, len, bytes);
+}
+
+bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  if (addr + len < addr)
+    return false;
+  return bus.store(addr, len, bytes);
+}
+
+void sim_t::make_dtb()
+{
+
+  start_pc = start_pc == reg_t(-1) ? get_entry_point() : start_pc;
+
+  #include "bootrom.h"
+
+  std::vector<char> rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec));
+
+  // dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, procs, mems);
+  // std::string dtb = dts_compile(dts);
+
+  // rom.insert(rom.end(), dtb.begin(), dtb.end());
+  const int align = 0x1000;
+  rom.resize((rom.size() + align - 1) / align * align);
+
+  boot_rom.reset(new rom_device_t(rom));
+  bus.add_device(DEFAULT_RSTVEC, boot_rom.get());
+}
+
+char* sim_t::addr_to_mem(reg_t addr) {
+  auto desc = bus.find_device(addr);
+  if (auto mem = dynamic_cast<mem_t*>(desc.second))
+    if (addr - desc.first < mem->size())
+      return mem->contents() + (addr - desc.first);
+  return NULL;
+}
+
+// htif
+
+void sim_t::reset()
+{
+  if (dtb_enabled)
+    make_dtb();
+}
+
+void sim_t::idle()
+{
+  target.switch_to();
+}
+
+void sim_t::read_chunk(addr_t taddr, size_t len, void* dst)
+{
+  assert(len == 8);
+  auto data = debug_mmu->load_uint64(taddr);
+  memcpy(dst, &data, sizeof data);
+}
+
+void sim_t::write_chunk(addr_t taddr, size_t len, const void* src)
+{
+  assert(len == 8);
+  uint64_t data;
+  memcpy(&data, src, sizeof data);
+  debug_mmu->store_uint64(taddr, data);
+}
+
+void sim_t::proc_reset(unsigned id)
+{
+  debug_module.proc_reset(id);
+}
diff --git a/tb/riscv-isa-sim/riscv/sim.h b/tb/riscv-isa-sim/riscv/sim.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ee7ef309457275b126e8da5063455ce465b17a4
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/sim.h
@@ -0,0 +1,129 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_SIM_H
+#define _RISCV_SIM_H
+
+#include "processor.h"
+#include "devices.h"
+#include "debug_module.h"
+#include "simif.h"
+#include <fesvr/htif.h>
+#include <fesvr/context.h>
+#include <vector>
+#include <string>
+#include <memory>
+
+class mmu_t;
+class remote_bitbang_t;
+
+// this class encapsulates the processors and memory in a RISC-V machine.
+class sim_t : public htif_t, public simif_t
+{
+public:
+  sim_t(const char* isa, size_t _nprocs,  bool halted, reg_t start_pc,
+        std::vector<std::pair<reg_t, mem_t*>> mems,
+        const std::vector<std::string>& args, const std::vector<int> hartids,
+        unsigned progsize, unsigned max_bus_master_bits, bool require_authentication);
+  ~sim_t();
+
+  // run the simulation to completion
+  int run();
+  void set_debug(bool value);
+  void set_log(bool value);
+  void set_histogram(bool value);
+  void set_procs_debug(bool value);
+  void set_dtb_enabled(bool value) {
+    this->dtb_enabled = value;
+  }
+  void set_remote_bitbang(remote_bitbang_t* remote_bitbang) {
+    this->remote_bitbang = remote_bitbang;
+  }
+  const char* get_dts() { if (dts.empty()) reset(); return dts.c_str(); }
+  processor_t* get_core(size_t i) { return procs.at(i); }
+  unsigned nprocs() const { return procs.size(); }
+
+  // Callback for processors to let the simulation know they were reset.
+  void proc_reset(unsigned id);
+
+private:
+  std::vector<std::pair<reg_t, mem_t*>> mems;
+  mmu_t* debug_mmu;  // debug port into main memory
+  std::vector<processor_t*> procs;
+  reg_t start_pc;
+  std::string dts;
+  std::unique_ptr<rom_device_t> boot_rom;
+  std::unique_ptr<clint_t> clint;
+  std::unique_ptr<dump_t> dump;
+  std::unique_ptr<uart_t> uart;
+  bus_t bus;
+
+  processor_t* get_core(const std::string& i);
+  void step(size_t n); // step through simulation
+  static const size_t INTERLEAVE = 5000;
+  static const size_t INSNS_PER_RTC_TICK = 100; // 10 MHz clock for 1 BIPS core
+  static const size_t CPU_HZ = 1000000000; // 1GHz CPU
+  size_t current_step;
+  size_t current_proc;
+  bool debug;
+  bool log;
+  bool histogram_enabled; // provide a histogram of PCs
+  bool dtb_enabled;
+  remote_bitbang_t* remote_bitbang;
+
+  // memory-mapped I/O routines
+  char* addr_to_mem(reg_t addr);
+  bool mmio_load(reg_t addr, size_t len, uint8_t* bytes);
+  bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes);
+  void make_dtb();
+
+  // presents a prompt for introspection into the simulation
+  void interactive();
+
+  // functions that help implement interactive()
+  void interactive_help(const std::string& cmd, const std::vector<std::string>& args);
+  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_reg(const std::string& cmd, const std::vector<std::string>& args);
+  void interactive_freg(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_pc(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, bool noisy);
+  void interactive_until_silent(const std::string& cmd, const std::vector<std::string>& args);
+  void interactive_until_noisy(const std::string& cmd, const std::vector<std::string>& args);
+  reg_t get_reg(const std::vector<std::string>& args);
+  freg_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);
+
+  friend class processor_t;
+  friend class mmu_t;
+  friend class debug_module_t;
+
+  // htif
+  friend void sim_thread_main(void*);
+  void main();
+
+  context_t* host;
+  context_t target;
+  void reset();
+  void idle();
+  void read_chunk(addr_t taddr, size_t len, void* dst);
+  void write_chunk(addr_t taddr, size_t len, const void* src);
+  size_t chunk_align() { return 8; }
+  size_t chunk_max_size() { return 8; }
+
+public:
+  // Initialize this after procs, because in debug_module_t::reset() we
+  // enumerate processors, which segfaults if procs hasn't been initialized
+  // yet.
+  debug_module_t debug_module;
+};
+
+extern volatile bool ctrlc_pressed;
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/simif.h b/tb/riscv-isa-sim/riscv/simif.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d982b3396c3edb1f0404138eaff0c03febb8e19
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/simif.h
@@ -0,0 +1,21 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_SIMIF_H
+#define _RISCV_SIMIF_H
+
+#include "decode.h"
+
+// this is the interface to the simulator used by the processors and memory
+class simif_t
+{
+public:
+  // should return NULL for MMIO addresses
+  virtual char* addr_to_mem(reg_t addr) = 0;
+  // used for MMIO addresses
+  virtual bool mmio_load(reg_t addr, size_t len, uint8_t* bytes) = 0;
+  virtual bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
+  // Callback for processors to let the simulation know they were reset.
+  virtual void proc_reset(unsigned id) = 0;
+};
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/tracer.h b/tb/riscv-isa-sim/riscv/tracer.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f1bc7841af593bc720e0ce36fc2629899cb4210
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/tracer.h
@@ -0,0 +1,11 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_TRACER_H
+#define _RISCV_TRACER_H
+
+#include "processor.h"
+
+static inline void trace_opcode(processor_t* p, insn_bits_t opc, insn_t insn) {
+}
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/trap.cc b/tb/riscv-isa-sim/riscv/trap.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4ac2f1f717423ca0ba133840b54abfcfb37c0a3e
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/trap.cc
@@ -0,0 +1,12 @@
+// See LICENSE for license details.
+
+#include "trap.h"
+#include "processor.h"
+#include <cstdio>
+
+const char* trap_t::name()
+{
+  const char* fmt = uint8_t(which) == which ? "trap #%u" : "interrupt #%u";
+  sprintf(_name, fmt, uint8_t(which));
+  return _name;
+}
diff --git a/tb/riscv-isa-sim/riscv/trap.h b/tb/riscv-isa-sim/riscv/trap.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5b8a5080abe6fe34e21071ddfd219b52aeae11c
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/trap.h
@@ -0,0 +1,63 @@
+// See LICENSE for license details.
+
+#ifndef _RISCV_TRAP_H
+#define _RISCV_TRAP_H
+
+#include "decode.h"
+#include <stdlib.h>
+
+struct state_t;
+
+class trap_t
+{
+ public:
+  trap_t(reg_t which) : which(which) {}
+  virtual const char* name();
+  virtual bool has_tval() { return false; }
+  virtual reg_t get_tval() { return 0; }
+  reg_t cause() { return which; }
+ private:
+  char _name[16];
+  reg_t which;
+};
+
+class mem_trap_t : public trap_t
+{
+ public:
+  mem_trap_t(reg_t which, reg_t tval)
+    : trap_t(which), tval(tval) {}
+  bool has_tval() override { return true; }
+  reg_t get_tval() override { return tval; }
+ private:
+  reg_t tval;
+};
+
+#define DECLARE_TRAP(n, x) class trap_##x : public trap_t { \
+ public: \
+  trap_##x() : trap_t(n) {} \
+  const char* name() { return "trap_"#x; } \
+};
+
+#define DECLARE_MEM_TRAP(n, x) class trap_##x : public mem_trap_t { \
+ public: \
+  trap_##x(reg_t tval) : mem_trap_t(n, tval) {} \
+  const char* name() { return "trap_"#x; } \
+};
+
+DECLARE_MEM_TRAP(CAUSE_MISALIGNED_FETCH, instruction_address_misaligned)
+DECLARE_MEM_TRAP(CAUSE_FETCH_ACCESS, instruction_access_fault)
+DECLARE_MEM_TRAP(CAUSE_ILLEGAL_INSTRUCTION, illegal_instruction)
+DECLARE_MEM_TRAP(CAUSE_BREAKPOINT, breakpoint)
+DECLARE_MEM_TRAP(CAUSE_MISALIGNED_LOAD, load_address_misaligned)
+DECLARE_MEM_TRAP(CAUSE_MISALIGNED_STORE, store_address_misaligned)
+DECLARE_MEM_TRAP(CAUSE_LOAD_ACCESS, load_access_fault)
+DECLARE_MEM_TRAP(CAUSE_STORE_ACCESS, store_access_fault)
+DECLARE_TRAP(CAUSE_USER_ECALL, user_ecall)
+DECLARE_TRAP(CAUSE_SUPERVISOR_ECALL, supervisor_ecall)
+DECLARE_TRAP(CAUSE_HYPERVISOR_ECALL, hypervisor_ecall)
+DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall)
+DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault)
+DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault)
+DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault)
+
+#endif
diff --git a/tb/riscv-isa-sim/riscv/uart.cc b/tb/riscv-isa-sim/riscv/uart.cc
new file mode 100644
index 0000000000000000000000000000000000000000..91e2e69911ccc81ea1b30d3d8352b28992610ae2
--- /dev/null
+++ b/tb/riscv-isa-sim/riscv/uart.cc
@@ -0,0 +1,142 @@
+#include "devices.h"
+#include "processor.h"
+
+#define RBR  0
+#define THR  0
+#define IER  1
+#define IIR  2
+#define FCR  2
+#define LCR  3
+#define MCR  4
+#define LSR  5
+#define MSR  6
+#define SCR  7
+#define DLL  0
+#define DLM  1
+
+#define THRE 5 // transmit holding register empty
+#define TEMT 6 // transmit holding register empty
+
+uart_t::uart_t()
+{
+  dll = 0;
+  dlm = 0;
+  ier = 0;
+  lcr = 0;
+  mcr = 0;
+  lsr = 0;
+  msr = 0;
+  scr = 0;
+}
+
+  // set {char}  0x10000004 = 0x00
+  // set {char}  0x1000000C = 0x80
+  // set {char}  0x10000000 = 0x1B
+  // set {char}  0x10000004 = 0x00
+  // set {char}  0x1000000C = 0x03
+  // set {char}  0x10000008 = 0xC7
+bool uart_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  // we do not support unaligned stores
+  if ((addr & 0x3) != 0) {
+    return false;
+  }
+
+  switch ((addr >> 0x2) & 0x7) {
+    case THR:
+              // access DLL
+              if (lcr & 0x80) {
+                bytes[0] = dll;
+              } else {
+                // TODO(zarubaf)
+                // printf("%c", bytes[0]);
+                bytes[0] = 0;
+              }
+              break;
+    case IER:
+              // access DLM
+              if (lcr & 0x80) {
+                bytes[0] = dlm;
+              } else {
+                bytes[0] = ier;
+              }
+              break;
+    case IIR:
+              if (fifo_enabled) {
+                bytes[0] = 0xC0;
+              } else {
+                bytes[0] = 0x00;
+              }
+              break;
+    case LCR:
+              bytes[0] = lcr;
+              break;
+    case MCR:
+              bytes[0] = mcr;
+              break;
+    case LSR:
+              bytes[0] = lsr | (1 << THRE) | (1 << TEMT);
+              break;
+    case MSR:
+              bytes[0] = msr;
+              break;
+    case SCR:
+              bytes[0] = scr;
+              break;
+  }
+
+  return true;
+}
+
+bool uart_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+
+  // we do not support unaligned stores
+  if ((addr & 0x3) != 0) {
+    return false;
+  }
+
+  switch ((addr >> 0x2) & 0x7) {
+    case THR:
+              // access DLL
+              if (lcr & 0x80) {
+                dll = bytes[0];
+              } else {
+                printf("%c", bytes[0]);
+              }
+              break;
+    case IER:
+              // access DLM
+              if (lcr & 0x80) {
+                dlm = bytes[0];
+              } else {
+                ier = bytes[0] & 0xF;
+              }
+              break;
+    case FCR:
+              if (bytes[0] & 0x1) {
+                fifo_enabled = true;
+              } else {
+                fifo_enabled = false;
+              }
+              break;
+    case LCR:
+              lcr = bytes[0];
+              break;
+    case MCR:
+              mcr = bytes[0] & 0x1F;
+              break;
+    case LSR:
+              lsr = bytes[0];
+              break;
+    case MSR:
+              msr = bytes[0];
+              break;
+    case SCR:
+              scr = bytes[0];
+              break;
+  }
+
+  return true;
+}
+
diff --git a/tb/riscv-isa-sim/scripts/config.guess b/tb/riscv-isa-sim/scripts/config.guess
new file mode 100755
index 0000000000000000000000000000000000000000..f32079abda668e5fc8f8de6f226e7b26384e8a03
--- /dev/null
+++ b/tb/riscv-isa-sim/scripts/config.guess
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[456])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	case ${UNAME_MACHINE} in
+	    pc98)
+		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:windows32*:*)
+    	# uname -m includes "-pc" on this system.
+    	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:[3456]*)
+    	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    EM64T | authenticamd)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-gnu
+	else
+	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit ;;
+    crisv32:Linux:*:*)
+	echo crisv32-axis-linux-gnu
+	exit ;;
+    frv:Linux:*:*)
+    	echo frv-unknown-linux-gnu
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^CPU/{
+		s: ::g
+		p
+	    }'`"
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+	;;
+    or32:Linux:*:*)
+	echo or32-unknown-linux-gnu
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-gnu
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-gnu
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux
+	exit ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-gnu
+	exit ;;
+    x86_64:Linux:*:*)
+	echo x86_64-unknown-linux-gnu
+	exit ;;
+    xtensa*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+	#ifdef __dietlibc__
+	LIBC=dietlibc
+	#endif
+EOF
+	eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+	    /^LIBC/{
+		s: ::g
+		p
+	    }'`"
+	test x"${LIBC}" != x && {
+		echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+		exit
+	}
+	test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	case $UNAME_PROCESSOR in
+	    unknown) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+	{ echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    c34*)
+	echo c34-convex-bsd
+	exit ;;
+    c38*)
+	echo c38-convex-bsd
+	exit ;;
+    c4*)
+	echo c4-convex-bsd
+	exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tb/riscv-isa-sim/scripts/config.sub b/tb/riscv-isa-sim/scripts/config.sub
new file mode 100755
index 0000000000000000000000000000000000000000..9613107198c2c0b4875d89867d9b948b6fd8a45e
--- /dev/null
+++ b/tb/riscv-isa-sim/scripts/config.sub
@@ -0,0 +1,1663 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+#   Free Software Foundation, Inc.
+
+timestamp='2009-09-02'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+	| bfin \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| mt \
+	| msp430 \
+	| nios | nios2 \
+	| ns16k | ns32k \
+	| or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	# cbatten - Add maven target
+	maven)
+		basic_machine=mipsmavenel-ucb
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nios-* | nios2-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+    	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tile*)
+		basic_machine=tile-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+        -os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+        -tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+        mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+    	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tb/riscv-isa-sim/scripts/install.sh b/tb/riscv-isa-sim/scripts/install.sh
new file mode 100755
index 0000000000000000000000000000000000000000..89fc9b098b8c5ab20ff24069b7233ab411aec440
--- /dev/null
+++ b/tb/riscv-isa-sim/scripts/install.sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/tb/riscv-isa-sim/scripts/mk-install-dirs.sh b/tb/riscv-isa-sim/scripts/mk-install-dirs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..644b5f728f6e15c6434182312c0ba9ed52c924ca
--- /dev/null
+++ b/tb/riscv-isa-sim/scripts/mk-install-dirs.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1 2003/09/09 22:24:03 mhampton Exp $
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp" 1>&2
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+          errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/tb/riscv-isa-sim/scripts/vcs-version.sh b/tb/riscv-isa-sim/scripts/vcs-version.sh
new file mode 100755
index 0000000000000000000000000000000000000000..31fae86951417532716468541d345cd366cc2b0e
--- /dev/null
+++ b/tb/riscv-isa-sim/scripts/vcs-version.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+#=========================================================================
+# vcs-version.sh [options] [src-dir]
+#=========================================================================
+#
+#  -h  Display this message
+#  -v  Verbose mode
+#
+# This script will create a version string by querying a version control
+# system. The string is appropriate for use in installations and
+# distributions. Currently this script assumes we are using git as our
+# version control system but it would be possible to check and see if we
+# are using an alternative version control system and create a version
+# string appropriately.
+# 
+# The script uses git describe plus a few other git commands to create a
+# version strings in the following format:
+#
+#  X.Y[-Z-gN][-dirty]
+#
+# where X is the major release, Y is the minor release, Z is the number
+# of commits since the X.Y release, N is an eight digit abbreviated SHA
+# hash of the most recent commit and the dirty suffix is appended when
+# the working directory used to create the installation or distribution
+# is not a pristine checkout. Here are some example version strings:
+#
+#  0.0                    : initial import
+#  0.0-3-g99ef6933        : 3rd commit since initial import (N=99ef6933)
+#  1.0                    : release 1.0
+#  1.1-12-g3487ab12       : 12th commit since release 1.1 (N=3487ab12)
+#  1.1-12-g3487ab12-dirty : 12th commit since release 1.1 (N=3487ab12)
+#
+# The last example is from a dirty working directory. To find the last
+# release, the script looks for the last tag (does not need to be an
+# annotated tag, but probably should be) which matches the format rel-*.
+# If there is no such tag in the history, then the script uses 0.0 as
+# the release number and counts the total number of commits since the
+# original import for the commit count.
+#
+# If the current directory is not within the working directory, then the
+# path to the source directory should be supplied on the command line.
+#
+# Author : Christopher Batten
+# Date   : August 5, 2009
+
+set -e
+
+#-------------------------------------------------------------------------
+# Command line parsing
+#-------------------------------------------------------------------------
+
+if ( test "$1" = "-h" ); then
+  echo ""
+  sed -n '3p' $0 | sed -e 's/#//'
+  sed -n '5,/^$/p' $0 | sed -e 's/#//'
+  exit 1
+fi
+
+# Source directory command line option
+
+src_dir="."
+if ( test -n "$1" ); then
+  src_dir="$1"
+fi
+
+#-------------------------------------------------------------------------
+# Verify source directory
+#-------------------------------------------------------------------------
+# If the source directory is not a git working directory output a
+# question mark. A distribution will not be in a working directory, but
+# the build system should be structured such that this script is not
+# executed (and instead the version information should probably come
+# from configure). If the user does not specify a source directory use
+# the current directory.
+
+if !( git rev-parse --is-inside-work-tree &> /dev/null ); then
+  echo "?"
+  exit 1;
+fi
+
+top_dir=`git rev-parse --show-cdup`
+cd ./${top_dir}
+
+#-------------------------------------------------------------------------
+# Create the version string
+#-------------------------------------------------------------------------
+# See if we can do a describe based on a tag and if not use a default
+# release number of 0.0 so that we always get canonical version number
+
+if ( git describe --tags --match "rel-*" &> /dev/null ); then
+  ver_str=`git describe --tags --match "rel-*" | sed 's/rel-//'`
+else
+  ver_num="0.0"
+  ver_commits=`git rev-list --all | wc -l | tr -d " "`
+  ver_sha=`git describe --tags --match "rel-*" --always`
+  ver_str="${ver_num}-${ver_commits}-g${ver_sha}"
+fi
+
+# Add a dirty suffix if working directory is dirty
+
+if !( git diff --quiet ); then
+  ver_str="${ver_str}-dirty"
+else
+  untracked=`git ls-files --directory --exclude-standard --others -t`
+  if ( test -n "${untracked}" ); then
+    ver_str="${ver_str}-dirty"
+  fi  
+fi
+
+# Output the final version string
+
+echo "${ver_str}"
+
+# Final exit status
+
+exit 0;
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_add.c b/tb/riscv-isa-sim/softfloat/f128_add.c
new file mode 100644
index 0000000000000000000000000000000000000000..6568ab6f3476b2c76ff5820b4675c2b84b20c056
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_add.c
@@ -0,0 +1,78 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t f128_add( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool signA;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
+    float128_t
+        (*magsFuncPtr)(
+            uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
+#endif
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    signA = signF128UI64( uiA64 );
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    signB = signF128UI64( uiB64 );
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+    if ( signA == signB ) {
+        return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
+    } else {
+        return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
+    }
+#else
+    magsFuncPtr =
+        (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128;
+    return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_classify.c b/tb/riscv-isa-sim/softfloat/f128_classify.c
new file mode 100755
index 0000000000000000000000000000000000000000..1092a9b51f3a739e3bc2b049d1894e230bb727c8
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_classify.c
@@ -0,0 +1,37 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast16_t f128_classify( float128_t a )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+
+    uint_fast16_t infOrNaN = expF128UI64( uiA64 ) == 0x7FFF;
+    uint_fast16_t subnormalOrZero = expF128UI64( uiA64 ) == 0;
+    bool sign = signF128UI64( uiA64 );
+    bool fracZero = fracF128UI64( uiA64 ) == 0 && uiA0 == 0;
+    bool isNaN = isNaNF128UI( uiA64, uiA0 );
+    bool isSNaN = softfloat_isSigNaNF128UI( uiA64, uiA0 );
+
+    return
+        (  sign && infOrNaN && fracZero )          << 0 |
+        (  sign && !infOrNaN && !subnormalOrZero ) << 1 |
+        (  sign && subnormalOrZero && !fracZero )  << 2 |
+        (  sign && subnormalOrZero && fracZero )   << 3 |
+        ( !sign && infOrNaN && fracZero )          << 7 |
+        ( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
+        ( !sign && subnormalOrZero && !fracZero )  << 5 |
+        ( !sign && subnormalOrZero && fracZero )   << 4 |
+        ( isNaN &&  isSNaN )                       << 8 |
+        ( isNaN && !isSNaN )                       << 9;
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_div.c b/tb/riscv-isa-sim/softfloat/f128_div.c
new file mode 100644
index 0000000000000000000000000000000000000000..9384e7562ea55968abc606bf620401371db8abf5
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_div.c
@@ -0,0 +1,199 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f128_div( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool signA;
+    int_fast32_t expA;
+    struct uint128 sigA;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signB;
+    int_fast32_t expB;
+    struct uint128 sigB;
+    bool signZ;
+    struct exp32_sig128 normExpSig;
+    int_fast32_t expZ;
+    struct uint128 rem;
+    uint_fast32_t recip32;
+    int ix;
+    uint_fast64_t q64;
+    uint_fast32_t q;
+    struct uint128 term;
+    uint_fast32_t qs[3];
+    uint_fast64_t sigZExtra;
+    struct uint128 sigZ, uiZ;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    signA = signF128UI64( uiA64 );
+    expA  = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    signB = signF128UI64( uiB64 );
+    expB  = expF128UI64( uiB64 );
+    sigB.v64 = fracF128UI64( uiB64 );
+    sigB.v0  = uiB0;
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FFF ) {
+        if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
+        if ( expB == 0x7FFF ) {
+            if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
+            goto invalid;
+        }
+        goto infinity;
+    }
+    if ( expB == 0x7FFF ) {
+        if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
+        goto zero;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! (sigB.v64 | sigB.v0) ) {
+            if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid;
+            softfloat_raiseFlags( softfloat_flag_infinite );
+            goto infinity;
+        }
+        normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! (sigA.v64 | sigA.v0) ) goto zero;
+        normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA - expB + 0x3FFE;
+    sigA.v64 |= UINT64_C( 0x0001000000000000 );
+    sigB.v64 |= UINT64_C( 0x0001000000000000 );
+    rem = sigA;
+    if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) {
+        --expZ;
+        rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 );
+    }
+    recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
+    ix = 3;
+    for (;;) {
+        q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
+        q = (q64 + 0x80000000)>>32;
+        --ix;
+        if ( ix < 0 ) break;
+        rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
+        term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
+        rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
+        if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
+            --q;
+            rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+        }
+        qs[ix] = q;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ((q + 1) & 7) < 2 ) {
+        rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
+        term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
+        rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
+        if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
+            --q;
+            rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+        } else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) {
+            ++q;
+            rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+        }
+        if ( rem.v64 | rem.v0 ) q |= 1;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sigZExtra = (uint64_t) ((uint_fast64_t) q<<60);
+    term = softfloat_shortShiftLeft128( 0, qs[1], 54 );
+    sigZ =
+        softfloat_add128(
+            (uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4),
+            term.v64, term.v0
+        );
+    return
+        softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infinity:
+    uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
+    goto uiZ0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ.v64 = packToF128UI64( signZ, 0, 0 );
+ uiZ0:
+    uiZ.v0 = 0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_eq.c b/tb/riscv-isa-sim/softfloat/f128_eq.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0e1ad28687745bbba02944c780fa85bbb0e3bb9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_eq.c
@@ -0,0 +1,73 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f128_eq( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
+        if (
+               softfloat_isSigNaNF128UI( uiA64, uiA0 )
+            || softfloat_isSigNaNF128UI( uiB64, uiB0 )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    return
+           (uiA0 == uiB0)
+        && (   (uiA64 == uiB64)
+            || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
+           );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_eq_signaling.c b/tb/riscv-isa-sim/softfloat/f128_eq_signaling.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd37b979d22ec7927663bdf4002aa13f582a4b29
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_eq_signaling.c
@@ -0,0 +1,67 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f128_eq_signaling( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    return
+           (uiA0 == uiB0)
+        && (   (uiA64 == uiB64)
+            || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
+           );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_isSignalingNaN.c b/tb/riscv-isa-sim/softfloat/f128_isSignalingNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..fced58e50390c07a736b5c5f3888bffeba61f316
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_isSignalingNaN.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f128_isSignalingNaN( float128_t a )
+{
+    union ui128_f128 uA;
+
+    uA.f = a;
+    return softfloat_isSigNaNF128UI( uA.ui.v64, uA.ui.v0 );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_le.c b/tb/riscv-isa-sim/softfloat/f128_le.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b0aa23445784301b23a0c863620b8b6c1cbfc69
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_le.c
@@ -0,0 +1,72 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f128_le( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF128UI64( uiA64 );
+    signB = signF128UI64( uiB64 );
+    return
+        (signA != signB)
+            ? signA
+                  || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                            | uiA0 | uiB0)
+            : ((uiA64 == uiB64) && (uiA0 == uiB0))
+                  || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_le_quiet.c b/tb/riscv-isa-sim/softfloat/f128_le_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..3b44038859484d5ad868ef079855888e58b58690
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_le_quiet.c
@@ -0,0 +1,78 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f128_le_quiet( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
+        if (
+               softfloat_isSigNaNF128UI( uiA64, uiA0 )
+            || softfloat_isSigNaNF128UI( uiB64, uiB0 )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF128UI64( uiA64 );
+    signB = signF128UI64( uiB64 );
+    return
+        (signA != signB)
+            ? signA
+                  || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                            | uiA0 | uiB0)
+            : ((uiA64 == uiB64) && (uiA0 == uiB0))
+                  || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_lt.c b/tb/riscv-isa-sim/softfloat/f128_lt.c
new file mode 100644
index 0000000000000000000000000000000000000000..a28f95b74181176fb312fa75685e65d8c87f25ca
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_lt.c
@@ -0,0 +1,72 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f128_lt( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF128UI64( uiA64 );
+    signB = signF128UI64( uiB64 );
+    return
+        (signA != signB)
+            ? signA
+                  && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                          | uiA0 | uiB0)
+            : ((uiA64 != uiB64) || (uiA0 != uiB0))
+                  && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_lt_quiet.c b/tb/riscv-isa-sim/softfloat/f128_lt_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..20146ee4ba73fedc0385d5379d11ea8a27ed9800
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_lt_quiet.c
@@ -0,0 +1,78 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f128_lt_quiet( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
+        if (
+               softfloat_isSigNaNF128UI( uiA64, uiA0 )
+            || softfloat_isSigNaNF128UI( uiB64, uiB0 )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF128UI64( uiA64 );
+    signB = signF128UI64( uiB64 );
+    return
+        (signA != signB)
+            ? signA
+                  && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                          | uiA0 | uiB0)
+            : ((uiA64 != uiB64) || (uiA0 != uiB0))
+                  && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_mul.c b/tb/riscv-isa-sim/softfloat/f128_mul.c
new file mode 100644
index 0000000000000000000000000000000000000000..1871613954a1b71decdd1c228ba2bd963ebb0bea
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_mul.c
@@ -0,0 +1,163 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f128_mul( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool signA;
+    int_fast32_t expA;
+    struct uint128 sigA;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signB;
+    int_fast32_t expB;
+    struct uint128 sigB;
+    bool signZ;
+    uint_fast64_t magBits;
+    struct exp32_sig128 normExpSig;
+    int_fast32_t expZ;
+    uint64_t sig256Z[4];
+    uint_fast64_t sigZExtra;
+    struct uint128 sigZ;
+    struct uint128_extra sig128Extra;
+    struct uint128 uiZ;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    signA = signF128UI64( uiA64 );
+    expA  = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    signB = signF128UI64( uiB64 );
+    expB  = expF128UI64( uiB64 );
+    sigB.v64 = fracF128UI64( uiB64 );
+    sigB.v0  = uiB0;
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FFF ) {
+        if (
+            (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
+        ) {
+            goto propagateNaN;
+        }
+        magBits = expB | sigB.v64 | sigB.v0;
+        goto infArg;
+    }
+    if ( expB == 0x7FFF ) {
+        if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
+        magBits = expA | sigA.v64 | sigA.v0;
+        goto infArg;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! (sigA.v64 | sigA.v0) ) goto zero;
+        normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! (sigB.v64 | sigB.v0) ) goto zero;
+        normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0x4000;
+    sigA.v64 |= UINT64_C( 0x0001000000000000 );
+    sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 );
+    softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
+    sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0);
+    sigZ =
+        softfloat_add128(
+            sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )],
+            sigA.v64, sigA.v0
+        );
+    if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) {
+        ++expZ;
+        sig128Extra =
+            softfloat_shortShiftRightJam128Extra(
+                sigZ.v64, sigZ.v0, sigZExtra, 1 );
+        sigZ = sig128Extra.v;
+        sigZExtra = sig128Extra.extra;
+    }
+    return
+        softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infArg:
+    if ( ! magBits ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        uiZ.v64 = defaultNaNF128UI64;
+        uiZ.v0  = defaultNaNF128UI0;
+        goto uiZ;
+    }
+    uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
+    goto uiZ0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ.v64 = packToF128UI64( signZ, 0, 0 );
+ uiZ0:
+    uiZ.v0 = 0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_mulAdd.c b/tb/riscv-isa-sim/softfloat/f128_mulAdd.c
new file mode 100644
index 0000000000000000000000000000000000000000..b2e2142fa8ace45fba0a1b40c95a0ae9b486a7f1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_mulAdd.c
@@ -0,0 +1,63 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t f128_mulAdd( float128_t a, float128_t b, float128_t c )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    union ui128_f128 uC;
+    uint_fast64_t uiC64, uiC0;
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    uC.f = c;
+    uiC64 = uC.ui.v64;
+    uiC0  = uC.ui.v0;
+    return softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_rem.c b/tb/riscv-isa-sim/softfloat/f128_rem.c
new file mode 100644
index 0000000000000000000000000000000000000000..555d71eb7a7cb6ef04fa7b5b320be83578f0ec60
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_rem.c
@@ -0,0 +1,190 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f128_rem( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool signA;
+    int_fast32_t expA;
+    struct uint128 sigA;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    int_fast32_t expB;
+    struct uint128 sigB;
+    struct exp32_sig128 normExpSig;
+    struct uint128 rem;
+    int_fast32_t expDiff;
+    uint_fast32_t q, recip32;
+    uint_fast64_t q64;
+    struct uint128 term, altRem, meanRem;
+    bool signRem;
+    struct uint128 uiZ;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    signA = signF128UI64( uiA64 );
+    expA  = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    expB  = expF128UI64( uiB64 );
+    sigB.v64 = fracF128UI64( uiB64 );
+    sigB.v0  = uiB0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FFF ) {
+        if (
+            (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
+        ) {
+            goto propagateNaN;
+        }
+        goto invalid;
+    }
+    if ( expB == 0x7FFF ) {
+        if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! (sigB.v64 | sigB.v0) ) goto invalid;
+        normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! (sigA.v64 | sigA.v0) ) return a;
+        normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sigA.v64 |= UINT64_C( 0x0001000000000000 );
+    sigB.v64 |= UINT64_C( 0x0001000000000000 );
+    rem = sigA;
+    expDiff = expA - expB;
+    if ( expDiff < 1 ) {
+        if ( expDiff < -1 ) return a;
+        if ( expDiff ) {
+            --expB;
+            sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 );
+            q = 0;
+        } else {
+            q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 );
+            if ( q ) {
+                rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+            }
+        }
+    } else {
+        recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
+        expDiff -= 30;
+        for (;;) {
+            q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
+            if ( expDiff < 0 ) break;
+            q = (q64 + 0x80000000)>>32;
+            rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
+            term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
+            rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
+            if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
+                rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+            }
+            expDiff -= 29;
+        }
+        /*--------------------------------------------------------------------
+        | (`expDiff' cannot be less than -29 here.)
+        *--------------------------------------------------------------------*/
+        q = (uint32_t) (q64>>32)>>(~expDiff & 31);
+        rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
+        term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
+        rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
+        if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
+            altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+            goto selectRem;
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    do {
+        altRem = rem;
+        ++q;
+        rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
+    } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
+ selectRem:
+    meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
+    if (
+        (meanRem.v64 & UINT64_C( 0x8000000000000000 ))
+            || (! (meanRem.v64 | meanRem.v0) && (q & 1))
+    ) {
+        rem = altRem;
+    }
+    signRem = signA;
+    if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
+        signRem = ! signRem;
+        rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
+    }
+    return softfloat_normRoundPackToF128( signRem, expB - 1, rem.v64, rem.v0 );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_roundToInt.c b/tb/riscv-isa-sim/softfloat/f128_roundToInt.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f1f07ecd3b3df59c05f89d538ad430fac05cc9a
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_roundToInt.c
@@ -0,0 +1,160 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t
+ f128_roundToInt( float128_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    int_fast32_t exp;
+    struct uint128 uiZ;
+    uint_fast64_t lastBitMask, roundBitsMask;
+    bool roundNearEven;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    exp = expF128UI64( uiA64 );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x402F <= exp ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( 0x406F <= exp ) {
+            if ( (exp == 0x7FFF) && (fracF128UI64( uiA64 ) | uiA0) ) {
+                uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 );
+                goto uiZ;
+            }
+            return a;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        lastBitMask = (uint_fast64_t) 2<<(0x406E - exp);
+        roundBitsMask = lastBitMask - 1;
+        uiZ.v64 = uiA64;
+        uiZ.v0  = uiA0;
+        roundNearEven = (roundingMode == softfloat_round_near_even);
+        if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) ) {
+            if ( exp == 0x402F ) {
+                if ( UINT64_C( 0x8000000000000000 ) <= uiZ.v0 ) {
+                    ++uiZ.v64;
+                    if (
+                        roundNearEven
+                            && (uiZ.v0 == UINT64_C( 0x8000000000000000 ))
+                    ) {
+                        uiZ.v64 &= ~1;
+                    }
+                }
+            } else {
+                uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, lastBitMask>>1 );
+                if ( roundNearEven && ! (uiZ.v0 & roundBitsMask) ) {
+                    uiZ.v0 &= ~lastBitMask;
+                }
+            }
+        } else if (
+            roundingMode
+                == (signF128UI64( uiZ.v64 ) ? softfloat_round_min
+                        : softfloat_round_max)
+        ) {
+            uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, roundBitsMask );
+        }
+        uiZ.v0 &= ~roundBitsMask;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( exp < 0x3FFF ) {
+            if ( ! ((uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0) ) {
+                return a;
+            }
+            if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
+            uiZ.v64 = uiA64 & packToF128UI64( 1, 0, 0 );
+            uiZ.v0  = 0;
+            switch ( roundingMode ) {
+             case softfloat_round_near_even:
+                if ( ! (fracF128UI64( uiA64 ) | uiA0) ) break;
+             case softfloat_round_near_maxMag:
+                if ( exp == 0x3FFE ) uiZ.v64 |= packToF128UI64( 0, 0x3FFF, 0 );
+                break;
+             case softfloat_round_min:
+                if ( uiZ.v64 ) uiZ.v64 = packToF128UI64( 1, 0x3FFF, 0 );
+                break;
+             case softfloat_round_max:
+                if ( ! uiZ.v64 ) uiZ.v64 = packToF128UI64( 0, 0x3FFF, 0 );
+                break;
+            }
+            goto uiZ;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        uiZ.v64 = uiA64;
+        uiZ.v0  = 0;
+        lastBitMask = (uint_fast64_t) 1<<(0x402F - exp);
+        roundBitsMask = lastBitMask - 1;
+        if ( roundingMode == softfloat_round_near_maxMag ) {
+            uiZ.v64 += lastBitMask>>1;
+        } else if ( roundingMode == softfloat_round_near_even ) {
+            uiZ.v64 += lastBitMask>>1;
+            if ( ! ((uiZ.v64 & roundBitsMask) | uiA0) ) {
+                uiZ.v64 &= ~lastBitMask;
+            }
+        } else if (
+            roundingMode
+                == (signF128UI64( uiZ.v64 ) ? softfloat_round_min
+                        : softfloat_round_max)
+        ) {
+            uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask;
+        }
+        uiZ.v64 &= ~roundBitsMask;
+    }
+    if ( exact && ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_sqrt.c b/tb/riscv-isa-sim/softfloat/f128_sqrt.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b99694ec4838f77e17615ed42cc2986bdab7ad2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_sqrt.c
@@ -0,0 +1,201 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f128_sqrt( float128_t a )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool signA;
+    int_fast32_t expA;
+    struct uint128 sigA, uiZ;
+    struct exp32_sig128 normExpSig;
+    int_fast32_t expZ;
+    uint_fast32_t sig32A, recipSqrt32, sig32Z;
+    struct uint128 rem;
+    uint32_t qs[3];
+    uint_fast32_t q;
+    uint_fast64_t x64, sig64Z;
+    struct uint128 y, term;
+    uint_fast64_t sigZExtra;
+    struct uint128 sigZ;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    signA = signF128UI64( uiA64 );
+    expA  = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FFF ) {
+        if ( sigA.v64 | sigA.v0 ) {
+            uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 );
+            goto uiZ;
+        }
+        if ( ! signA ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( signA ) {
+        if ( ! (expA | sigA.v64 | sigA.v0) ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! (sigA.v64 | sigA.v0) ) return a;
+        normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    | (`sig32Z' is guaranteed to be a lower bound on the square root of
+    | `sig32A', which makes `sig32Z' also a lower bound on the square root of
+    | `sigA'.)
+    *------------------------------------------------------------------------*/
+    expZ = ((expA - 0x3FFF)>>1) + 0x3FFE;
+    expA &= 1;
+    sigA.v64 |= UINT64_C( 0x0001000000000000 );
+    sig32A = sigA.v64>>17;
+    recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
+    sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
+    if ( expA ) {
+        sig32Z >>= 1;
+        rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 12 );
+    } else {
+        rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 13 );
+    }
+    qs[2] = sig32Z;
+    rem.v64 -= (uint_fast64_t) sig32Z * sig32Z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    q = ((uint32_t) (rem.v64>>2) * (uint_fast64_t) recipSqrt32)>>32;
+    x64 = (uint_fast64_t) sig32Z<<32;
+    sig64Z = x64 + ((uint_fast64_t) q<<3);
+    y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
+    /*------------------------------------------------------------------------
+    | (Repeating this loop is a rare occurrence.)
+    *------------------------------------------------------------------------*/
+    for (;;) {
+        term = softfloat_mul64ByShifted32To128( x64 + sig64Z, q );
+        rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
+        if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
+        --q;
+        sig64Z -= 1<<3;
+    }
+    qs[1] = q;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    q = ((rem.v64>>2) * recipSqrt32)>>32;
+    y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
+    sig64Z <<= 1;
+    /*------------------------------------------------------------------------
+    | (Repeating this loop is a rare occurrence.)
+    *------------------------------------------------------------------------*/
+    for (;;) {
+        term = softfloat_shortShiftLeft128( 0, sig64Z, 32 );
+        term = softfloat_add128( term.v64, term.v0, 0, (uint_fast64_t) q<<6 );
+        term = softfloat_mul128By32( term.v64, term.v0, q );
+        rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
+        if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
+        --q;
+    }
+    qs[0] = q;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
+    sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
+    term = softfloat_shortShiftLeft128( 0, qs[1], 53 );
+    sigZ =
+        softfloat_add128(
+            (uint_fast64_t) qs[2]<<18, ((uint_fast64_t) qs[0]<<24) + (q>>5),
+            term.v64, term.v0
+        );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( (q & 0xF) <= 2 ) {
+        q &= ~3;
+        sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
+        y = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, 6 );
+        y.v0 |= sigZExtra>>58;
+        term = softfloat_sub128( y.v64, y.v0, 0, q );
+        y    = softfloat_mul64ByShifted32To128( term.v0,  q );
+        term = softfloat_mul64ByShifted32To128( term.v64, q );
+        term = softfloat_add128( term.v64, term.v0, 0, y.v64 );
+        rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 20 );
+        term = softfloat_sub128( term.v64, term.v0, rem.v64, rem.v0 );
+        /*--------------------------------------------------------------------
+        | The concatenation of `term' and `y.v0' is now the negative remainder
+        | (3 words altogether).
+        *--------------------------------------------------------------------*/
+        if ( term.v64 & UINT64_C( 0x8000000000000000 ) ) {
+            sigZExtra |= 1;
+        } else {
+            if ( term.v64 | term.v0 | y.v0 ) {
+                if ( sigZExtra ) {
+                    --sigZExtra;
+                } else {
+                    sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 );
+                    sigZExtra = ~0;
+                }
+            }
+        }
+    }
+    return softfloat_roundPackToF128( 0, expZ, sigZ.v64, sigZ.v0, sigZExtra );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_sub.c b/tb/riscv-isa-sim/softfloat/f128_sub.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce2e5adb13ceb5638caf41b54ed0100f0ab518e7
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_sub.c
@@ -0,0 +1,78 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t f128_sub( float128_t a, float128_t b )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool signA;
+    union ui128_f128 uB;
+    uint_fast64_t uiB64, uiB0;
+    bool signB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
+    float128_t
+        (*magsFuncPtr)(
+            uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
+#endif
+
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    signA = signF128UI64( uiA64 );
+    uB.f = b;
+    uiB64 = uB.ui.v64;
+    uiB0  = uB.ui.v0;
+    signB = signF128UI64( uiB64 );
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+    if ( signA == signB ) {
+        return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
+    } else {
+        return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA );
+    }
+#else
+    magsFuncPtr =
+        (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
+    return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_f16.c b/tb/riscv-isa-sim/softfloat/f128_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..a910c12a30b546470958fb21fa343a70440d296c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_f16.c
@@ -0,0 +1,95 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t f128_to_f16( float128_t a )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t frac64;
+    struct commonNaN commonNaN;
+    uint_fast16_t uiZ, frac16;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x7FFF ) {
+        if ( frac64 ) {
+            softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
+            uiZ = softfloat_commonNaNToF16UI( &commonNaN );
+        } else {
+            uiZ = packToF16UI( sign, 0x1F, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac16 = softfloat_shortShiftRightJam64( frac64, 34 );
+    if ( ! (exp | frac16) ) {
+        uiZ = packToF16UI( sign, 0, 0 );
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    exp -= 0x3FF1;
+    if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
+        if ( exp < -0x40 ) exp = -0x40;
+    }
+    return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_f32.c b/tb/riscv-isa-sim/softfloat/f128_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..d890d3ebe7ab5121f413c6edbff506ffbcabf555
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_f32.c
@@ -0,0 +1,95 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f128_to_f32( float128_t a )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t frac64;
+    struct commonNaN commonNaN;
+    uint_fast32_t uiZ, frac32;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x7FFF ) {
+        if ( frac64 ) {
+            softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
+            uiZ = softfloat_commonNaNToF32UI( &commonNaN );
+        } else {
+            uiZ = packToF32UI( sign, 0xFF, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac32 = softfloat_shortShiftRightJam64( frac64, 18 );
+    if ( ! (exp | frac32) ) {
+        uiZ = packToF32UI( sign, 0, 0 );
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    exp -= 0x3F81;
+    if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
+        if ( exp < -0x1000 ) exp = -0x1000;
+    }
+    return softfloat_roundPackToF32( sign, exp, frac32 | 0x40000000 );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_f64.c b/tb/riscv-isa-sim/softfloat/f128_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..e7aec20156787c7e25c898bdc307c5b29d8bcf8d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_f64.c
@@ -0,0 +1,100 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f128_to_f64( float128_t a )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t frac64, frac0;
+    struct commonNaN commonNaN;
+    uint_fast64_t uiZ;
+    struct uint128 frac128;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    frac64 = fracF128UI64( uiA64 );
+    frac0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x7FFF ) {
+        if ( frac64 | frac0 ) {
+            softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN );
+            uiZ = softfloat_commonNaNToF64UI( &commonNaN );
+        } else {
+            uiZ = packToF64UI( sign, 0x7FF, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac128 = softfloat_shortShiftLeft128( frac64, frac0, 14 );
+    frac64 = frac128.v64 | (frac128.v0 != 0);
+    if ( ! (exp | frac64) ) {
+        uiZ = packToF64UI( sign, 0, 0 );
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    exp -= 0x3C01;
+    if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
+        if ( exp < -0x1000 ) exp = -0x1000;
+    }
+    return
+        softfloat_roundPackToF64(
+            sign, exp, frac64 | UINT64_C( 0x4000000000000000 ) );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_i32.c b/tb/riscv-isa-sim/softfloat/f128_to_i32.c
new file mode 100644
index 0000000000000000000000000000000000000000..507691ccb880980c4f93f4e3da4f13b56e28907a
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_i32.c
@@ -0,0 +1,85 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f128_to_i32( float128_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t sig64, sig0;
+    int_fast32_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 );
+    sig0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
+    if ( (exp == 0x7FFF) && (sig64 | sig0) ) {
+#if (i32_fromNaN == i32_fromPosOverflow)
+        sign = 0;
+#elif (i32_fromNaN == i32_fromNegOverflow)
+        sign = 1;
+#else
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return i32_fromNaN;
+#endif
+    }
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
+    sig64 |= (sig0 != 0);
+    shiftDist = 0x4023 - exp;
+    if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
+    return softfloat_roundToI32( sign, sig64, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_i32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f128_to_i32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc9f84f18b35858dfba12611f4928f192f8a7d8c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_i32_r_minMag.c
@@ -0,0 +1,100 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    int_fast32_t exp;
+    uint_fast64_t sig64;
+    int_fast32_t shiftDist;
+    bool sign;
+    int_fast32_t absZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x402F - exp;
+    if ( 49 <= shiftDist ) {
+        if ( exact && (exp | sig64) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF128UI64( uiA64 );
+    if ( shiftDist < 18 ) {
+        if (
+            sign && (shiftDist == 17)
+                && (sig64 < UINT64_C( 0x0000000000020000 ))
+        ) {
+            if ( exact && sig64 ) {
+                softfloat_exceptionFlags |= softfloat_flag_inexact;
+            }
+            return -0x7FFFFFFF - 1;
+        }
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x7FFF) && sig64 ? i32_fromNaN
+                : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig64 |= UINT64_C( 0x0001000000000000 );
+    absZ = sig64>>shiftDist;
+    if (
+        exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig64)
+    ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sign ? -absZ : absZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_i64.c b/tb/riscv-isa-sim/softfloat/f128_to_i64.c
new file mode 100644
index 0000000000000000000000000000000000000000..2282eafde52f7c66447b2c5c4aa204edafb25dc5
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_i64.c
@@ -0,0 +1,95 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f128_to_i64( float128_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t sig64, sig0;
+    int_fast32_t shiftDist;
+    struct uint128 sig128;
+    struct uint64_extra sigExtra;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 );
+    sig0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x402F - exp;
+    if ( shiftDist <= 0 ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( shiftDist < -15 ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            return
+                (exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
+                    : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig64 |= UINT64_C( 0x0001000000000000 );
+        if ( shiftDist ) {
+            sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
+            sig64 = sig128.v64;
+            sig0  = sig128.v0;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
+        sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
+        sig64 = sigExtra.v;
+        sig0  = sigExtra.extra;
+    }
+    return softfloat_roundToI64( sign, sig64, sig0, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_i64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f128_to_i64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e0d63da9c5bed06343119afc41a90a5cf973ecc
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_i64_r_minMag.c
@@ -0,0 +1,113 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f128_to_i64_r_minMag( float128_t a, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t sig64, sig0;
+    int_fast32_t shiftDist;
+    int_fast8_t negShiftDist;
+    int_fast64_t absZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 );
+    sig0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x402F - exp;
+    if ( shiftDist < 0 ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( shiftDist < -14 ) {
+            if (
+                   (uiA64 == UINT64_C( 0xC03E000000000000 ))
+                && (sig0 < UINT64_C( 0x0002000000000000 ))
+            ) {
+                if ( exact && sig0 ) {
+                    softfloat_exceptionFlags |= softfloat_flag_inexact;
+                }
+                return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
+            }
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            return
+                (exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
+                    : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig64 |= UINT64_C( 0x0001000000000000 );
+        negShiftDist = -shiftDist;
+        absZ = sig64<<negShiftDist | sig0>>(shiftDist & 63);
+        if ( exact && (uint64_t) (sig0<<negShiftDist) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( 49 <= shiftDist ) {
+            if ( exact && (exp | sig64 | sig0) ) {
+                softfloat_exceptionFlags |= softfloat_flag_inexact;
+            }
+            return 0;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig64 |= UINT64_C( 0x0001000000000000 );
+        absZ = sig64>>shiftDist;
+        if ( exact && (sig0 || (absZ<<shiftDist != sig64)) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+    }
+    return sign ? -absZ : absZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_ui32.c b/tb/riscv-isa-sim/softfloat/f128_to_ui32.c
new file mode 100644
index 0000000000000000000000000000000000000000..75e53d9b2721f7baf7eb7cedaeed7f402e8c6fb8
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_ui32.c
@@ -0,0 +1,86 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t
+ f128_to_ui32( float128_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t sig64;
+    int_fast32_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
+    if ( (exp == 0x7FFF) && sig64 ) {
+#if (ui32_fromNaN == ui32_fromPosOverflow)
+        sign = 0;
+#elif (ui32_fromNaN == ui32_fromNegOverflow)
+        sign = 1;
+#else
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return ui32_fromNaN;
+#endif
+    }
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
+    shiftDist = 0x4023 - exp;
+    if ( 0 < shiftDist ) {
+        sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
+    }
+    return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_ui32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f128_to_ui32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..2097fb81f62b8ab454ba25a8ecb9827ef8a3af82
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_ui32_r_minMag.c
@@ -0,0 +1,89 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    int_fast32_t exp;
+    uint_fast64_t sig64;
+    int_fast32_t shiftDist;
+    bool sign;
+    uint_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x402F - exp;
+    if ( 49 <= shiftDist ) {
+        if ( exact && (exp | sig64) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF128UI64( uiA64 );
+    if ( sign || (shiftDist < 17) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x7FFF) && sig64 ? ui32_fromNaN
+                : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig64 |= UINT64_C( 0x0001000000000000 );
+    z = sig64>>shiftDist;
+    if ( exact && ((uint_fast64_t) z<<shiftDist != sig64) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_ui64.c b/tb/riscv-isa-sim/softfloat/f128_to_ui64.c
new file mode 100644
index 0000000000000000000000000000000000000000..b88d25151a514c73fe5852cb1e700f4d65d07ea1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_ui64.c
@@ -0,0 +1,96 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t
+ f128_to_ui64( float128_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t sig64, sig0;
+    int_fast32_t shiftDist;
+    struct uint128 sig128;
+    struct uint64_extra sigExtra;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 );
+    sig0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x402F - exp;
+    if ( shiftDist <= 0 ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( shiftDist < -15 ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            return
+                (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
+                    : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig64 |= UINT64_C( 0x0001000000000000 );
+        if ( shiftDist ) {
+            sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
+            sig64 = sig128.v64;
+            sig0  = sig128.v0;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
+        sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
+        sig64 = sigExtra.v;
+        sig0  = sigExtra.extra;
+    }
+    return softfloat_roundToUI64( sign, sig64, sig0, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f128_to_ui64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f128_to_ui64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..fb16320aa5c35db8e65813fd2d4dc540cc757e73
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f128_to_ui64_r_minMag.c
@@ -0,0 +1,105 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f128_to_ui64_r_minMag( float128_t a, bool exact )
+{
+    union ui128_f128 uA;
+    uint_fast64_t uiA64, uiA0;
+    bool sign;
+    int_fast32_t exp;
+    uint_fast64_t sig64, sig0;
+    int_fast32_t shiftDist;
+    int_fast8_t negShiftDist;
+    uint_fast64_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA64 = uA.ui.v64;
+    uiA0  = uA.ui.v0;
+    sign  = signF128UI64( uiA64 );
+    exp   = expF128UI64( uiA64 );
+    sig64 = fracF128UI64( uiA64 );
+    sig0  = uiA0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x402F - exp;
+    if ( shiftDist < 0 ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( sign || (shiftDist < -15) ) goto invalid;
+        sig64 |= UINT64_C( 0x0001000000000000 );
+        negShiftDist = -shiftDist;
+        z = sig64<<negShiftDist | sig0>>(shiftDist & 63);
+        if ( exact && (uint64_t) (sig0<<negShiftDist) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( 49 <= shiftDist ) {
+            if ( exact && (exp | sig64 | sig0) ) {
+                softfloat_exceptionFlags |= softfloat_flag_inexact;
+            }
+            return 0;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( sign ) goto invalid;
+        sig64 |= UINT64_C( 0x0001000000000000 );
+        z = sig64>>shiftDist;
+        if ( exact && (sig0 || (z<<shiftDist != sig64)) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return
+        (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
+            : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_add.c b/tb/riscv-isa-sim/softfloat/f16_add.c
new file mode 100644
index 0000000000000000000000000000000000000000..eb763d01197508e144824a10c82b5dc0e688bb39
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_add.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t f16_add( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
+    float16_t (*magsFuncPtr)( uint_fast16_t, uint_fast16_t );
+#endif
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
+    if ( signF16UI( uiA ^ uiB ) ) {
+        return softfloat_subMagsF16( uiA, uiB );
+    } else {
+        return softfloat_addMagsF16( uiA, uiB );
+    }
+#else
+    magsFuncPtr =
+        signF16UI( uiA ^ uiB ) ? softfloat_subMagsF16 : softfloat_addMagsF16;
+    return (*magsFuncPtr)( uiA, uiB );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_div.c b/tb/riscv-isa-sim/softfloat/f16_div.c
new file mode 100644
index 0000000000000000000000000000000000000000..71b5c29b0c6c540900f30919863b9a44144aad5f
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_div.c
@@ -0,0 +1,186 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extern const uint16_t softfloat_approxRecip_1k0s[];
+extern const uint16_t softfloat_approxRecip_1k1s[];
+
+float16_t f16_div( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool signA;
+    int_fast8_t expA;
+    uint_fast16_t sigA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    bool signB;
+    int_fast8_t expB;
+    uint_fast16_t sigB;
+    bool signZ;
+    struct exp8_sig16 normExpSig;
+    int_fast8_t expZ;
+#ifdef SOFTFLOAT_FAST_DIV32TO16
+    uint_fast32_t sig32A;
+    uint_fast16_t sigZ;
+#else
+    int index;
+    uint16_t r0;
+    uint_fast16_t sigZ, rem;
+#endif
+    uint_fast16_t uiZ;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF16UI( uiA );
+    expA  = expF16UI( uiA );
+    sigA  = fracF16UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF16UI( uiB );
+    expB  = expF16UI( uiB );
+    sigB  = fracF16UI( uiB );
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x1F ) {
+        if ( sigA ) goto propagateNaN;
+        if ( expB == 0x1F ) {
+            if ( sigB ) goto propagateNaN;
+            goto invalid;
+        }
+        goto infinity;
+    }
+    if ( expB == 0x1F ) {
+        if ( sigB ) goto propagateNaN;
+        goto zero;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! sigB ) {
+            if ( ! (expA | sigA) ) goto invalid;
+            softfloat_raiseFlags( softfloat_flag_infinite );
+            goto infinity;
+        }
+        normExpSig = softfloat_normSubnormalF16Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! sigA ) goto zero;
+        normExpSig = softfloat_normSubnormalF16Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA - expB + 0xE;
+    sigA |= 0x0400;
+    sigB |= 0x0400;
+#ifdef SOFTFLOAT_FAST_DIV32TO16
+    if ( sigA < sigB ) {
+        --expZ;
+        sig32A = (uint_fast32_t) sigA<<15;
+    } else {
+        sig32A = (uint_fast32_t) sigA<<14;
+    }
+    sigZ = sig32A / sigB;
+    if ( ! (sigZ & 7) ) sigZ |= ((uint_fast32_t) sigB * sigZ != sig32A);
+#else
+    if ( sigA < sigB ) {
+        --expZ;
+        sigA <<= 5;
+    } else {
+        sigA <<= 4;
+    }
+    index = sigB>>6 & 0xF;
+    r0 = softfloat_approxRecip_1k0s[index]
+             - (((uint_fast32_t) softfloat_approxRecip_1k1s[index]
+                     * (sigB & 0x3F))
+                    >>10);
+    sigZ = ((uint_fast32_t) sigA * r0)>>16;
+    rem = (sigA<<10) - sigZ * sigB;
+    sigZ += (rem * (uint_fast32_t) r0)>>26;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    ++sigZ;
+    if ( ! (sigZ & 7) ) {
+        sigZ &= ~1;
+        rem = (sigA<<10) - sigZ * sigB;
+        if ( rem & 0x8000 ) {
+            sigZ -= 2;
+        } else {
+            if ( rem ) sigZ |= 1;
+        }
+    }
+#endif
+    return softfloat_roundPackToF16( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF16UI;
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infinity:
+    uiZ = packToF16UI( signZ, 0x1F, 0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ = packToF16UI( signZ, 0, 0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_eq.c b/tb/riscv-isa-sim/softfloat/f16_eq.c
new file mode 100644
index 0000000000000000000000000000000000000000..37a60998f1c4e19cf3aacf2da3ef62fc65a33f0c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_eq.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f16_eq( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    return (uiA == uiB) || ! (uint16_t) ((uiA | uiB)<<1);
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_eq_signaling.c b/tb/riscv-isa-sim/softfloat/f16_eq_signaling.c
new file mode 100644
index 0000000000000000000000000000000000000000..894f7b59d7edf70b615d0728f31a54123c81b934
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_eq_signaling.c
@@ -0,0 +1,61 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f16_eq_signaling( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    return (uiA == uiB) || ! (uint16_t) ((uiA | uiB)<<1);
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_isSignalingNaN.c b/tb/riscv-isa-sim/softfloat/f16_isSignalingNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..657805be3fbddfc7f4ef1899d0fa37f7f3391a37
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_isSignalingNaN.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f16_isSignalingNaN( float16_t a )
+{
+    union ui16_f16 uA;
+
+    uA.f = a;
+    return softfloat_isSigNaNF16UI( uA.ui );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_le.c b/tb/riscv-isa-sim/softfloat/f16_le.c
new file mode 100644
index 0000000000000000000000000000000000000000..37eaf1879a4743d869d7a9e482ac7710201871e1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_le.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f16_le( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF16UI( uiA );
+    signB = signF16UI( uiB );
+    return
+        (signA != signB) ? signA || ! (uint16_t) ((uiA | uiB)<<1)
+            : (uiA == uiB) || (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_le_quiet.c b/tb/riscv-isa-sim/softfloat/f16_le_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..8391db74db45f0771befc46f66e08abf98aee2fb
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_le_quiet.c
@@ -0,0 +1,71 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f16_le_quiet( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF16UI( uiA );
+    signB = signF16UI( uiB );
+    return
+        (signA != signB) ? signA || ! (uint16_t) ((uiA | uiB)<<1)
+            : (uiA == uiB) || (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_lt.c b/tb/riscv-isa-sim/softfloat/f16_lt.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d3522a4731b5c2b2a95806f352e427c71ef4c54
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_lt.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f16_lt( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF16UI( uiA );
+    signB = signF16UI( uiB );
+    return
+        (signA != signB) ? signA && ((uint16_t) ((uiA | uiB)<<1) != 0)
+            : (uiA != uiB) && (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_lt_quiet.c b/tb/riscv-isa-sim/softfloat/f16_lt_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..37f762cdae0446f0bdc6a7096bf26afb293dfc04
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_lt_quiet.c
@@ -0,0 +1,71 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f16_lt_quiet( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF16UI( uiA ) || isNaNF16UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF16UI( uiA );
+    signB = signF16UI( uiB );
+    return
+        (signA != signB) ? signA && ((uint16_t) ((uiA | uiB)<<1) != 0)
+            : (uiA != uiB) && (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_mul.c b/tb/riscv-isa-sim/softfloat/f16_mul.c
new file mode 100644
index 0000000000000000000000000000000000000000..255caa7edc30d4d7708c2c0ba4438c523b0f0aea
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_mul.c
@@ -0,0 +1,140 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t f16_mul( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool signA;
+    int_fast8_t expA;
+    uint_fast16_t sigA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    bool signB;
+    int_fast8_t expB;
+    uint_fast16_t sigB;
+    bool signZ;
+    uint_fast16_t magBits;
+    struct exp8_sig16 normExpSig;
+    int_fast8_t expZ;
+    uint_fast32_t sig32Z;
+    uint_fast16_t sigZ, uiZ;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF16UI( uiA );
+    expA  = expF16UI( uiA );
+    sigA  = fracF16UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF16UI( uiB );
+    expB  = expF16UI( uiB );
+    sigB  = fracF16UI( uiB );
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x1F ) {
+        if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN;
+        magBits = expB | sigB;
+        goto infArg;
+    }
+    if ( expB == 0x1F ) {
+        if ( sigB ) goto propagateNaN;
+        magBits = expA | sigA;
+        goto infArg;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zero;
+        normExpSig = softfloat_normSubnormalF16Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zero;
+        normExpSig = softfloat_normSubnormalF16Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0xF;
+    sigA = (sigA | 0x0400)<<4;
+    sigB = (sigB | 0x0400)<<5;
+    sig32Z = (uint_fast32_t) sigA * sigB;
+    sigZ = sig32Z>>16;
+    if ( sig32Z & 0xFFFF ) sigZ |= 1;
+    if ( sigZ < 0x4000 ) {
+        --expZ;
+        sigZ <<= 1;
+    }
+    return softfloat_roundPackToF16( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infArg:
+    if ( ! magBits ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        uiZ = defaultNaNF16UI;
+    } else {
+        uiZ = packToF16UI( signZ, 0x1F, 0 );
+    }
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ = packToF16UI( signZ, 0, 0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_mulAdd.c b/tb/riscv-isa-sim/softfloat/f16_mulAdd.c
new file mode 100644
index 0000000000000000000000000000000000000000..40261963939a627865a5e574980c11195787ea52
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_mulAdd.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t f16_mulAdd( float16_t a, float16_t b, float16_t c )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    union ui16_f16 uC;
+    uint_fast16_t uiC;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    uC.f = c;
+    uiC = uC.ui;
+    return softfloat_mulAddF16( uiA, uiB, uiC, 0 );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_rem.c b/tb/riscv-isa-sim/softfloat/f16_rem.c
new file mode 100644
index 0000000000000000000000000000000000000000..86c319ddced0f910484b5afe7549f155ff6ec91d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_rem.c
@@ -0,0 +1,171 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t f16_rem( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool signA;
+    int_fast8_t expA;
+    uint_fast16_t sigA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+    int_fast8_t expB;
+    uint_fast16_t sigB;
+    struct exp8_sig16 normExpSig;
+    uint16_t rem;
+    int_fast8_t expDiff;
+    uint_fast16_t q;
+    uint32_t recip32, q32;
+    uint16_t altRem, meanRem;
+    bool signRem;
+    uint_fast16_t uiZ;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF16UI( uiA );
+    expA  = expF16UI( uiA );
+    sigA  = fracF16UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    expB = expF16UI( uiB );
+    sigB = fracF16UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x1F ) {
+        if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN;
+        goto invalid;
+    }
+    if ( expB == 0x1F ) {
+        if ( sigB ) goto propagateNaN;
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! sigB ) goto invalid;
+        normExpSig = softfloat_normSubnormalF16Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! sigA ) return a;
+        normExpSig = softfloat_normSubnormalF16Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    rem = sigA | 0x0400;
+    sigB |= 0x0400;
+    expDiff = expA - expB;
+    if ( expDiff < 1 ) {
+        if ( expDiff < -1 ) return a;
+        sigB <<= 3;
+        if ( expDiff ) {
+            rem <<= 2;
+            q = 0;
+        } else {
+            rem <<= 3;
+            q = (sigB <= rem);
+            if ( q ) rem -= sigB;
+        }
+    } else {
+        recip32 = softfloat_approxRecip32_1( (uint_fast32_t) sigB<<21 );
+        /*--------------------------------------------------------------------
+        | Changing the shift of `rem' here requires also changing the initial
+        | subtraction from `expDiff'.
+        *--------------------------------------------------------------------*/
+        rem <<= 4;
+        expDiff -= 31;
+        /*--------------------------------------------------------------------
+        | The scale of `sigB' affects how many bits are obtained during each
+        | cycle of the loop.  Currently this is 29 bits per loop iteration,
+        | which is believed to be the maximum possible.
+        *--------------------------------------------------------------------*/
+        sigB <<= 3;
+        for (;;) {
+            q32 = (rem * (uint_fast64_t) recip32)>>16;
+            if ( expDiff < 0 ) break;
+            rem = -((uint_fast16_t) q32 * sigB);
+            expDiff -= 29;
+        }
+        /*--------------------------------------------------------------------
+        | (`expDiff' cannot be less than -30 here.)
+        *--------------------------------------------------------------------*/
+        q32 >>= ~expDiff & 31;
+        q = q32;
+        rem = (rem<<(expDiff + 30)) - q * sigB;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    do {
+        altRem = rem;
+        ++q;
+        rem -= sigB;
+    } while ( ! (rem & 0x8000) );
+    meanRem = rem + altRem;
+    if ( (meanRem & 0x8000) || (! meanRem && (q & 1)) ) rem = altRem;
+    signRem = signA;
+    if ( 0x8000 <= rem ) {
+        signRem = ! signRem;
+        rem = -rem;
+    }
+    return softfloat_normRoundPackToF16( signRem, expB, rem );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
+    goto uiZ;
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF16UI;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_roundToInt.c b/tb/riscv-isa-sim/softfloat/f16_roundToInt.c
new file mode 100644
index 0000000000000000000000000000000000000000..9bbd47eb2df6aec8278a48298f2b7c010d0834d6
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_roundToInt.c
@@ -0,0 +1,112 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t f16_roundToInt( float16_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    int_fast8_t exp;
+    uint_fast16_t uiZ, lastBitMask, roundBitsMask;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp <= 0xE ) {
+        if ( ! (uint16_t) (uiA<<1) ) return a;
+        if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
+        uiZ = uiA & packToF16UI( 1, 0, 0 );
+        switch ( roundingMode ) {
+         case softfloat_round_near_even:
+            if ( ! fracF16UI( uiA ) ) break;
+         case softfloat_round_near_maxMag:
+            if ( exp == 0xE ) uiZ |= packToF16UI( 0, 0xF, 0 );
+            break;
+         case softfloat_round_min:
+            if ( uiZ ) uiZ = packToF16UI( 1, 0xF, 0 );
+            break;
+         case softfloat_round_max:
+            if ( ! uiZ ) uiZ = packToF16UI( 0, 0xF, 0 );
+            break;
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x19 <= exp ) {
+        if ( (exp == 0x1F) && fracF16UI( uiA ) ) {
+            uiZ = softfloat_propagateNaNF16UI( uiA, 0 );
+            goto uiZ;
+        }
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ = uiA;
+    lastBitMask = (uint_fast16_t) 1<<(0x19 - exp);
+    roundBitsMask = lastBitMask - 1;
+    if ( roundingMode == softfloat_round_near_maxMag ) {
+        uiZ += lastBitMask>>1;
+    } else if ( roundingMode == softfloat_round_near_even ) {
+        uiZ += lastBitMask>>1;
+        if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask;
+    } else if (
+        roundingMode
+            == (signF16UI( uiZ ) ? softfloat_round_min : softfloat_round_max)
+    ) {
+        uiZ += roundBitsMask;
+    }
+    uiZ &= ~roundBitsMask;
+    if ( exact && (uiZ != uiA) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_sqrt.c b/tb/riscv-isa-sim/softfloat/f16_sqrt.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ff292392e7890b3e98abf67199e0d6eee63e433
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_sqrt.c
@@ -0,0 +1,136 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
+extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
+
+float16_t f16_sqrt( float16_t a )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool signA;
+    int_fast8_t expA;
+    uint_fast16_t sigA, uiZ;
+    struct exp8_sig16 normExpSig;
+    int_fast8_t expZ;
+    int index;
+    uint_fast16_t r0;
+    uint_fast32_t ESqrR0;
+    uint16_t sigma0;
+    uint_fast16_t recipSqrt16, sigZ, shiftedSigZ;
+    uint16_t negRem;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF16UI( uiA );
+    expA  = expF16UI( uiA );
+    sigA  = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x1F ) {
+        if ( sigA ) {
+            uiZ = softfloat_propagateNaNF16UI( uiA, 0 );
+            goto uiZ;
+        }
+        if ( ! signA ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( signA ) {
+        if ( ! (expA | sigA) ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) return a;
+        normExpSig = softfloat_normSubnormalF16Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = ((expA - 0xF)>>1) + 0xE;
+    expA &= 1;
+    sigA |= 0x0400;
+    index = (sigA>>6 & 0xE) + expA;
+    r0 = softfloat_approxRecipSqrt_1k0s[index]
+             - (((uint_fast32_t) softfloat_approxRecipSqrt_1k1s[index]
+                     * (sigA & 0x7F))
+                    >>11);
+    ESqrR0 = ((uint_fast32_t) r0 * r0)>>1;
+    if ( expA ) ESqrR0 >>= 1;
+    sigma0 = ~(uint_fast16_t) ((ESqrR0 * sigA)>>16);
+    recipSqrt16 = r0 + (((uint_fast32_t) r0 * sigma0)>>25);
+    if ( ! (recipSqrt16 & 0x8000) ) recipSqrt16 = 0x8000;
+    sigZ = ((uint_fast32_t) (sigA<<5) * recipSqrt16)>>16;
+    if ( expA ) sigZ >>= 1;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    ++sigZ;
+    if ( ! (sigZ & 7) ) {
+        shiftedSigZ = sigZ>>1;
+        negRem = shiftedSigZ * shiftedSigZ;
+        sigZ &= ~1;
+        if ( negRem & 0x8000 ) {
+            sigZ |= 1;
+        } else {
+            if ( negRem ) --sigZ;
+        }
+    }
+    return softfloat_roundPackToF16( 0, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF16UI;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_sub.c b/tb/riscv-isa-sim/softfloat/f16_sub.c
new file mode 100644
index 0000000000000000000000000000000000000000..811f239f10c52ef287614364c399b2e308830b57
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_sub.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t f16_sub( float16_t a, float16_t b )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    union ui16_f16 uB;
+    uint_fast16_t uiB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
+    float16_t (*magsFuncPtr)( uint_fast16_t, uint_fast16_t );
+#endif
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
+    if ( signF16UI( uiA ^ uiB ) ) {
+        return softfloat_addMagsF16( uiA, uiB );
+    } else {
+        return softfloat_subMagsF16( uiA, uiB );
+    }
+#else
+    magsFuncPtr =
+        signF16UI( uiA ^ uiB ) ? softfloat_addMagsF16 : softfloat_subMagsF16;
+    return (*magsFuncPtr)( uiA, uiB );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_f128.c b/tb/riscv-isa-sim/softfloat/f16_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..961cdaaf1711d7d999a95284d83ee2bb4f6451f7
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_f128.c
@@ -0,0 +1,96 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f16_to_f128( float16_t a )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    struct commonNaN commonNaN;
+    struct uint128 uiZ;
+    struct exp8_sig16 normExpSig;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        if ( frac ) {
+            softfloat_f16UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF128UI( &commonNaN );
+        } else {
+            uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
+            uiZ.v0  = 0;
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! exp ) {
+        if ( ! frac ) {
+            uiZ.v64 = packToF128UI64( sign, 0, 0 );
+            uiZ.v0  = 0;
+            goto uiZ;
+        }
+        normExpSig = softfloat_normSubnormalF16Sig( frac );
+        exp = normExpSig.exp - 1;
+        frac = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ.v64 = packToF128UI64( sign, exp + 0x3FF0, (uint_fast64_t) frac<<38 );
+    uiZ.v0  = 0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_f32.c b/tb/riscv-isa-sim/softfloat/f16_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..fb8b3819d130adc3b6ac9fd139fc14a651e35d32
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_f32.c
@@ -0,0 +1,93 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f16_to_f32( float16_t a )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    struct commonNaN commonNaN;
+    uint_fast32_t uiZ;
+    struct exp8_sig16 normExpSig;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        if ( frac ) {
+            softfloat_f16UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF32UI( &commonNaN );
+        } else {
+            uiZ = packToF32UI( sign, 0xFF, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! exp ) {
+        if ( ! frac ) {
+            uiZ = packToF32UI( sign, 0, 0 );
+            goto uiZ;
+        }
+        normExpSig = softfloat_normSubnormalF16Sig( frac );
+        exp = normExpSig.exp - 1;
+        frac = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ = packToF32UI( sign, exp + 0x70, (uint_fast32_t) frac<<13 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_f64.c b/tb/riscv-isa-sim/softfloat/f16_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..4ab27ba0b5d43d04311fa5a42265ded60e394f41
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_f64.c
@@ -0,0 +1,93 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f16_to_f64( float16_t a )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    struct commonNaN commonNaN;
+    uint_fast64_t uiZ;
+    struct exp8_sig16 normExpSig;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        if ( frac ) {
+            softfloat_f16UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF64UI( &commonNaN );
+        } else {
+            uiZ = packToF64UI( sign, 0x7FF, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! exp ) {
+        if ( ! frac ) {
+            uiZ = packToF64UI( sign, 0, 0 );
+            goto uiZ;
+        }
+        normExpSig = softfloat_normSubnormalF16Sig( frac );
+        exp = normExpSig.exp - 1;
+        frac = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ = packToF64UI( sign, exp + 0x3F0, (uint_fast64_t) frac<<42 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_i32.c b/tb/riscv-isa-sim/softfloat/f16_to_i32.c
new file mode 100644
index 0000000000000000000000000000000000000000..24b19846d0a1222403d9455e2140efabb125b156
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_i32.c
@@ -0,0 +1,87 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f16_to_i32( float16_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    int_fast32_t sig32;
+    int_fast8_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            frac ? i32_fromNaN
+                : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig32 = frac;
+    if ( exp ) {
+        sig32 |= 0x0400;
+        shiftDist = exp - 0x19;
+        if ( 0 <= shiftDist ) {
+            sig32 <<= shiftDist;
+            return sign ? -sig32 : sig32;
+        }
+        shiftDist = exp - 0x0D;
+        if ( 0 < shiftDist ) sig32 <<= shiftDist;
+    }
+    return
+        softfloat_roundToI32(
+            sign, (uint_fast32_t) sig32, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_i32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f16_to_i32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..ebb4965ca62fcf8401e01c1b74fceba9635b446b
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_i32_r_minMag.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f16_to_i32_r_minMag( float16_t a, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    int_fast8_t shiftDist;
+    bool sign;
+    int_fast32_t alignedSig;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = exp - 0x0F;
+    if ( shiftDist < 0 ) {
+        if ( exact && (exp | frac) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF16UI( uiA );
+    if ( exp == 0x1F ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x1F) && frac ? i32_fromNaN
+                : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    alignedSig = (int_fast32_t) (frac | 0x0400)<<shiftDist;
+    if ( exact && (alignedSig & 0x3FF) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    alignedSig >>= 10;
+    return sign ? -alignedSig : alignedSig;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_i64.c b/tb/riscv-isa-sim/softfloat/f16_to_i64.c
new file mode 100644
index 0000000000000000000000000000000000000000..c2417456402ff380cbc3b4c35c8d3e086517013e
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_i64.c
@@ -0,0 +1,87 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f16_to_i64( float16_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    int_fast32_t sig32;
+    int_fast8_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            frac ? i64_fromNaN
+                : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig32 = frac;
+    if ( exp ) {
+        sig32 |= 0x0400;
+        shiftDist = exp - 0x19;
+        if ( 0 <= shiftDist ) {
+            sig32 <<= shiftDist;
+            return sign ? -sig32 : sig32;
+        }
+        shiftDist = exp - 0x0D;
+        if ( 0 < shiftDist ) sig32 <<= shiftDist;
+    }
+    return
+        softfloat_roundToI32(
+            sign, (uint_fast32_t) sig32, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_i64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f16_to_i64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..dc9a8d37f2e8775d907511da43b1c36e8a5cecf4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_i64_r_minMag.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f16_to_i64_r_minMag( float16_t a, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    int_fast8_t shiftDist;
+    bool sign;
+    int_fast32_t alignedSig;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = exp - 0x0F;
+    if ( shiftDist < 0 ) {
+        if ( exact && (exp | frac) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF16UI( uiA );
+    if ( exp == 0x1F ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x1F) && frac ? i64_fromNaN
+                : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    alignedSig = (int_fast32_t) (frac | 0x0400)<<shiftDist;
+    if ( exact && (alignedSig & 0x3FF) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    alignedSig >>= 10;
+    return sign ? -alignedSig : alignedSig;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_ui32.c b/tb/riscv-isa-sim/softfloat/f16_to_ui32.c
new file mode 100644
index 0000000000000000000000000000000000000000..c99af39c6791c94d578bfd86a81a2dbe4026c677
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_ui32.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f16_to_ui32( float16_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    uint_fast32_t sig32;
+    int_fast8_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            frac ? ui32_fromNaN
+                : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig32 = frac;
+    if ( exp ) {
+        sig32 |= 0x0400;
+        shiftDist = exp - 0x19;
+        if ( (0 <= shiftDist) && ! sign ) {
+            return sig32<<shiftDist;
+        }
+        shiftDist = exp - 0x0D;
+        if ( 0 < shiftDist ) sig32 <<= shiftDist;
+    }
+    return softfloat_roundToUI32( sign, sig32, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_ui32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f16_to_ui32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..f63e05abc693a70a6d26fdd70ccb2b3ed711445d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_ui32_r_minMag.c
@@ -0,0 +1,87 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f16_to_ui32_r_minMag( float16_t a, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    int_fast8_t shiftDist;
+    bool sign;
+    uint_fast32_t alignedSig;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = exp - 0x0F;
+    if ( shiftDist < 0 ) {
+        if ( exact && (exp | frac) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF16UI( uiA );
+    if ( sign || (exp == 0x1F) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x1F) && frac ? ui32_fromNaN
+                : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    alignedSig = (uint_fast32_t) (frac | 0x0400)<<shiftDist;
+    if ( exact && (alignedSig & 0x3FF) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return alignedSig>>10;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_ui64.c b/tb/riscv-isa-sim/softfloat/f16_to_ui64.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd260eae8bb8cb3690c4a600061ec1569c35d405
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_ui64.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f16_to_ui64( float16_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    bool sign;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    uint_fast32_t sig32;
+    int_fast8_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF16UI( uiA );
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x1F ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            frac ? ui64_fromNaN
+                : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig32 = frac;
+    if ( exp ) {
+        sig32 |= 0x0400;
+        shiftDist = exp - 0x19;
+        if ( (0 <= shiftDist) && ! sign ) {
+            return sig32<<shiftDist;
+        }
+        shiftDist = exp - 0x0D;
+        if ( 0 < shiftDist ) sig32 <<= shiftDist;
+    }
+    return softfloat_roundToUI32( sign, sig32, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f16_to_ui64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f16_to_ui64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..a57b422928756daaa05b19f8156d4b283f7f8aa1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f16_to_ui64_r_minMag.c
@@ -0,0 +1,87 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f16_to_ui64_r_minMag( float16_t a, bool exact )
+{
+    union ui16_f16 uA;
+    uint_fast16_t uiA;
+    int_fast8_t exp;
+    uint_fast16_t frac;
+    int_fast8_t shiftDist;
+    bool sign;
+    uint_fast32_t alignedSig;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp  = expF16UI( uiA );
+    frac = fracF16UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = exp - 0x0F;
+    if ( shiftDist < 0 ) {
+        if ( exact && (exp | frac) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF16UI( uiA );
+    if ( sign || (exp == 0x1F) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x1F) && frac ? ui64_fromNaN
+                : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    alignedSig = (uint_fast32_t) (frac | 0x0400)<<shiftDist;
+    if ( exact && (alignedSig & 0x3FF) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return alignedSig>>10;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_add.c b/tb/riscv-isa-sim/softfloat/f32_add.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a51eccf68530307a51df76d73e94b8439c9e103
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_add.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t f32_add( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
+    float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t );
+#endif
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
+    if ( signF32UI( uiA ^ uiB ) ) {
+        return softfloat_subMagsF32( uiA, uiB );
+    } else {
+        return softfloat_addMagsF32( uiA, uiB );
+    }
+#else
+    magsFuncPtr =
+        signF32UI( uiA ^ uiB ) ? softfloat_subMagsF32 : softfloat_addMagsF32;
+    return (*magsFuncPtr)( uiA, uiB );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_classify.c b/tb/riscv-isa-sim/softfloat/f32_classify.c
new file mode 100755
index 0000000000000000000000000000000000000000..83fad878aaf9f1ffb8926d557708149773da7d45
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_classify.c
@@ -0,0 +1,36 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast16_t f32_classify( float32_t a )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+
+    uA.f = a;
+    uiA = uA.ui;
+
+    uint_fast16_t infOrNaN = expF32UI( uiA ) == 0xFF;
+    uint_fast16_t subnormalOrZero = expF32UI( uiA ) == 0;
+    bool sign = signF32UI( uiA );
+    bool fracZero = fracF32UI( uiA ) == 0;
+    bool isNaN = isNaNF32UI( uiA );
+    bool isSNaN = softfloat_isSigNaNF32UI( uiA );
+
+    return
+        (  sign && infOrNaN && fracZero )          << 0 |
+        (  sign && !infOrNaN && !subnormalOrZero ) << 1 |
+        (  sign && subnormalOrZero && !fracZero )  << 2 |
+        (  sign && subnormalOrZero && fracZero )   << 3 |
+        ( !sign && infOrNaN && fracZero )          << 7 |
+        ( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
+        ( !sign && subnormalOrZero && !fracZero )  << 5 |
+        ( !sign && subnormalOrZero && fracZero )   << 4 |
+        ( isNaN &&  isSNaN )                       << 8 |
+        ( isNaN && !isSNaN )                       << 9;
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_div.c b/tb/riscv-isa-sim/softfloat/f32_div.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d101254b15adb8d0054c74945bdabc018932957
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_div.c
@@ -0,0 +1,180 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f32_div( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast32_t sigA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    bool signB;
+    int_fast16_t expB;
+    uint_fast32_t sigB;
+    bool signZ;
+    struct exp16_sig32 normExpSig;
+    int_fast16_t expZ;
+#ifdef SOFTFLOAT_FAST_DIV64TO32
+    uint_fast64_t sig64A;
+    uint_fast32_t sigZ;
+#else
+    uint_fast32_t sigZ;
+    uint_fast64_t rem;
+#endif
+    uint_fast32_t uiZ;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF32UI( uiA );
+    expA  = expF32UI( uiA );
+    sigA  = fracF32UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF32UI( uiB );
+    expB  = expF32UI( uiB );
+    sigB  = fracF32UI( uiB );
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0xFF ) {
+        if ( sigA ) goto propagateNaN;
+        if ( expB == 0xFF ) {
+            if ( sigB ) goto propagateNaN;
+            goto invalid;
+        }
+        goto infinity;
+    }
+    if ( expB == 0xFF ) {
+        if ( sigB ) goto propagateNaN;
+        goto zero;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! sigB ) {
+            if ( ! (expA | sigA) ) goto invalid;
+            softfloat_raiseFlags( softfloat_flag_infinite );
+            goto infinity;
+        }
+        normExpSig = softfloat_normSubnormalF32Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! sigA ) goto zero;
+        normExpSig = softfloat_normSubnormalF32Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA - expB + 0x7E;
+    sigA |= 0x00800000;
+    sigB |= 0x00800000;
+#ifdef SOFTFLOAT_FAST_DIV64TO32
+    if ( sigA < sigB ) {
+        --expZ;
+        sig64A = (uint_fast64_t) sigA<<31;
+    } else {
+        sig64A = (uint_fast64_t) sigA<<30;
+    }
+    sigZ = sig64A / sigB;
+    if ( ! (sigZ & 0x3F) ) sigZ |= ((uint_fast64_t) sigB * sigZ != sig64A);
+#else
+    if ( sigA < sigB ) {
+        --expZ;
+        sigA <<= 8;
+    } else {
+        sigA <<= 7;
+    }
+    sigB <<= 8;
+    sigZ = ((uint_fast64_t) sigA * softfloat_approxRecip32_1( sigB ))>>32;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sigZ += 2;
+    if ( (sigZ & 0x3F) < 2 ) {
+        sigZ &= ~3;
+#ifdef SOFTFLOAT_FAST_INT64
+        rem = ((uint_fast64_t) sigA<<31) - (uint_fast64_t) sigZ * sigB;
+#else
+        rem = ((uint_fast64_t) sigA<<32) - (uint_fast64_t) (sigZ<<1) * sigB;
+#endif
+        if ( rem & UINT64_C( 0x8000000000000000 ) ) {
+            sigZ -= 4;
+        } else {
+            if ( rem ) sigZ |= 1;
+        }
+    }
+#endif
+    return softfloat_roundPackToF32( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF32UI;
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infinity:
+    uiZ = packToF32UI( signZ, 0xFF, 0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ = packToF32UI( signZ, 0, 0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_eq.c b/tb/riscv-isa-sim/softfloat/f32_eq.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f07eee300bd1db038d469c2f517d576e963b74c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_eq.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f32_eq( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1);
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_eq_signaling.c b/tb/riscv-isa-sim/softfloat/f32_eq_signaling.c
new file mode 100644
index 0000000000000000000000000000000000000000..f5fcc8242cec25accccea08e08057f79f3b09b3b
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_eq_signaling.c
@@ -0,0 +1,61 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f32_eq_signaling( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1);
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_isSignalingNaN.c b/tb/riscv-isa-sim/softfloat/f32_isSignalingNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..5004a5aae4a8d33ee338c66f4299bad8d155efe2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_isSignalingNaN.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f32_isSignalingNaN( float32_t a )
+{
+    union ui32_f32 uA;
+
+    uA.f = a;
+    return softfloat_isSigNaNF32UI( uA.ui );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_le.c b/tb/riscv-isa-sim/softfloat/f32_le.c
new file mode 100644
index 0000000000000000000000000000000000000000..77595fbbcf798b1caa0ec0b970d88099987f96dd
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_le.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f32_le( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF32UI( uiA );
+    signB = signF32UI( uiB );
+    return
+        (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1)
+            : (uiA == uiB) || (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_le_quiet.c b/tb/riscv-isa-sim/softfloat/f32_le_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..1ec9101070db782c111bb101f7f83e65805c1199
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_le_quiet.c
@@ -0,0 +1,71 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f32_le_quiet( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF32UI( uiA );
+    signB = signF32UI( uiB );
+    return
+        (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1)
+            : (uiA == uiB) || (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_lt.c b/tb/riscv-isa-sim/softfloat/f32_lt.c
new file mode 100644
index 0000000000000000000000000000000000000000..9e12843fbd698d0037e65b5ca4a8ba4f66389735
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_lt.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f32_lt( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF32UI( uiA );
+    signB = signF32UI( uiB );
+    return
+        (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0)
+            : (uiA != uiB) && (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_lt_quiet.c b/tb/riscv-isa-sim/softfloat/f32_lt_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f83b8105636b406140b517c4fbd0fdfabe0cd5d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_lt_quiet.c
@@ -0,0 +1,71 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f32_lt_quiet( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF32UI( uiA );
+    signB = signF32UI( uiB );
+    return
+        (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0)
+            : (uiA != uiB) && (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_mul.c b/tb/riscv-isa-sim/softfloat/f32_mul.c
new file mode 100644
index 0000000000000000000000000000000000000000..a2a673f1c09e339851abef8d7feaf377c9783f8f
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_mul.c
@@ -0,0 +1,137 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f32_mul( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast32_t sigA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    bool signB;
+    int_fast16_t expB;
+    uint_fast32_t sigB;
+    bool signZ;
+    uint_fast32_t magBits;
+    struct exp16_sig32 normExpSig;
+    int_fast16_t expZ;
+    uint_fast32_t sigZ, uiZ;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF32UI( uiA );
+    expA  = expF32UI( uiA );
+    sigA  = fracF32UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF32UI( uiB );
+    expB  = expF32UI( uiB );
+    sigB  = fracF32UI( uiB );
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0xFF ) {
+        if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN;
+        magBits = expB | sigB;
+        goto infArg;
+    }
+    if ( expB == 0xFF ) {
+        if ( sigB ) goto propagateNaN;
+        magBits = expA | sigA;
+        goto infArg;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zero;
+        normExpSig = softfloat_normSubnormalF32Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zero;
+        normExpSig = softfloat_normSubnormalF32Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0x7F;
+    sigA = (sigA | 0x00800000)<<7;
+    sigB = (sigB | 0x00800000)<<8;
+    sigZ = softfloat_shortShiftRightJam64( (uint_fast64_t) sigA * sigB, 32 );
+    if ( sigZ < 0x40000000 ) {
+        --expZ;
+        sigZ <<= 1;
+    }
+    return softfloat_roundPackToF32( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infArg:
+    if ( ! magBits ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        uiZ = defaultNaNF32UI;
+    } else {
+        uiZ = packToF32UI( signZ, 0xFF, 0 );
+    }
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ = packToF32UI( signZ, 0, 0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_mulAdd.c b/tb/riscv-isa-sim/softfloat/f32_mulAdd.c
new file mode 100644
index 0000000000000000000000000000000000000000..e98021b75b4b5e899864b9cf20a8147a6603fdd8
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_mulAdd.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    union ui32_f32 uC;
+    uint_fast32_t uiC;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    uC.f = c;
+    uiC = uC.ui;
+    return softfloat_mulAddF32( uiA, uiB, uiC, 0 );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_rem.c b/tb/riscv-isa-sim/softfloat/f32_rem.c
new file mode 100644
index 0000000000000000000000000000000000000000..771b1b94cbbc6b44e1b7646b8dd88bcba9c0740f
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_rem.c
@@ -0,0 +1,168 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f32_rem( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast32_t sigA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+    int_fast16_t expB;
+    uint_fast32_t sigB;
+    struct exp16_sig32 normExpSig;
+    uint32_t rem;
+    int_fast16_t expDiff;
+    uint32_t q, recip32, altRem, meanRem;
+    bool signRem;
+    uint_fast32_t uiZ;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF32UI( uiA );
+    expA  = expF32UI( uiA );
+    sigA  = fracF32UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    expB = expF32UI( uiB );
+    sigB = fracF32UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0xFF ) {
+        if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN;
+        goto invalid;
+    }
+    if ( expB == 0xFF ) {
+        if ( sigB ) goto propagateNaN;
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! sigB ) goto invalid;
+        normExpSig = softfloat_normSubnormalF32Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! sigA ) return a;
+        normExpSig = softfloat_normSubnormalF32Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    rem = sigA | 0x00800000;
+    sigB |= 0x00800000;
+    expDiff = expA - expB;
+    if ( expDiff < 1 ) {
+        if ( expDiff < -1 ) return a;
+        sigB <<= 6;
+        if ( expDiff ) {
+            rem <<= 5;
+            q = 0;
+        } else {
+            rem <<= 6;
+            q = (sigB <= rem);
+            if ( q ) rem -= sigB;
+        }
+    } else {
+        recip32 = softfloat_approxRecip32_1( sigB<<8 );
+        /*--------------------------------------------------------------------
+        | Changing the shift of `rem' here requires also changing the initial
+        | subtraction from `expDiff'.
+        *--------------------------------------------------------------------*/
+        rem <<= 7;
+        expDiff -= 31;
+        /*--------------------------------------------------------------------
+        | The scale of `sigB' affects how many bits are obtained during each
+        | cycle of the loop.  Currently this is 29 bits per loop iteration,
+        | which is believed to be the maximum possible.
+        *--------------------------------------------------------------------*/
+        sigB <<= 6;
+        for (;;) {
+            q = (rem * (uint_fast64_t) recip32)>>32;
+            if ( expDiff < 0 ) break;
+            rem = -(q * (uint32_t) sigB);
+            expDiff -= 29;
+        }
+        /*--------------------------------------------------------------------
+        | (`expDiff' cannot be less than -30 here.)
+        *--------------------------------------------------------------------*/
+        q >>= ~expDiff & 31;
+        rem = (rem<<(expDiff + 30)) - q * (uint32_t) sigB;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    do {
+        altRem = rem;
+        ++q;
+        rem -= sigB;
+    } while ( ! (rem & 0x80000000) );
+    meanRem = rem + altRem;
+    if ( (meanRem & 0x80000000) || (! meanRem && (q & 1)) ) rem = altRem;
+    signRem = signA;
+    if ( 0x80000000 <= rem ) {
+        signRem = ! signRem;
+        rem = -rem;
+    }
+    return softfloat_normRoundPackToF32( signRem, expB, rem );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
+    goto uiZ;
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF32UI;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_roundToInt.c b/tb/riscv-isa-sim/softfloat/f32_roundToInt.c
new file mode 100644
index 0000000000000000000000000000000000000000..0861b84054582cc10f630a933eef09b119c2664a
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_roundToInt.c
@@ -0,0 +1,112 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f32_roundToInt( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    int_fast16_t exp;
+    uint_fast32_t uiZ, lastBitMask, roundBitsMask;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp <= 0x7E ) {
+        if ( ! (uint32_t) (uiA<<1) ) return a;
+        if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
+        uiZ = uiA & packToF32UI( 1, 0, 0 );
+        switch ( roundingMode ) {
+         case softfloat_round_near_even:
+            if ( ! fracF32UI( uiA ) ) break;
+         case softfloat_round_near_maxMag:
+            if ( exp == 0x7E ) uiZ |= packToF32UI( 0, 0x7F, 0 );
+            break;
+         case softfloat_round_min:
+            if ( uiZ ) uiZ = packToF32UI( 1, 0x7F, 0 );
+            break;
+         case softfloat_round_max:
+            if ( ! uiZ ) uiZ = packToF32UI( 0, 0x7F, 0 );
+            break;
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x96 <= exp ) {
+        if ( (exp == 0xFF) && fracF32UI( uiA ) ) {
+            uiZ = softfloat_propagateNaNF32UI( uiA, 0 );
+            goto uiZ;
+        }
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ = uiA;
+    lastBitMask = (uint_fast32_t) 1<<(0x96 - exp);
+    roundBitsMask = lastBitMask - 1;
+    if ( roundingMode == softfloat_round_near_maxMag ) {
+        uiZ += lastBitMask>>1;
+    } else if ( roundingMode == softfloat_round_near_even ) {
+        uiZ += lastBitMask>>1;
+        if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask;
+    } else if (
+        roundingMode
+            == (signF32UI( uiZ ) ? softfloat_round_min : softfloat_round_max)
+    ) {
+        uiZ += roundBitsMask;
+    }
+    uiZ &= ~roundBitsMask;
+    if ( exact && (uiZ != uiA) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_sqrt.c b/tb/riscv-isa-sim/softfloat/f32_sqrt.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ef659e4f2d696bb901461d48af6d7c12a8bd818
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_sqrt.c
@@ -0,0 +1,121 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f32_sqrt( float32_t a )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast32_t sigA, uiZ;
+    struct exp16_sig32 normExpSig;
+    int_fast16_t expZ;
+    uint_fast32_t sigZ, shiftedSigZ;
+    uint32_t negRem;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF32UI( uiA );
+    expA  = expF32UI( uiA );
+    sigA  = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0xFF ) {
+        if ( sigA ) {
+            uiZ = softfloat_propagateNaNF32UI( uiA, 0 );
+            goto uiZ;
+        }
+        if ( ! signA ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( signA ) {
+        if ( ! (expA | sigA) ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) return a;
+        normExpSig = softfloat_normSubnormalF32Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = ((expA - 0x7F)>>1) + 0x7E;
+    expA &= 1;
+    sigA = (sigA | 0x00800000)<<8;
+    sigZ =
+        ((uint_fast64_t) sigA * softfloat_approxRecipSqrt32_1( expA, sigA ))
+            >>32;
+    if ( expA ) sigZ >>= 1;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sigZ += 2;
+    if ( (sigZ & 0x3F) < 2 ) {
+        shiftedSigZ = sigZ>>2;
+        negRem = shiftedSigZ * shiftedSigZ;
+        sigZ &= ~3;
+        if ( negRem & 0x80000000 ) {
+            sigZ |= 1;
+        } else {
+            if ( negRem ) --sigZ;
+        }
+    }
+    return softfloat_roundPackToF32( 0, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF32UI;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_sub.c b/tb/riscv-isa-sim/softfloat/f32_sub.c
new file mode 100644
index 0000000000000000000000000000000000000000..d8307381daffa5cbdd2fe921928bb1be7ec95378
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_sub.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t f32_sub( float32_t a, float32_t b )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    union ui32_f32 uB;
+    uint_fast32_t uiB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1)
+    float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t );
+#endif
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
+    if ( signF32UI( uiA ^ uiB ) ) {
+        return softfloat_addMagsF32( uiA, uiB );
+    } else {
+        return softfloat_subMagsF32( uiA, uiB );
+    }
+#else
+    magsFuncPtr =
+        signF32UI( uiA ^ uiB ) ? softfloat_addMagsF32 : softfloat_subMagsF32;
+    return (*magsFuncPtr)( uiA, uiB );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_f128.c b/tb/riscv-isa-sim/softfloat/f32_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf51926461d14295895ca223a0bdba8e4fcfb7bd
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_f128.c
@@ -0,0 +1,96 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f32_to_f128( float32_t a )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t frac;
+    struct commonNaN commonNaN;
+    struct uint128 uiZ;
+    struct exp16_sig32 normExpSig;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    frac = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0xFF ) {
+        if ( frac ) {
+            softfloat_f32UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF128UI( &commonNaN );
+        } else {
+            uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
+            uiZ.v0  = 0;
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! exp ) {
+        if ( ! frac ) {
+            uiZ.v64 = packToF128UI64( sign, 0, 0 );
+            uiZ.v0  = 0;
+            goto uiZ;
+        }
+        normExpSig = softfloat_normSubnormalF32Sig( frac );
+        exp = normExpSig.exp - 1;
+        frac = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) frac<<25 );
+    uiZ.v0  = 0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_f16.c b/tb/riscv-isa-sim/softfloat/f32_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a971589952fabb43196a3b7273604d8261086f2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_f16.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t f32_to_f16( float32_t a )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t frac;
+    struct commonNaN commonNaN;
+    uint_fast16_t uiZ, frac16;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    frac = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0xFF ) {
+        if ( frac ) {
+            softfloat_f32UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF16UI( &commonNaN );
+        } else {
+            uiZ = packToF16UI( sign, 0x1F, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac16 = frac>>9 | ((frac & 0x1FF) != 0);
+    if ( ! (exp | frac16) ) {
+        uiZ = packToF16UI( sign, 0, 0 );
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    return softfloat_roundPackToF16( sign, exp - 0x71, frac16 | 0x4000 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_f64.c b/tb/riscv-isa-sim/softfloat/f32_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..f9e02f2277070d7fdbe6d325f11889290e8ec978
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_f64.c
@@ -0,0 +1,93 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f32_to_f64( float32_t a )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t frac;
+    struct commonNaN commonNaN;
+    uint_fast64_t uiZ;
+    struct exp16_sig32 normExpSig;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    frac = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0xFF ) {
+        if ( frac ) {
+            softfloat_f32UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF64UI( &commonNaN );
+        } else {
+            uiZ = packToF64UI( sign, 0x7FF, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! exp ) {
+        if ( ! frac ) {
+            uiZ = packToF64UI( sign, 0, 0 );
+            goto uiZ;
+        }
+        normExpSig = softfloat_normSubnormalF32Sig( frac );
+        exp = normExpSig.exp - 1;
+        frac = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) frac<<29 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_i32.c b/tb/riscv-isa-sim/softfloat/f32_to_i32.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9f2cf9b392158746b77fb6993e13370eab8bc83
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_i32.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f32_to_i32( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    uint_fast64_t sig64;
+    int_fast16_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    sig  = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
+    if ( (exp == 0xFF) && sig ) {
+#if (i32_fromNaN == i32_fromPosOverflow)
+        sign = 0;
+#elif (i32_fromNaN == i32_fromNegOverflow)
+        sign = 1;
+#else
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return i32_fromNaN;
+#endif
+    }
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= 0x00800000;
+    sig64 = (uint_fast64_t) sig<<32;
+    shiftDist = 0xAA - exp;
+    if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
+    return softfloat_roundToI32( sign, sig64, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_i32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f32_to_i32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a94dcc680bac0a021123d2bccaba4430ef2c4c9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_i32_r_minMag.c
@@ -0,0 +1,89 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    int_fast32_t absZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF32UI( uiA );
+    sig = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x9E - exp;
+    if ( 32 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF32UI( uiA );
+    if ( shiftDist <= 0 ) {
+        if ( uiA == packToF32UI( 1, 0x9E, 0 ) ) return -0x7FFFFFFF - 1;
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0xFF) && sig ? i32_fromNaN
+                : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig = (sig | 0x00800000)<<8;
+    absZ = sig>>shiftDist;
+    if ( exact && ((uint_fast32_t) absZ<<shiftDist != sig) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sign ? -absZ : absZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_i64.c b/tb/riscv-isa-sim/softfloat/f32_to_i64.c
new file mode 100644
index 0000000000000000000000000000000000000000..48ab46fd9a8f70e25146ddbaceb6b2951c815c8b
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_i64.c
@@ -0,0 +1,96 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f32_to_i64( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    int_fast16_t shiftDist;
+#ifdef SOFTFLOAT_FAST_INT64
+    uint_fast64_t sig64, extra;
+    struct uint64_extra sig64Extra;
+#else
+    uint32_t extSig[3];
+#endif
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    sig  = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0xBE - exp;
+    if ( shiftDist < 0 ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0xFF) && sig ? i64_fromNaN
+                : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= 0x00800000;
+#ifdef SOFTFLOAT_FAST_INT64
+    sig64 = (uint_fast64_t) sig<<40;
+    extra = 0;
+    if ( shiftDist ) {
+        sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftDist );
+        sig64 = sig64Extra.v;
+        extra = sig64Extra.extra;
+    }
+    return softfloat_roundToI64( sign, sig64, extra, roundingMode, exact );
+#else
+    extSig[indexWord( 3, 2 )] = sig<<8;
+    extSig[indexWord( 3, 1 )] = 0;
+    extSig[indexWord( 3, 0 )] = 0;
+    if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
+    return softfloat_roundMToI64( sign, extSig, roundingMode, exact );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_i64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f32_to_i64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d336a47bff28c7e2abbf7566d76769dff71b3af
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_i64_r_minMag.c
@@ -0,0 +1,94 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    uint_fast64_t sig64;
+    int_fast64_t absZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF32UI( uiA );
+    sig = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0xBE - exp;
+    if ( 64 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF32UI( uiA );
+    if ( shiftDist <= 0 ) {
+        if ( uiA == packToF32UI( 1, 0xBE, 0 ) ) {
+            return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
+        }
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0xFF) && sig ? i64_fromNaN
+                : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig |= 0x00800000;
+    sig64 = (uint_fast64_t) sig<<40;
+    absZ = sig64>>shiftDist;
+    shiftDist = 40 - shiftDist;
+    if ( exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31)) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sign ? -absZ : absZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_ui32.c b/tb/riscv-isa-sim/softfloat/f32_to_ui32.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ec279ba643dac3bbea29c9069076dd70b3ceebb
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_ui32.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f32_to_ui32( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    uint_fast64_t sig64;
+    int_fast16_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    sig  = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
+    if ( (exp == 0xFF) && sig ) {
+#if (ui32_fromNaN == ui32_fromPosOverflow)
+        sign = 0;
+#elif (ui32_fromNaN == ui32_fromNegOverflow)
+        sign = 1;
+#else
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return ui32_fromNaN;
+#endif
+    }
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= 0x00800000;
+    sig64 = (uint_fast64_t) sig<<32;
+    shiftDist = 0xAA - exp;
+    if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
+    return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_ui32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f32_to_ui32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..12f72619bfc4c9fbdeae0b036b5756ddbbedda99
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_ui32_r_minMag.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    uint_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF32UI( uiA );
+    sig = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x9E - exp;
+    if ( 32 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF32UI( uiA );
+    if ( sign || (shiftDist < 0) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0xFF) && sig ? ui32_fromNaN
+                : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig = (sig | 0x00800000)<<8;
+    z = sig>>shiftDist;
+    if ( exact && (z<<shiftDist != sig) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_ui64.c b/tb/riscv-isa-sim/softfloat/f32_to_ui64.c
new file mode 100644
index 0000000000000000000000000000000000000000..11c7b4b67d7f004e126bbc61f1646a52c5b94328
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_ui64.c
@@ -0,0 +1,96 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    int_fast16_t shiftDist;
+#ifdef SOFTFLOAT_FAST_INT64
+    uint_fast64_t sig64, extra;
+    struct uint64_extra sig64Extra;
+#else
+    uint32_t extSig[3];
+#endif
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF32UI( uiA );
+    exp  = expF32UI( uiA );
+    sig  = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0xBE - exp;
+    if ( shiftDist < 0 ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0xFF) && sig ? ui64_fromNaN
+                : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= 0x00800000;
+#ifdef SOFTFLOAT_FAST_INT64
+    sig64 = (uint_fast64_t) sig<<40;
+    extra = 0;
+    if ( shiftDist ) {
+        sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftDist );
+        sig64 = sig64Extra.v;
+        extra = sig64Extra.extra;
+    }
+    return softfloat_roundToUI64( sign, sig64, extra, roundingMode, exact );
+#else
+    extSig[indexWord( 3, 2 )] = sig<<8;
+    extSig[indexWord( 3, 1 )] = 0;
+    extSig[indexWord( 3, 0 )] = 0;
+    if ( shiftDist ) softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
+    return softfloat_roundMToUI64( sign, extSig, roundingMode, exact );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f32_to_ui64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f32_to_ui64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..f96f3e1fe64a2e8c06358b2eb6efe90fee9aad50
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f32_to_ui64_r_minMag.c
@@ -0,0 +1,90 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact )
+{
+    union ui32_f32 uA;
+    uint_fast32_t uiA;
+    int_fast16_t exp;
+    uint_fast32_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    uint_fast64_t sig64, z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF32UI( uiA );
+    sig = fracF32UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0xBE - exp;
+    if ( 64 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF32UI( uiA );
+    if ( sign || (shiftDist < 0) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0xFF) && sig ? ui64_fromNaN
+                : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig |= 0x00800000;
+    sig64 = (uint_fast64_t) sig<<40;
+    z = sig64>>shiftDist;
+    shiftDist = 40 - shiftDist;
+    if ( exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31)) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_add.c b/tb/riscv-isa-sim/softfloat/f64_add.c
new file mode 100644
index 0000000000000000000000000000000000000000..e9880ddfcd597dda41550022e386e21c454d0ed4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_add.c
@@ -0,0 +1,74 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t f64_add( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool signA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
+    float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool );
+#endif
+
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF64UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF64UI( uiB );
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+    if ( signA == signB ) {
+        return softfloat_addMagsF64( uiA, uiB, signA );
+    } else {
+        return softfloat_subMagsF64( uiA, uiB, signA );
+    }
+#else
+    magsFuncPtr =
+        (signA == signB) ? softfloat_addMagsF64 : softfloat_subMagsF64;
+    return (*magsFuncPtr)( uiA, uiB, signA );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_classify.c b/tb/riscv-isa-sim/softfloat/f64_classify.c
new file mode 100755
index 0000000000000000000000000000000000000000..180abde3cb1d5919420e3859f7fd88ab6f20404a
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_classify.c
@@ -0,0 +1,36 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast16_t f64_classify( float64_t a )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+
+    uA.f = a;
+    uiA = uA.ui;
+
+    uint_fast16_t infOrNaN = expF64UI( uiA ) == 0x7FF;
+    uint_fast16_t subnormalOrZero = expF64UI( uiA ) == 0;
+    bool sign = signF64UI( uiA );
+    bool fracZero = fracF64UI( uiA ) == 0;
+    bool isNaN = isNaNF64UI( uiA );
+    bool isSNaN = softfloat_isSigNaNF64UI( uiA );
+
+    return
+        (  sign && infOrNaN && fracZero )          << 0 |
+        (  sign && !infOrNaN && !subnormalOrZero ) << 1 |
+        (  sign && subnormalOrZero && !fracZero )  << 2 |
+        (  sign && subnormalOrZero && fracZero )   << 3 |
+        ( !sign && infOrNaN && fracZero )          << 7 |
+        ( !sign && !infOrNaN && !subnormalOrZero ) << 6 |
+        ( !sign && subnormalOrZero && !fracZero )  << 5 |
+        ( !sign && subnormalOrZero && fracZero )   << 4 |
+        ( isNaN &&  isSNaN )                       << 8 |
+        ( isNaN && !isSNaN )                       << 9;
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_div.c b/tb/riscv-isa-sim/softfloat/f64_div.c
new file mode 100644
index 0000000000000000000000000000000000000000..c5a2d4fe349500222d6ac85bc80a0208c2a5d280
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_div.c
@@ -0,0 +1,172 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f64_div( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast64_t sigA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signB;
+    int_fast16_t expB;
+    uint_fast64_t sigB;
+    bool signZ;
+    struct exp16_sig64 normExpSig;
+    int_fast16_t expZ;
+    uint32_t recip32, sig32Z, doubleTerm;
+    uint_fast64_t rem;
+    uint32_t q;
+    uint_fast64_t sigZ;
+    uint_fast64_t uiZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF64UI( uiA );
+    expA  = expF64UI( uiA );
+    sigA  = fracF64UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF64UI( uiB );
+    expB  = expF64UI( uiB );
+    sigB  = fracF64UI( uiB );
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FF ) {
+        if ( sigA ) goto propagateNaN;
+        if ( expB == 0x7FF ) {
+            if ( sigB ) goto propagateNaN;
+            goto invalid;
+        }
+        goto infinity;
+    }
+    if ( expB == 0x7FF ) {
+        if ( sigB ) goto propagateNaN;
+        goto zero;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! sigB ) {
+            if ( ! (expA | sigA) ) goto invalid;
+            softfloat_raiseFlags( softfloat_flag_infinite );
+            goto infinity;
+        }
+        normExpSig = softfloat_normSubnormalF64Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! sigA ) goto zero;
+        normExpSig = softfloat_normSubnormalF64Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA - expB + 0x3FE;
+    sigA |= UINT64_C( 0x0010000000000000 );
+    sigB |= UINT64_C( 0x0010000000000000 );
+    if ( sigA < sigB ) {
+        --expZ;
+        sigA <<= 11;
+    } else {
+        sigA <<= 10;
+    }
+    sigB <<= 11;
+    recip32 = softfloat_approxRecip32_1( sigB>>32 ) - 2;
+    sig32Z = ((uint32_t) (sigA>>32) * (uint_fast64_t) recip32)>>32;
+    doubleTerm = sig32Z<<1;
+    rem =
+        ((sigA - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28)
+            - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4);
+    q = (((uint32_t) (rem>>32) * (uint_fast64_t) recip32)>>32) + 4;
+    sigZ = ((uint_fast64_t) sig32Z<<32) + ((uint_fast64_t) q<<4);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( (sigZ & 0x1FF) < 4<<4 ) {
+        q &= ~7;
+        sigZ &= ~(uint_fast64_t) 0x7F;
+        doubleTerm = q<<1;
+        rem =
+            ((rem - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28)
+                - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4);
+        if ( rem & UINT64_C( 0x8000000000000000 ) ) {
+            sigZ -= 1<<7;
+        } else {
+            if ( rem ) sigZ |= 1;
+        }
+    }
+    return softfloat_roundPackToF64( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF64UI;
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infinity:
+    uiZ = packToF64UI( signZ, 0x7FF, 0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ = packToF64UI( signZ, 0, 0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_eq.c b/tb/riscv-isa-sim/softfloat/f64_eq.c
new file mode 100644
index 0000000000000000000000000000000000000000..ccb602a3824af4997c64ca415d4a4c839b46eb4b
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_eq.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f64_eq( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_eq_signaling.c b/tb/riscv-isa-sim/softfloat/f64_eq_signaling.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee5a4414f77396952759a25223a87fc39107e577
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_eq_signaling.c
@@ -0,0 +1,61 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f64_eq_signaling( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_isSignalingNaN.c b/tb/riscv-isa-sim/softfloat/f64_isSignalingNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..f55acb4a0281fb40e51a957b8b7e359c58d81bba
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_isSignalingNaN.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f64_isSignalingNaN( float64_t a )
+{
+    union ui64_f64 uA;
+
+    uA.f = a;
+    return softfloat_isSigNaNF64UI( uA.ui );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_le.c b/tb/riscv-isa-sim/softfloat/f64_le.c
new file mode 100644
index 0000000000000000000000000000000000000000..91fc994abe7b6f1d2023e25d53e117b7059374a6
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_le.c
@@ -0,0 +1,67 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f64_le( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF64UI( uiA );
+    signB = signF64UI( uiB );
+    return
+        (signA != signB)
+            ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+            : (uiA == uiB) || (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_le_quiet.c b/tb/riscv-isa-sim/softfloat/f64_le_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..a5d332a5b0f772d51ce58476bb9592d2a8161c00
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_le_quiet.c
@@ -0,0 +1,72 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f64_le_quiet( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF64UI( uiA );
+    signB = signF64UI( uiB );
+    return
+        (signA != signB)
+            ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+            : (uiA == uiB) || (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_lt.c b/tb/riscv-isa-sim/softfloat/f64_lt.c
new file mode 100644
index 0000000000000000000000000000000000000000..abf62fd3d530ed88236101c06b034b3f9bce5fb8
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_lt.c
@@ -0,0 +1,67 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+bool f64_lt( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return false;
+    }
+    signA = signF64UI( uiA );
+    signB = signF64UI( uiB );
+    return
+        (signA != signB)
+            ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+            : (uiA != uiB) && (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_lt_quiet.c b/tb/riscv-isa-sim/softfloat/f64_lt_quiet.c
new file mode 100644
index 0000000000000000000000000000000000000000..6531f577e624f760dcaa07aeb36cbf8d83653c58
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_lt_quiet.c
@@ -0,0 +1,72 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f64_lt_quiet( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signA, signB;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) {
+        if (
+            softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB )
+        ) {
+            softfloat_raiseFlags( softfloat_flag_invalid );
+        }
+        return false;
+    }
+    signA = signF64UI( uiA );
+    signB = signF64UI( uiB );
+    return
+        (signA != signB)
+            ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+            : (uiA != uiB) && (signA ^ (uiA < uiB));
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_mul.c b/tb/riscv-isa-sim/softfloat/f64_mul.c
new file mode 100644
index 0000000000000000000000000000000000000000..86f6654587c7be94b6bef05177e3fbca47ce7bfe
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_mul.c
@@ -0,0 +1,150 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f64_mul( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast64_t sigA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signB;
+    int_fast16_t expB;
+    uint_fast64_t sigB;
+    bool signZ;
+    uint_fast64_t magBits;
+    struct exp16_sig64 normExpSig;
+    int_fast16_t expZ;
+#ifdef SOFTFLOAT_FAST_INT64
+    struct uint128 sig128Z;
+#else
+    uint32_t sig128Z[4];
+#endif
+    uint_fast64_t sigZ, uiZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF64UI( uiA );
+    expA  = expF64UI( uiA );
+    sigA  = fracF64UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF64UI( uiB );
+    expB  = expF64UI( uiB );
+    sigB  = fracF64UI( uiB );
+    signZ = signA ^ signB;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FF ) {
+        if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN;
+        magBits = expB | sigB;
+        goto infArg;
+    }
+    if ( expB == 0x7FF ) {
+        if ( sigB ) goto propagateNaN;
+        magBits = expA | sigA;
+        goto infArg;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zero;
+        normExpSig = softfloat_normSubnormalF64Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zero;
+        normExpSig = softfloat_normSubnormalF64Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0x3FF;
+    sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10;
+    sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11;
+#ifdef SOFTFLOAT_FAST_INT64
+    sig128Z = softfloat_mul64To128( sigA, sigB );
+    sigZ = sig128Z.v64 | (sig128Z.v0 != 0);
+#else
+    softfloat_mul64To128M( sigA, sigB, sig128Z );
+    sigZ =
+        (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )];
+    if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1;
+#endif
+    if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
+        --expZ;
+        sigZ <<= 1;
+    }
+    return softfloat_roundPackToF64( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infArg:
+    if ( ! magBits ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        uiZ = defaultNaNF64UI;
+    } else {
+        uiZ = packToF64UI( signZ, 0x7FF, 0 );
+    }
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zero:
+    uiZ = packToF64UI( signZ, 0, 0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_mulAdd.c b/tb/riscv-isa-sim/softfloat/f64_mulAdd.c
new file mode 100644
index 0000000000000000000000000000000000000000..67fc44d38e51ec162ec3bd02a88ecd074f1911e3
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_mulAdd.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    union ui64_f64 uC;
+    uint_fast64_t uiC;
+
+    uA.f = a;
+    uiA = uA.ui;
+    uB.f = b;
+    uiB = uB.ui;
+    uC.f = c;
+    uiC = uC.ui;
+    return softfloat_mulAddF64( uiA, uiB, uiC, 0 );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_rem.c b/tb/riscv-isa-sim/softfloat/f64_rem.c
new file mode 100644
index 0000000000000000000000000000000000000000..e9174554211098439606459413093eab901b358d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_rem.c
@@ -0,0 +1,189 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f64_rem( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast64_t sigA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    int_fast16_t expB;
+    uint_fast64_t sigB;
+    struct exp16_sig64 normExpSig;
+    uint64_t rem;
+    int_fast16_t expDiff;
+    uint32_t q, recip32;
+    uint_fast64_t q64;
+    uint64_t altRem, meanRem;
+    bool signRem;
+    uint_fast64_t uiZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF64UI( uiA );
+    expA  = expF64UI( uiA );
+    sigA  = fracF64UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    expB = expF64UI( uiB );
+    sigB = fracF64UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FF ) {
+        if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN;
+        goto invalid;
+    }
+    if ( expB == 0x7FF ) {
+        if ( sigB ) goto propagateNaN;
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA < expB - 1 ) return a;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expB ) {
+        if ( ! sigB ) goto invalid;
+        normExpSig = softfloat_normSubnormalF64Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    if ( ! expA ) {
+        if ( ! sigA ) return a;
+        normExpSig = softfloat_normSubnormalF64Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    rem = sigA | UINT64_C( 0x0010000000000000 );
+    sigB |= UINT64_C( 0x0010000000000000 );
+    expDiff = expA - expB;
+    if ( expDiff < 1 ) {
+        if ( expDiff < -1 ) return a;
+        sigB <<= 9;
+        if ( expDiff ) {
+            rem <<= 8;
+            q = 0;
+        } else {
+            rem <<= 9;
+            q = (sigB <= rem);
+            if ( q ) rem -= sigB;
+        }
+    } else {
+        recip32 = softfloat_approxRecip32_1( sigB>>21 );
+        /*--------------------------------------------------------------------
+        | Changing the shift of `rem' here requires also changing the initial
+        | subtraction from `expDiff'.
+        *--------------------------------------------------------------------*/
+        rem <<= 9;
+        expDiff -= 30;
+        /*--------------------------------------------------------------------
+        | The scale of `sigB' affects how many bits are obtained during each
+        | cycle of the loop.  Currently this is 29 bits per loop iteration,
+        | the maximum possible.
+        *--------------------------------------------------------------------*/
+        sigB <<= 9;
+        for (;;) {
+            q64 = (uint32_t) (rem>>32) * (uint_fast64_t) recip32;
+            if ( expDiff < 0 ) break;
+            q = (q64 + 0x80000000)>>32;
+#ifdef SOFTFLOAT_FAST_INT64
+            rem <<= 29;
+#else
+            rem = (uint_fast64_t) (uint32_t) (rem>>3)<<32;
+#endif
+            rem -= q * (uint64_t) sigB;
+            if ( rem & UINT64_C( 0x8000000000000000 ) ) rem += sigB;
+            expDiff -= 29;
+        }
+        /*--------------------------------------------------------------------
+        | (`expDiff' cannot be less than -29 here.)
+        *--------------------------------------------------------------------*/
+        q = (uint32_t) (q64>>32)>>(~expDiff & 31);
+        rem = (rem<<(expDiff + 30)) - q * (uint64_t) sigB;
+        if ( rem & UINT64_C( 0x8000000000000000 ) ) {
+            altRem = rem + sigB;
+            goto selectRem;
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    do {
+        altRem = rem;
+        ++q;
+        rem -= sigB;
+    } while ( ! (rem & UINT64_C( 0x8000000000000000 )) );
+ selectRem:
+    meanRem = rem + altRem;
+    if (
+        (meanRem & UINT64_C( 0x8000000000000000 )) || (! meanRem && (q & 1))
+    ) {
+        rem = altRem;
+    }
+    signRem = signA;
+    if ( rem & UINT64_C( 0x8000000000000000 ) ) {
+        signRem = ! signRem;
+        rem = -rem;
+    }
+    return softfloat_normRoundPackToF64( signRem, expB, rem );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+    goto uiZ;
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF64UI;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_roundToInt.c b/tb/riscv-isa-sim/softfloat/f64_roundToInt.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f81007082cc019984c7698ccdd62eaf9e39fff5
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_roundToInt.c
@@ -0,0 +1,112 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    int_fast16_t exp;
+    uint_fast64_t uiZ, lastBitMask, roundBitsMask;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp <= 0x3FE ) {
+        if ( ! (uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) return a;
+        if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
+        uiZ = uiA & packToF64UI( 1, 0, 0 );
+        switch ( roundingMode ) {
+         case softfloat_round_near_even:
+            if ( ! fracF64UI( uiA ) ) break;
+         case softfloat_round_near_maxMag:
+            if ( exp == 0x3FE ) uiZ |= packToF64UI( 0, 0x3FF, 0 );
+            break;
+         case softfloat_round_min:
+            if ( uiZ ) uiZ = packToF64UI( 1, 0x3FF, 0 );
+            break;
+         case softfloat_round_max:
+            if ( ! uiZ ) uiZ = packToF64UI( 0, 0x3FF, 0 );
+            break;
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x433 <= exp ) {
+        if ( (exp == 0x7FF) && fracF64UI( uiA ) ) {
+            uiZ = softfloat_propagateNaNF64UI( uiA, 0 );
+            goto uiZ;
+        }
+        return a;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uiZ = uiA;
+    lastBitMask = (uint_fast64_t) 1<<(0x433 - exp);
+    roundBitsMask = lastBitMask - 1;
+    if ( roundingMode == softfloat_round_near_maxMag ) {
+        uiZ += lastBitMask>>1;
+    } else if ( roundingMode == softfloat_round_near_even ) {
+        uiZ += lastBitMask>>1;
+        if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask;
+    } else if (
+        roundingMode
+            == (signF64UI( uiZ ) ? softfloat_round_min : softfloat_round_max)
+    ) {
+        uiZ += roundBitsMask;
+    }
+    uiZ &= ~roundBitsMask;
+    if ( exact && (uiZ != uiA) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_sqrt.c b/tb/riscv-isa-sim/softfloat/f64_sqrt.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a06cfad3deb67dd4d72693c57f534c1466b7921
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_sqrt.c
@@ -0,0 +1,133 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t f64_sqrt( float64_t a )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool signA;
+    int_fast16_t expA;
+    uint_fast64_t sigA, uiZ;
+    struct exp16_sig64 normExpSig;
+    int_fast16_t expZ;
+    uint32_t sig32A, recipSqrt32, sig32Z;
+    uint_fast64_t rem;
+    uint32_t q;
+    uint_fast64_t sigZ, shiftedSigZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF64UI( uiA );
+    expA  = expF64UI( uiA );
+    sigA  = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FF ) {
+        if ( sigA ) {
+            uiZ = softfloat_propagateNaNF64UI( uiA, 0 );
+            goto uiZ;
+        }
+        if ( ! signA ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( signA ) {
+        if ( ! (expA | sigA) ) return a;
+        goto invalid;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) return a;
+        normExpSig = softfloat_normSubnormalF64Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    | (`sig32Z' is guaranteed to be a lower bound on the square root of
+    | `sig32A', which makes `sig32Z' also a lower bound on the square root of
+    | `sigA'.)
+    *------------------------------------------------------------------------*/
+    expZ = ((expA - 0x3FF)>>1) + 0x3FE;
+    expA &= 1;
+    sigA |= UINT64_C( 0x0010000000000000 );
+    sig32A = sigA>>21;
+    recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
+    sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
+    if ( expA ) {
+        sigA <<= 8;
+        sig32Z >>= 1;
+    } else {
+        sigA <<= 9;
+    }
+    rem = sigA - (uint_fast64_t) sig32Z * sig32Z;
+    q = ((uint32_t) (rem>>2) * (uint_fast64_t) recipSqrt32)>>32;
+    sigZ = ((uint_fast64_t) sig32Z<<32 | 1<<5) + ((uint_fast64_t) q<<3);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( (sigZ & 0x1FF) < 0x22 ) {
+        sigZ &= ~(uint_fast64_t) 0x3F;
+        shiftedSigZ = sigZ>>6;
+        rem = (sigA<<52) - shiftedSigZ * shiftedSigZ;
+        if ( rem & UINT64_C( 0x8000000000000000 ) ) {
+            --sigZ;
+        } else {
+            if ( rem ) sigZ |= 1;
+        }
+    }
+    return softfloat_roundPackToF64( 0, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF64UI;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_sub.c b/tb/riscv-isa-sim/softfloat/f64_sub.c
new file mode 100644
index 0000000000000000000000000000000000000000..0e990cd1355d9805ecbb3f133fd866f3f487b430
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_sub.c
@@ -0,0 +1,74 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t f64_sub( float64_t a, float64_t b )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool signA;
+    union ui64_f64 uB;
+    uint_fast64_t uiB;
+    bool signB;
+#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
+    float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool );
+#endif
+
+    uA.f = a;
+    uiA = uA.ui;
+    signA = signF64UI( uiA );
+    uB.f = b;
+    uiB = uB.ui;
+    signB = signF64UI( uiB );
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+    if ( signA == signB ) {
+        return softfloat_subMagsF64( uiA, uiB, signA );
+    } else {
+        return softfloat_addMagsF64( uiA, uiB, signA );
+    }
+#else
+    magsFuncPtr =
+        (signA == signB) ? softfloat_subMagsF64 : softfloat_addMagsF64;
+    return (*magsFuncPtr)( uiA, uiB, signA );
+#endif
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_f128.c b/tb/riscv-isa-sim/softfloat/f64_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..92c2d56016284211fff65d7984e6026f91676788
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_f128.c
@@ -0,0 +1,98 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f64_to_f128( float64_t a )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t frac;
+    struct commonNaN commonNaN;
+    struct uint128 uiZ;
+    struct exp16_sig64 normExpSig;
+    struct uint128 frac128;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    frac = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x7FF ) {
+        if ( frac ) {
+            softfloat_f64UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF128UI( &commonNaN );
+        } else {
+            uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
+            uiZ.v0  = 0;
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! exp ) {
+        if ( ! frac ) {
+            uiZ.v64 = packToF128UI64( sign, 0, 0 );
+            uiZ.v0  = 0;
+            goto uiZ;
+        }
+        normExpSig = softfloat_normSubnormalF64Sig( frac );
+        exp = normExpSig.exp - 1;
+        frac = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac128 = softfloat_shortShiftLeft128( 0, frac, 60 );
+    uiZ.v64 = packToF128UI64( sign, exp + 0x3C00, frac128.v64 );
+    uiZ.v0  = frac128.v0;
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_f16.c b/tb/riscv-isa-sim/softfloat/f64_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..325788c663e468d51c80e725d11fd6d248b8c0a2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_f16.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t f64_to_f16( float64_t a )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t frac;
+    struct commonNaN commonNaN;
+    uint_fast16_t uiZ, frac16;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    frac = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x7FF ) {
+        if ( frac ) {
+            softfloat_f64UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF16UI( &commonNaN );
+        } else {
+            uiZ = packToF16UI( sign, 0x1F, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac16 = softfloat_shortShiftRightJam64( frac, 38 );
+    if ( ! (exp | frac16) ) {
+        uiZ = packToF16UI( sign, 0, 0 );
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    return softfloat_roundPackToF16( sign, exp - 0x3F1, frac16 | 0x4000 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_f32.c b/tb/riscv-isa-sim/softfloat/f64_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..99b13dda47ff70ccede85016dfda76a5df616a6e
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_f32.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t f64_to_f32( float64_t a )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t frac;
+    struct commonNaN commonNaN;
+    uint_fast32_t uiZ, frac32;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    frac = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp == 0x7FF ) {
+        if ( frac ) {
+            softfloat_f64UIToCommonNaN( uiA, &commonNaN );
+            uiZ = softfloat_commonNaNToF32UI( &commonNaN );
+        } else {
+            uiZ = packToF32UI( sign, 0xFF, 0 );
+        }
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    frac32 = softfloat_shortShiftRightJam64( frac, 22 );
+    if ( ! (exp | frac32) ) {
+        uiZ = packToF32UI( sign, 0, 0 );
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    return softfloat_roundPackToF32( sign, exp - 0x381, frac32 | 0x40000000 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_i32.c b/tb/riscv-isa-sim/softfloat/f64_to_i32.c
new file mode 100644
index 0000000000000000000000000000000000000000..8712c0ac56bf56d64c163096c643c06255c3c709
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_i32.c
@@ -0,0 +1,82 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    sig  = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
+    if ( (exp == 0x7FF) && sig ) {
+#if (i32_fromNaN == i32_fromPosOverflow)
+        sign = 0;
+#elif (i32_fromNaN == i32_fromNegOverflow)
+        sign = 1;
+#else
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return i32_fromNaN;
+#endif
+    }
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
+    shiftDist = 0x427 - exp;
+    if ( 0 < shiftDist ) sig = softfloat_shiftRightJam64( sig, shiftDist );
+    return softfloat_roundToI32( sign, sig, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_i32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f64_to_i32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..b7e1e03054507247b375bfcf646f301b09084ff4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_i32_r_minMag.c
@@ -0,0 +1,96 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    int_fast32_t absZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF64UI( uiA );
+    sig = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x433 - exp;
+    if ( 53 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF64UI( uiA );
+    if ( shiftDist < 22 ) {
+        if (
+            sign && (exp == 0x41E) && (sig < UINT64_C( 0x0000000000200000 ))
+        ) {
+            if ( exact && sig ) {
+                softfloat_exceptionFlags |= softfloat_flag_inexact;
+            }
+            return -0x7FFFFFFF - 1;
+        }
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x7FF) && sig ? i32_fromNaN
+                : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig |= UINT64_C( 0x0010000000000000 );
+    absZ = sig>>shiftDist;
+    if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ<<shiftDist != sig) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sign ? -absZ : absZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_i64.c b/tb/riscv-isa-sim/softfloat/f64_to_i64.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f48843c0a8334b9633aeaa5cb3095b09aa9e1ea
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_i64.c
@@ -0,0 +1,103 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+#ifdef SOFTFLOAT_FAST_INT64
+    struct uint64_extra sigExtra;
+#else
+    uint32_t extSig[3];
+#endif
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    sig  = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
+    shiftDist = 0x433 - exp;
+#ifdef SOFTFLOAT_FAST_INT64
+    if ( shiftDist <= 0 ) {
+        if ( shiftDist < -11 ) goto invalid;
+        sigExtra.v = sig<<-shiftDist;
+        sigExtra.extra = 0;
+    } else {
+        sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist );
+    }
+    return
+        softfloat_roundToI64(
+            sign, sigExtra.v, sigExtra.extra, roundingMode, exact );
+#else
+    extSig[indexWord( 3, 0 )] = 0;
+    if ( shiftDist <= 0 ) {
+        if ( shiftDist < -11 ) goto invalid;
+        sig <<= -shiftDist;
+        extSig[indexWord( 3, 2 )] = sig>>32;
+        extSig[indexWord( 3, 1 )] = sig;
+    } else {
+        extSig[indexWord( 3, 2 )] = sig>>32;
+        extSig[indexWord( 3, 1 )] = sig;
+        softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
+    }
+    return softfloat_roundMToI64( sign, extSig, roundingMode, exact );
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return
+        (exp == 0x7FF) && fracF64UI( uiA ) ? i64_fromNaN
+            : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_i64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f64_to_i64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..3822606db3a38a2b7e2383782864acccd3583da2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_i64_r_minMag.c
@@ -0,0 +1,100 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+    int_fast64_t absZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    sig  = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x433 - exp;
+    if ( shiftDist <= 0 ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( shiftDist < -10 ) {
+            if ( uiA == packToF64UI( 1, 0x43E, 0 ) ) {
+                return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1;
+            }
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            return
+                (exp == 0x7FF) && sig ? i64_fromNaN
+                    : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig |= UINT64_C( 0x0010000000000000 );
+        absZ = sig<<-shiftDist;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( 53 <= shiftDist ) {
+            if ( exact && (exp | sig) ) {
+                softfloat_exceptionFlags |= softfloat_flag_inexact;
+            }
+            return 0;
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig |= UINT64_C( 0x0010000000000000 );
+        absZ = sig>>shiftDist;
+        if ( exact && (absZ<<shiftDist != sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+    }
+    return sign ? -absZ : absZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_ui32.c b/tb/riscv-isa-sim/softfloat/f64_to_ui32.c
new file mode 100644
index 0000000000000000000000000000000000000000..67e4d058812ff4820d55365ae90f9ae5c62b4bae
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_ui32.c
@@ -0,0 +1,82 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    sig  = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
+    if ( (exp == 0x7FF) && sig ) {
+#if (ui32_fromNaN == ui32_fromPosOverflow)
+        sign = 0;
+#elif (ui32_fromNaN == ui32_fromNegOverflow)
+        sign = 1;
+#else
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return ui32_fromNaN;
+#endif
+    }
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
+    shiftDist = 0x427 - exp;
+    if ( 0 < shiftDist ) sig = softfloat_shiftRightJam64( sig, shiftDist );
+    return softfloat_roundToUI32( sign, sig, roundingMode, exact );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_ui32_r_minMag.c b/tb/riscv-isa-sim/softfloat/f64_to_ui32_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..11f0b0501ee197efa1091690e2c11d0537b991be
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_ui32_r_minMag.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    uint_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF64UI( uiA );
+    sig = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x433 - exp;
+    if ( 53 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF64UI( uiA );
+    if ( sign || (shiftDist < 21) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        return
+            (exp == 0x7FF) && sig ? ui32_fromNaN
+                : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig |= UINT64_C( 0x0010000000000000 );
+    z = sig>>shiftDist;
+    if ( exact && ((uint_fast64_t) z<<shiftDist != sig) ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_ui64.c b/tb/riscv-isa-sim/softfloat/f64_to_ui64.c
new file mode 100644
index 0000000000000000000000000000000000000000..e92d605e5246cfe3252324551ff362332f632305
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_ui64.c
@@ -0,0 +1,103 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    bool sign;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+#ifdef SOFTFLOAT_FAST_INT64
+    struct uint64_extra sigExtra;
+#else
+    uint32_t extSig[3];
+#endif
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    sign = signF64UI( uiA );
+    exp  = expF64UI( uiA );
+    sig  = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( exp ) sig |= UINT64_C( 0x0010000000000000 );
+    shiftDist = 0x433 - exp;
+#ifdef SOFTFLOAT_FAST_INT64
+    if ( shiftDist <= 0 ) {
+        if ( shiftDist < -11 ) goto invalid;
+        sigExtra.v = sig<<-shiftDist;
+        sigExtra.extra = 0;
+    } else {
+        sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftDist );
+    }
+    return
+        softfloat_roundToUI64(
+            sign, sigExtra.v, sigExtra.extra, roundingMode, exact );
+#else
+    extSig[indexWord( 3, 0 )] = 0;
+    if ( shiftDist <= 0 ) {
+        if ( shiftDist < -11 ) goto invalid;
+        sig <<= -shiftDist;
+        extSig[indexWord( 3, 2 )] = sig>>32;
+        extSig[indexWord( 3, 1 )] = sig;
+    } else {
+        extSig[indexWord( 3, 2 )] = sig>>32;
+        extSig[indexWord( 3, 1 )] = sig;
+        softfloat_shiftRightJam96M( extSig, shiftDist, extSig );
+    }
+    return softfloat_roundMToUI64( sign, extSig, roundingMode, exact );
+#endif
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return
+        (exp == 0x7FF) && fracF64UI( uiA ) ? ui64_fromNaN
+            : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/f64_to_ui64_r_minMag.c b/tb/riscv-isa-sim/softfloat/f64_to_ui64_r_minMag.c
new file mode 100644
index 0000000000000000000000000000000000000000..25918c486d00ded642cd2c6c99190034f7c64723
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/f64_to_ui64_r_minMag.c
@@ -0,0 +1,93 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact )
+{
+    union ui64_f64 uA;
+    uint_fast64_t uiA;
+    int_fast16_t exp;
+    uint_fast64_t sig;
+    int_fast16_t shiftDist;
+    bool sign;
+    uint_fast64_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    uA.f = a;
+    uiA = uA.ui;
+    exp = expF64UI( uiA );
+    sig = fracF64UI( uiA );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 0x433 - exp;
+    if ( 53 <= shiftDist ) {
+        if ( exact && (exp | sig) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+        return 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sign = signF64UI( uiA );
+    if ( sign ) goto invalid;
+    if ( shiftDist <= 0 ) {
+        if ( shiftDist < -11 ) goto invalid;
+        z = (sig | UINT64_C( 0x0010000000000000 ))<<-shiftDist;
+    } else {
+        sig |= UINT64_C( 0x0010000000000000 );
+        z = sig>>shiftDist;
+        if ( exact && (uint64_t) (sig<<(-shiftDist & 63)) ) {
+            softfloat_exceptionFlags |= softfloat_flag_inexact;
+        }
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return
+        (exp == 0x7FF) && sig ? ui64_fromNaN
+            : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i32_to_f128.c b/tb/riscv-isa-sim/softfloat/i32_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..af7268aedeb0880d8f1d9c6f3059156304ad3e6c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i32_to_f128.c
@@ -0,0 +1,64 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t i32_to_f128( int32_t a )
+{
+    uint_fast64_t uiZ64;
+    bool sign;
+    uint_fast32_t absA;
+    int_fast8_t shiftDist;
+    union ui128_f128 uZ;
+
+    uiZ64 = 0;
+    if ( a ) {
+        sign = (a < 0);
+        absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
+        shiftDist = softfloat_countLeadingZeros32( absA ) + 17;
+        uiZ64 =
+            packToF128UI64(
+                sign, 0x402E - shiftDist, (uint_fast64_t) absA<<shiftDist );
+    }
+    uZ.ui.v64 = uiZ64;
+    uZ.ui.v0  = 0;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i32_to_f16.c b/tb/riscv-isa-sim/softfloat/i32_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..744297281211f214039a1c4090ca6b57e29acde4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i32_to_f16.c
@@ -0,0 +1,71 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t i32_to_f16( int32_t a )
+{
+    bool sign;
+    uint_fast32_t absA;
+    int_fast8_t shiftDist;
+    union ui16_f16 u;
+    uint_fast16_t sig;
+
+    sign = (a < 0);
+    absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
+    shiftDist = softfloat_countLeadingZeros32( absA ) - 21;
+    if ( 0 <= shiftDist ) {
+        u.ui =
+            a ? packToF16UI(
+                    sign, 0x18 - shiftDist, (uint_fast16_t) absA<<shiftDist )
+                : 0;
+        return u.f;
+    } else {
+        shiftDist += 4;
+        sig =
+            (shiftDist < 0)
+                ? absA>>(-shiftDist)
+                      | ((uint32_t) (absA<<(shiftDist & 31)) != 0)
+                : (uint_fast16_t) absA<<shiftDist;
+        return softfloat_roundPackToF16( sign, 0x1C - shiftDist, sig );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i32_to_f32.c b/tb/riscv-isa-sim/softfloat/i32_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..b1aedbacf9d013575912391bc01be10bb914edc2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i32_to_f32.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t i32_to_f32( int32_t a )
+{
+    bool sign;
+    union ui32_f32 uZ;
+    uint_fast32_t absA;
+
+    sign = (a < 0);
+    if ( ! (a & 0x7FFFFFFF) ) {
+        uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0;
+        return uZ.f;
+    }
+    absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
+    return softfloat_normRoundPackToF32( sign, 0x9C, absA );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i32_to_f64.c b/tb/riscv-isa-sim/softfloat/i32_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3901eb4afffdf51474209e39cc01bec2f9cf066
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i32_to_f64.c
@@ -0,0 +1,65 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t i32_to_f64( int32_t a )
+{
+    uint_fast64_t uiZ;
+    bool sign;
+    uint_fast32_t absA;
+    int_fast8_t shiftDist;
+    union ui64_f64 uZ;
+
+    if ( ! a ) {
+        uiZ = 0;
+    } else {
+        sign = (a < 0);
+        absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
+        shiftDist = softfloat_countLeadingZeros32( absA ) + 21;
+        uiZ =
+            packToF64UI(
+                sign, 0x432 - shiftDist, (uint_fast64_t) absA<<shiftDist );
+    }
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i64_to_f128.c b/tb/riscv-isa-sim/softfloat/i64_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..8eddbae2d7996715e826c22bb4052abb2c816304
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i64_to_f128.c
@@ -0,0 +1,72 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t i64_to_f128( int64_t a )
+{
+    uint_fast64_t uiZ64, uiZ0;
+    bool sign;
+    uint_fast64_t absA;
+    int_fast8_t shiftDist;
+    struct uint128 zSig;
+    union ui128_f128 uZ;
+
+    if ( ! a ) {
+        uiZ64 = 0;
+        uiZ0  = 0;
+    } else {
+        sign = (a < 0);
+        absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
+        shiftDist = softfloat_countLeadingZeros64( absA ) + 49;
+        if ( 64 <= shiftDist ) {
+            zSig.v64 = absA<<(shiftDist - 64);
+            zSig.v0  = 0;
+        } else {
+            zSig = softfloat_shortShiftLeft128( 0, absA, shiftDist );
+        }
+        uiZ64 = packToF128UI64( sign, 0x406E - shiftDist, zSig.v64 );
+        uiZ0  = zSig.v0;
+    }
+    uZ.ui.v64 = uiZ64;
+    uZ.ui.v0  = uiZ0;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i64_to_f16.c b/tb/riscv-isa-sim/softfloat/i64_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..56f019128750556a2711b9bf704dcca53979a434
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i64_to_f16.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t i64_to_f16( int64_t a )
+{
+    bool sign;
+    uint_fast64_t absA;
+    int_fast8_t shiftDist;
+    union ui16_f16 u;
+    uint_fast16_t sig;
+
+    sign = (a < 0);
+    absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
+    shiftDist = softfloat_countLeadingZeros64( absA ) - 53;
+    if ( 0 <= shiftDist ) {
+        u.ui =
+            a ? packToF16UI(
+                    sign, 0x18 - shiftDist, (uint_fast16_t) absA<<shiftDist )
+                : 0;
+        return u.f;
+    } else {
+        shiftDist += 4;
+        sig =
+            (shiftDist < 0)
+                ? softfloat_shortShiftRightJam64( absA, -shiftDist )
+                : (uint_fast16_t) absA<<shiftDist;
+        return softfloat_roundPackToF16( sign, 0x1C - shiftDist, sig );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i64_to_f32.c b/tb/riscv-isa-sim/softfloat/i64_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..e8a3494cc99df85eb82e541f6297fc8de23fdb19
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i64_to_f32.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t i64_to_f32( int64_t a )
+{
+    bool sign;
+    uint_fast64_t absA;
+    int_fast8_t shiftDist;
+    union ui32_f32 u;
+    uint_fast32_t sig;
+
+    sign = (a < 0);
+    absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
+    shiftDist = softfloat_countLeadingZeros64( absA ) - 40;
+    if ( 0 <= shiftDist ) {
+        u.ui =
+            a ? packToF32UI(
+                    sign, 0x95 - shiftDist, (uint_fast32_t) absA<<shiftDist )
+                : 0;
+        return u.f;
+    } else {
+        shiftDist += 7;
+        sig =
+            (shiftDist < 0)
+                ? softfloat_shortShiftRightJam64( absA, -shiftDist )
+                : (uint_fast32_t) absA<<shiftDist;
+        return softfloat_roundPackToF32( sign, 0x9C - shiftDist, sig );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/i64_to_f64.c b/tb/riscv-isa-sim/softfloat/i64_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..392fef9dcd16cec106fd36aaf83ed3d35c5b4b17
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/i64_to_f64.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t i64_to_f64( int64_t a )
+{
+    bool sign;
+    union ui64_f64 uZ;
+    uint_fast64_t absA;
+
+    sign = (a < 0);
+    if ( ! (a & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) {
+        uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0;
+        return uZ.f;
+    }
+    absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a;
+    return softfloat_normRoundPackToF64( sign, 0x43C, absA );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/internals.h b/tb/riscv-isa-sim/softfloat/internals.h
new file mode 100644
index 0000000000000000000000000000000000000000..55585e967e317b6cd60a68f4783b177060a33bac
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/internals.h
@@ -0,0 +1,286 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#ifndef internals_h
+#define internals_h 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "primitives.h"
+#include "softfloat_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+union ui16_f16 { uint16_t ui; float16_t f; };
+union ui32_f32 { uint32_t ui; float32_t f; };
+union ui64_f64 { uint64_t ui; float64_t f; };
+
+#ifdef SOFTFLOAT_FAST_INT64
+union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; };
+union ui128_f128 { struct uint128 ui; float128_t f; };
+#endif
+
+enum {
+    softfloat_mulAdd_subC    = 1,
+    softfloat_mulAdd_subProd = 2
+};
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool );
+
+#ifdef SOFTFLOAT_FAST_INT64
+uint_fast64_t
+ softfloat_roundToUI64(
+     bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
+#else
+uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool );
+#endif
+
+int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool );
+
+#ifdef SOFTFLOAT_FAST_INT64
+int_fast64_t
+ softfloat_roundToI64(
+     bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
+#else
+int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool );
+#endif
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15))
+#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F)
+#define fracF16UI( a ) ((a) & 0x03FF)
+#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))
+
+#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))
+
+struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; };
+struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t );
+
+float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t );
+float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t );
+
+float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t );
+float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t );
+float16_t
+ softfloat_mulAddF16(
+     uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t );
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31))
+#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF)
+#define fracF32UI( a ) ((a) & 0x007FFFFF)
+#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig))
+
+#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))
+
+struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; };
+struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t );
+
+float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t );
+float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t );
+
+float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t );
+float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t );
+float32_t
+ softfloat_mulAddF32(
+     uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t );
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63))
+#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF)
+#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))
+#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig)))
+
+#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )))
+
+struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; };
+struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t );
+
+float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t );
+float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t );
+
+float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool );
+float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool );
+float64_t
+ softfloat_mulAddF64(
+     uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15))
+#define expExtF80UI64( a64 ) ((a64) & 0x7FFF)
+#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp))
+
+#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
+
+#ifdef SOFTFLOAT_FAST_INT64
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+struct exp32_sig64 { int_fast32_t exp; uint64_t sig; };
+struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t );
+
+extFloat80_t
+ softfloat_roundPackToExtF80(
+     bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
+extFloat80_t
+ softfloat_normRoundPackToExtF80(
+     bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
+
+extFloat80_t
+ softfloat_addMagsExtF80(
+     uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
+extFloat80_t
+ softfloat_subMagsExtF80(
+     uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63))
+#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF)
+#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))
+#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64))
+
+#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))))
+
+struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; };
+struct exp32_sig128
+ softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t );
+
+float128_t
+ softfloat_roundPackToF128(
+     bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t );
+float128_t
+ softfloat_normRoundPackToF128(
+     bool, int_fast32_t, uint_fast64_t, uint_fast64_t );
+
+float128_t
+ softfloat_addMagsF128(
+     uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
+float128_t
+ softfloat_subMagsF128(
+     uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
+float128_t
+ softfloat_mulAddF128(
+     uint_fast64_t,
+     uint_fast64_t,
+     uint_fast64_t,
+     uint_fast64_t,
+     uint_fast64_t,
+     uint_fast64_t,
+     uint_fast8_t
+ );
+
+#else
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+bool
+ softfloat_tryPropagateNaNExtF80M(
+     const struct extFloat80M *,
+     const struct extFloat80M *,
+     struct extFloat80M *
+ );
+void softfloat_invalidExtF80M( struct extFloat80M * );
+
+int softfloat_normExtF80SigM( uint64_t * );
+
+void
+ softfloat_roundPackMToExtF80M(
+     bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
+void
+ softfloat_normRoundPackMToExtF80M(
+     bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
+
+void
+ softfloat_addExtF80M(
+     const struct extFloat80M *,
+     const struct extFloat80M *,
+     struct extFloat80M *,
+     bool
+ );
+
+int
+ softfloat_compareNonnormExtF80M(
+     const struct extFloat80M *, const struct extFloat80M * );
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31))
+#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF)
+#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF)
+#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96))
+
+bool softfloat_isNaNF128M( const uint32_t * );
+
+bool
+ softfloat_tryPropagateNaNF128M(
+     const uint32_t *, const uint32_t *, uint32_t * );
+void softfloat_invalidF128M( uint32_t * );
+
+int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * );
+
+void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * );
+void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * );
+
+void
+ softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool );
+void
+ softfloat_mulAddF128M(
+     const uint32_t *,
+     const uint32_t *,
+     const uint32_t *,
+     uint32_t *,
+     uint_fast8_t
+ );
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/platform.h b/tb/riscv-isa-sim/softfloat/platform.h
new file mode 100644
index 0000000000000000000000000000000000000000..03dd429fafef7c0170fa344eec1684f73ae61fef
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/platform.h
@@ -0,0 +1,48 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define LITTLEENDIAN 1
+
+#define INLINE_LEVEL 5
+#define SOFTFLOAT_FAST_INT64
+#define SOFTFLOAT_FAST_DIV64TO32
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define INLINE static inline
+
diff --git a/tb/riscv-isa-sim/softfloat/primitiveTypes.h b/tb/riscv-isa-sim/softfloat/primitiveTypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..b112049193ed608f785a6f71c91a4eedb68d39a9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/primitiveTypes.h
@@ -0,0 +1,86 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#ifndef primitiveTypes_h
+#define primitiveTypes_h 1
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifdef SOFTFLOAT_FAST_INT64
+
+#ifdef LITTLEENDIAN
+struct uint128 { uint64_t v0, v64; };
+struct uint64_extra { uint64_t extra, v; };
+struct uint128_extra { uint64_t extra; struct uint128 v; };
+#else
+struct uint128 { uint64_t v64, v0; };
+struct uint64_extra { uint64_t v, extra; };
+struct uint128_extra { struct uint128 v; uint64_t extra; };
+#endif
+
+#endif
+
+/*----------------------------------------------------------------------------
+| These macros are used to isolate the differences in word order between big-
+| endian and little-endian platforms.
+*----------------------------------------------------------------------------*/
+#ifdef LITTLEENDIAN
+#define wordIncr 1
+#define indexWord( total, n ) (n)
+#define indexWordHi( total ) ((total) - 1)
+#define indexWordLo( total ) 0
+#define indexMultiword( total, m, n ) (n)
+#define indexMultiwordHi( total, n ) ((total) - (n))
+#define indexMultiwordLo( total, n ) 0
+#define indexMultiwordHiBut( total, n ) (n)
+#define indexMultiwordLoBut( total, n ) 0
+#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 }
+#else
+#define wordIncr -1
+#define indexWord( total, n ) ((total) - 1 - (n))
+#define indexWordHi( total ) 0
+#define indexWordLo( total ) ((total) - 1)
+#define indexMultiword( total, m, n ) ((total) - 1 - (m))
+#define indexMultiwordHi( total, n ) 0
+#define indexMultiwordLo( total, n ) ((total) - (n))
+#define indexMultiwordHiBut( total, n ) 0
+#define indexMultiwordLoBut( total, n ) (n)
+#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 }
+#endif
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/primitives.h b/tb/riscv-isa-sim/softfloat/primitives.h
new file mode 100644
index 0000000000000000000000000000000000000000..1acc8a8ae104b9f0c71f714561bfa8bf254cbe9c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/primitives.h
@@ -0,0 +1,1168 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#ifndef primitives_h
+#define primitives_h 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "primitiveTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef softfloat_shortShiftRightJam64
+/*----------------------------------------------------------------------------
+| Shifts 'a' right by the number of bits given in 'dist', which must be in
+| the range 1 to 63.  If any nonzero bits are shifted off, they are "jammed"
+| into the least-significant bit of the shifted value by setting the least-
+| significant bit to 1.  This shifted-and-jammed value is returned.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
+    { return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
+#else
+uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shiftRightJam32
+/*----------------------------------------------------------------------------
+| Shifts 'a' right by the number of bits given in 'dist', which must not
+| be zero.  If any nonzero bits are shifted off, they are "jammed" into the
+| least-significant bit of the shifted value by setting the least-significant
+| bit to 1.  This shifted-and-jammed value is returned.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist' is
+| greater than 32, the result will be either 0 or 1, depending on whether 'a'
+| is zero or nonzero.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
+{
+    return
+        (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
+}
+#else
+uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shiftRightJam64
+/*----------------------------------------------------------------------------
+| Shifts 'a' right by the number of bits given in 'dist', which must not
+| be zero.  If any nonzero bits are shifted off, they are "jammed" into the
+| least-significant bit of the shifted value by setting the least-significant
+| bit to 1.  This shifted-and-jammed value is returned.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist' is
+| greater than 64, the result will be either 0 or 1, depending on whether 'a'
+| is zero or nonzero.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
+INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
+{
+    return
+        (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
+}
+#else
+uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist );
+#endif
+#endif
+
+/*----------------------------------------------------------------------------
+| A constant table that translates an 8-bit unsigned integer (the array index)
+| into the number of leading 0 bits before the most-significant 1 of that
+| integer.  For integer zero (index 0), the corresponding table element is 8.
+*----------------------------------------------------------------------------*/
+extern const uint_least8_t softfloat_countLeadingZeros8[256];
+
+#ifndef softfloat_countLeadingZeros16
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| 'a'.  If 'a' is zero, 16 is returned.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
+{
+    uint_fast8_t count = 8;
+    if ( 0x100 <= a ) {
+        count = 0;
+        a >>= 8;
+    }
+    count += softfloat_countLeadingZeros8[a];
+    return count;
+}
+#else
+uint_fast8_t softfloat_countLeadingZeros16( uint16_t a );
+#endif
+#endif
+
+#ifndef softfloat_countLeadingZeros32
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| 'a'.  If 'a' is zero, 32 is returned.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
+INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
+{
+    uint_fast8_t count = 0;
+    if ( a < 0x10000 ) {
+        count = 16;
+        a <<= 16;
+    }
+    if ( a < 0x1000000 ) {
+        count += 8;
+        a <<= 8;
+    }
+    count += softfloat_countLeadingZeros8[a>>24];
+    return count;
+}
+#else
+uint_fast8_t softfloat_countLeadingZeros32( uint32_t a );
+#endif
+#endif
+
+#ifndef softfloat_countLeadingZeros64
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| 'a'.  If 'a' is zero, 64 is returned.
+*----------------------------------------------------------------------------*/
+uint_fast8_t softfloat_countLeadingZeros64( uint64_t a );
+#endif
+
+extern const uint16_t softfloat_approxRecip_1k0s[16];
+extern const uint16_t softfloat_approxRecip_1k1s[16];
+
+#ifndef softfloat_approxRecip32_1
+/*----------------------------------------------------------------------------
+| Returns an approximation to the reciprocal of the number represented by 'a',
+| where 'a' is interpreted as an unsigned fixed-point number with one integer
+| bit and 31 fraction bits.  The 'a' input must be "normalized", meaning that
+| its most-significant bit (bit 31) must be 1.  Thus, if A is the value of
+| the fixed-point interpretation of 'a', then 1 <= A < 2.  The returned value
+| is interpreted as a pure unsigned fraction, having no integer bits and 32
+| fraction bits.  The approximation returned is never greater than the true
+| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp
+| (units in the last place).
+*----------------------------------------------------------------------------*/
+#ifdef SOFTFLOAT_FAST_DIV64TO32
+#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a)))
+#else
+uint32_t softfloat_approxRecip32_1( uint32_t a );
+#endif
+#endif
+
+extern const uint16_t softfloat_approxRecipSqrt_1k0s[16];
+extern const uint16_t softfloat_approxRecipSqrt_1k1s[16];
+
+#ifndef softfloat_approxRecipSqrt32_1
+/*----------------------------------------------------------------------------
+| Returns an approximation to the reciprocal of the square root of the number
+| represented by 'a', where 'a' is interpreted as an unsigned fixed-point
+| number either with one integer bit and 31 fraction bits or with two integer
+| bits and 30 fraction bits.  The format of 'a' is determined by 'oddExpA',
+| which must be either 0 or 1.  If 'oddExpA' is 1, 'a' is interpreted as
+| having one integer bit, and if 'oddExpA' is 0, 'a' is interpreted as having
+| two integer bits.  The 'a' input must be "normalized", meaning that its
+| most-significant bit (bit 31) must be 1.  Thus, if A is the value of the
+| fixed-point interpretation of 'a', it follows that 1 <= A < 2 when 'oddExpA'
+| is 1, and 2 <= A < 4 when 'oddExpA' is 0.
+|   The returned value is interpreted as a pure unsigned fraction, having
+| no integer bits and 32 fraction bits.  The approximation returned is never
+| greater than the true reciprocal 1/sqrt(A), and it differs from the true
+| reciprocal by at most 2.06 ulp (units in the last place).  The approximation
+| returned is also always within the range 0.5 to 1; thus, the most-
+| significant bit of the result is always set.
+*----------------------------------------------------------------------------*/
+uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
+#endif
+
+#ifdef SOFTFLOAT_FAST_INT64
+
+/*----------------------------------------------------------------------------
+| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is
+| defined.
+*----------------------------------------------------------------------------*/
+
+#ifndef softfloat_eq128
+/*----------------------------------------------------------------------------
+| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
+| and 'a0' is equal to the 128-bit unsigned integer formed by concatenating
+| 'b64' and 'b0'.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
+INLINE
+bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+    { return (a64 == b64) && (a0 == b0); }
+#else
+bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
+#endif
+#endif
+
+#ifndef softfloat_le128
+/*----------------------------------------------------------------------------
+| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
+| and 'a0' is less than or equal to the 128-bit unsigned integer formed by
+| concatenating 'b64' and 'b0'.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+    { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
+#else
+bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
+#endif
+#endif
+
+#ifndef softfloat_lt128
+/*----------------------------------------------------------------------------
+| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
+| and 'a0' is less than the 128-bit unsigned integer formed by concatenating
+| 'b64' and 'b0'.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+    { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
+#else
+bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
+#endif
+#endif
+
+#ifndef softfloat_shortShiftLeft128
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' left by the
+| number of bits given in 'dist', which must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+struct uint128
+ softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
+{
+    struct uint128 z;
+    z.v64 = a64<<dist | a0>>(-dist & 63);
+    z.v0 = a0<<dist;
+    return z;
+}
+#else
+struct uint128
+ softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shortShiftRight128
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
+| number of bits given in 'dist', which must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+struct uint128
+ softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
+{
+    struct uint128 z;
+    z.v64 = a64>>dist;
+    z.v0 = a64<<(-dist & 63) | a0>>dist;
+    return z;
+}
+#else
+struct uint128
+ softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shortShiftRightJam64Extra
+/*----------------------------------------------------------------------------
+| This function is the same as 'softfloat_shiftRightJam64Extra' (below),
+| except that 'dist' must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+struct uint64_extra
+ softfloat_shortShiftRightJam64Extra(
+     uint64_t a, uint64_t extra, uint_fast8_t dist )
+{
+    struct uint64_extra z;
+    z.v = a>>dist;
+    z.extra = a<<(-dist & 63) | (extra != 0);
+    return z;
+}
+#else
+struct uint64_extra
+ softfloat_shortShiftRightJam64Extra(
+     uint64_t a, uint64_t extra, uint_fast8_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shortShiftRightJam128
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
+| number of bits given in 'dist', which must be in the range 1 to 63.  If any
+| nonzero bits are shifted off, they are "jammed" into the least-significant
+| bit of the shifted value by setting the least-significant bit to 1.  This
+| shifted-and-jammed value is returned.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
+INLINE
+struct uint128
+ softfloat_shortShiftRightJam128(
+     uint64_t a64, uint64_t a0, uint_fast8_t dist )
+{
+    uint_fast8_t negDist = -dist;
+    struct uint128 z;
+    z.v64 = a64>>dist;
+    z.v0 =
+        a64<<(negDist & 63) | a0>>dist
+            | ((uint64_t) (a0<<(negDist & 63)) != 0);
+    return z;
+}
+#else
+struct uint128
+ softfloat_shortShiftRightJam128(
+     uint64_t a64, uint64_t a0, uint_fast8_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shortShiftRightJam128Extra
+/*----------------------------------------------------------------------------
+| This function is the same as 'softfloat_shiftRightJam128Extra' (below),
+| except that 'dist' must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
+INLINE
+struct uint128_extra
+ softfloat_shortShiftRightJam128Extra(
+     uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
+{
+    uint_fast8_t negDist = -dist;
+    struct uint128_extra z;
+    z.v.v64 = a64>>dist;
+    z.v.v0 = a64<<(negDist & 63) | a0>>dist;
+    z.extra = a0<<(negDist & 63) | (extra != 0);
+    return z;
+}
+#else
+struct uint128_extra
+ softfloat_shortShiftRightJam128Extra(
+     uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shiftRightJam64Extra
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64
+| _plus_ the number of bits given in 'dist', which must not be zero.  This
+| shifted value is at most 64 nonzero bits and is returned in the 'v' field
+| of the 'struct uint64_extra' result.  The 64-bit 'extra' field of the result
+| contains a value formed as follows from the bits that were shifted off:  The
+| _last_ bit shifted off is the most-significant bit of the 'extra' field, and
+| the other 63 bits of the 'extra' field are all zero if and only if _all_but_
+| _the_last_ bits shifted off were all zero.
+|   (This function makes more sense if 'a' and 'extra' are considered to form
+| an unsigned fixed-point number with binary point between 'a' and 'extra'.
+| This fixed-point value is shifted right by the number of bits given in
+| 'dist', and the integer part of this shifted value is returned in the 'v'
+| field of the result.  The fractional part of the shifted value is modified
+| as described above and returned in the 'extra' field of the result.)
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
+INLINE
+struct uint64_extra
+ softfloat_shiftRightJam64Extra(
+     uint64_t a, uint64_t extra, uint_fast32_t dist )
+{
+    struct uint64_extra z;
+    if ( dist < 64 ) {
+        z.v = a>>dist;
+        z.extra = a<<(-dist & 63);
+    } else {
+        z.v = 0;
+        z.extra = (dist == 64) ? a : (a != 0);
+    }
+    z.extra |= (extra != 0);
+    return z;
+}
+#else
+struct uint64_extra
+ softfloat_shiftRightJam64Extra(
+     uint64_t a, uint64_t extra, uint_fast32_t dist );
+#endif
+#endif
+
+#ifndef softfloat_shiftRightJam128
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
+| number of bits given in 'dist', which must not be zero.  If any nonzero bits
+| are shifted off, they are "jammed" into the least-significant bit of the
+| shifted value by setting the least-significant bit to 1.  This shifted-and-
+| jammed value is returned.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist' is
+| greater than 128, the result will be either 0 or 1, depending on whether the
+| original 128 bits are all zeros.
+*----------------------------------------------------------------------------*/
+struct uint128
+ softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist );
+#endif
+
+#ifndef softfloat_shiftRightJam128Extra
+/*----------------------------------------------------------------------------
+| Shifts the 192 bits formed by concatenating 'a64', 'a0', and 'extra' right
+| by 64 _plus_ the number of bits given in 'dist', which must not be zero.
+| This shifted value is at most 128 nonzero bits and is returned in the 'v'
+| field of the 'struct uint128_extra' result.  The 64-bit 'extra' field of the
+| result contains a value formed as follows from the bits that were shifted
+| off:  The _last_ bit shifted off is the most-significant bit of the 'extra'
+| field, and the other 63 bits of the 'extra' field are all zero if and only
+| if _all_but_the_last_ bits shifted off were all zero.
+|   (This function makes more sense if 'a64', 'a0', and 'extra' are considered
+| to form an unsigned fixed-point number with binary point between 'a0' and
+| 'extra'.  This fixed-point value is shifted right by the number of bits
+| given in 'dist', and the integer part of this shifted value is returned
+| in the 'v' field of the result.  The fractional part of the shifted value
+| is modified as described above and returned in the 'extra' field of the
+| result.)
+*----------------------------------------------------------------------------*/
+struct uint128_extra
+ softfloat_shiftRightJam128Extra(
+     uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist );
+#endif
+
+#ifndef softfloat_shiftRightJam256M
+/*----------------------------------------------------------------------------
+| Shifts the 256-bit unsigned integer pointed to by 'aPtr' right by the number
+| of bits given in 'dist', which must not be zero.  If any nonzero bits are
+| shifted off, they are "jammed" into the least-significant bit of the shifted
+| value by setting the least-significant bit to 1.  This shifted-and-jammed
+| value is stored at the location pointed to by 'zPtr'.  Each of 'aPtr' and
+| 'zPtr' points to an array of four 64-bit elements that concatenate in the
+| platform's normal endian order to form a 256-bit integer.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist'
+| is greater than 256, the stored result will be either 0 or 1, depending on
+| whether the original 256 bits are all zeros.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shiftRightJam256M(
+     const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr );
+#endif
+
+#ifndef softfloat_add128
+/*----------------------------------------------------------------------------
+| Returns the sum of the 128-bit integer formed by concatenating 'a64' and
+| 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'.  The
+| addition is modulo 2^128, so any carry out is lost.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+struct uint128
+ softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+    struct uint128 z;
+    z.v0 = a0 + b0;
+    z.v64 = a64 + b64 + (z.v0 < a0);
+    return z;
+}
+#else
+struct uint128
+ softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
+#endif
+#endif
+
+#ifndef softfloat_add256M
+/*----------------------------------------------------------------------------
+| Adds the two 256-bit integers pointed to by 'aPtr' and 'bPtr'.  The addition
+| is modulo 2^256, so any carry out is lost.  The sum is stored at the
+| location pointed to by 'zPtr'.  Each of 'aPtr', 'bPtr', and 'zPtr' points to
+| an array of four 64-bit elements that concatenate in the platform's normal
+| endian order to form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_add256M(
+     const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
+#endif
+
+#ifndef softfloat_sub128
+/*----------------------------------------------------------------------------
+| Returns the difference of the 128-bit integer formed by concatenating 'a64'
+| and 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'.
+| The subtraction is modulo 2^128, so any borrow out (carry out) is lost.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+struct uint128
+ softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+    struct uint128 z;
+    z.v0 = a0 - b0;
+    z.v64 = a64 - b64;
+    z.v64 -= (a0 < b0);
+    return z;
+}
+#else
+struct uint128
+ softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
+#endif
+#endif
+
+#ifndef softfloat_sub256M
+/*----------------------------------------------------------------------------
+| Subtracts the 256-bit integer pointed to by 'bPtr' from the 256-bit integer
+| pointed to by 'aPtr'.  The addition is modulo 2^256, so any borrow out
+| (carry out) is lost.  The difference is stored at the location pointed to
+| by 'zPtr'.  Each of 'aPtr', 'bPtr', and 'zPtr' points to an array of four
+| 64-bit elements that concatenate in the platform's normal endian order to
+| form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_sub256M(
+     const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
+#endif
+
+#ifndef softfloat_mul64ByShifted32To128
+/*----------------------------------------------------------------------------
+| Returns the 128-bit product of 'a', 'b', and 2^32.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
+INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
+{
+    uint_fast64_t mid;
+    struct uint128 z;
+    mid = (uint_fast64_t) (uint32_t) a * b;
+    z.v0 = mid<<32;
+    z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32);
+    return z;
+}
+#else
+struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b );
+#endif
+#endif
+
+#ifndef softfloat_mul64To128
+/*----------------------------------------------------------------------------
+| Returns the 128-bit product of 'a' and 'b'.
+*----------------------------------------------------------------------------*/
+struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b );
+#endif
+
+#ifndef softfloat_mul128By32
+/*----------------------------------------------------------------------------
+| Returns the product of the 128-bit integer formed by concatenating 'a64' and
+| 'a0', multiplied by 'b'.  The multiplication is modulo 2^128; any overflow
+| bits are discarded.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
+INLINE
+struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
+{
+    struct uint128 z;
+    uint_fast64_t mid;
+    uint_fast32_t carry;
+    z.v0 = a0 * b;
+    mid = (uint_fast64_t) (uint32_t) (a0>>32) * b;
+    carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid);
+    z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32);
+    return z;
+}
+#else
+struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b );
+#endif
+#endif
+
+#ifndef softfloat_mul128To256M
+/*----------------------------------------------------------------------------
+| Multiplies the 128-bit unsigned integer formed by concatenating 'a64' and
+| 'a0' by the 128-bit unsigned integer formed by concatenating 'b64' and
+| 'b0'.  The 256-bit product is stored at the location pointed to by 'zPtr'.
+| Argument 'zPtr' points to an array of four 64-bit elements that concatenate
+| in the platform's normal endian order to form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_mul128To256M(
+     uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr );
+#endif
+
+#else
+
+/*----------------------------------------------------------------------------
+| The following functions are needed only when 'SOFTFLOAT_FAST_INT64' is not
+| defined.
+*----------------------------------------------------------------------------*/
+
+#ifndef softfloat_compare96M
+/*----------------------------------------------------------------------------
+| Compares the two 96-bit unsigned integers pointed to by 'aPtr' and 'bPtr'.
+| Returns -1 if the first integer (A) is less than the second (B); returns 0
+| if the two integers are equal; and returns +1 if the first integer (A)
+| is greater than the second (B).  (The result is thus the signum of A - B.)
+| Each of 'aPtr' and 'bPtr' points to an array of three 32-bit elements that
+| concatenate in the platform's normal endian order to form a 96-bit integer.
+*----------------------------------------------------------------------------*/
+int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr );
+#endif
+
+#ifndef softfloat_compare128M
+/*----------------------------------------------------------------------------
+| Compares the two 128-bit unsigned integers pointed to by 'aPtr' and 'bPtr'.
+| Returns -1 if the first integer (A) is less than the second (B); returns 0
+| if the two integers are equal; and returns +1 if the first integer (A)
+| is greater than the second (B).  (The result is thus the signum of A - B.)
+| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
+| concatenate in the platform's normal endian order to form a 128-bit integer.
+*----------------------------------------------------------------------------*/
+int_fast8_t
+ softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr );
+#endif
+
+#ifndef softfloat_shortShiftLeft64To96M
+/*----------------------------------------------------------------------------
+| Extends 'a' to 96 bits and shifts the value left by the number of bits given
+| in 'dist', which must be in the range 1 to 31.  The result is stored at the
+| location pointed to by 'zPtr'.  Argument 'zPtr' points to an array of three
+| 32-bit elements that concatenate in the platform's normal endian order to
+| form a 96-bit integer.
+*----------------------------------------------------------------------------*/
+#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
+INLINE
+void
+ softfloat_shortShiftLeft64To96M(
+     uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
+{
+    zPtr[indexWord( 3, 0 )] = (uint32_t) a<<dist;
+    a >>= 32 - dist;
+    zPtr[indexWord( 3, 2 )] = a>>32;
+    zPtr[indexWord( 3, 1 )] = a;
+}
+#else
+void
+ softfloat_shortShiftLeft64To96M(
+     uint64_t a, uint_fast8_t dist, uint32_t *zPtr );
+#endif
+#endif
+
+#ifndef softfloat_shortShiftLeftM
+/*----------------------------------------------------------------------------
+| Shifts the N-bit unsigned integer pointed to by 'aPtr' left by the number
+| of bits given in 'dist', where N = 'size_words' * 32.  The value of 'dist'
+| must be in the range 1 to 31.  Any nonzero bits shifted off are lost.  The
+| shifted N-bit result is stored at the location pointed to by 'zPtr'.  Each
+| of 'aPtr' and 'zPtr' points to a 'size_words'-long array of 32-bit elements
+| that concatenate in the platform's normal endian order to form an N-bit
+| integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shortShiftLeftM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint_fast8_t dist,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_shortShiftLeft96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shortShiftLeftM' with
+| 'size_words' = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shortShiftLeft128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shortShiftLeftM' with
+| 'size_words' = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shortShiftLeft160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shortShiftLeftM' with
+| 'size_words' = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftLeftM
+/*----------------------------------------------------------------------------
+| Shifts the N-bit unsigned integer pointed to by 'aPtr' left by the number
+| of bits given in 'dist', where N = 'size_words' * 32.  The value of 'dist'
+| must not be zero.  Any nonzero bits shifted off are lost.  The shifted
+| N-bit result is stored at the location pointed to by 'zPtr'.  Each of 'aPtr'
+| and 'zPtr' points to a 'size_words'-long array of 32-bit elements that
+| concatenate in the platform's normal endian order to form an N-bit integer.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist' is
+| greater than N, the stored result will be 0.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shiftLeftM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint32_t dist,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_shiftLeft96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftLeftM' with
+| 'size_words' = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftLeft96M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 3, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftLeft128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftLeftM' with
+| 'size_words' = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftLeft160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftLeftM' with
+| 'size_words' = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftLeft160M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 5, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shortShiftRightM
+/*----------------------------------------------------------------------------
+| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
+| of bits given in 'dist', where N = 'size_words' * 32.  The value of 'dist'
+| must be in the range 1 to 31.  Any nonzero bits shifted off are lost.  The
+| shifted N-bit result is stored at the location pointed to by 'zPtr'.  Each
+| of 'aPtr' and 'zPtr' points to a 'size_words'-long array of 32-bit elements
+| that concatenate in the platform's normal endian order to form an N-bit
+| integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shortShiftRightM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint_fast8_t dist,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_shortShiftRight128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shortShiftRightM' with
+| 'size_words' = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_shortShiftRight128M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 4, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shortShiftRight160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shortShiftRightM' with
+| 'size_words' = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_shortShiftRight160M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 5, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shortShiftRightJamM
+/*----------------------------------------------------------------------------
+| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
+| of bits given in 'dist', where N = 'size_words' * 32.  The value of 'dist'
+| must be in the range 1 to 31.  If any nonzero bits are shifted off, they are
+| "jammed" into the least-significant bit of the shifted value by setting the
+| least-significant bit to 1.  This shifted-and-jammed N-bit result is stored
+| at the location pointed to by 'zPtr'.  Each of 'aPtr' and 'zPtr' points
+| to a 'size_words'-long array of 32-bit elements that concatenate in the
+| platform's normal endian order to form an N-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shortShiftRightJamM(
+     uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * );
+#endif
+
+#ifndef softfloat_shortShiftRightJam160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shortShiftRightJamM' with
+| 'size_words' = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_shortShiftRightJam160M( aPtr, dist, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftRightM
+/*----------------------------------------------------------------------------
+| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
+| of bits given in 'dist', where N = 'size_words' * 32.  The value of 'dist'
+| must not be zero.  Any nonzero bits shifted off are lost.  The shifted
+| N-bit result is stored at the location pointed to by 'zPtr'.  Each of 'aPtr'
+| and 'zPtr' points to a 'size_words'-long array of 32-bit elements that
+| concatenate in the platform's normal endian order to form an N-bit integer.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist' is
+| greater than N, the stored result will be 0.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shiftRightM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint32_t dist,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_shiftRight96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftRightM' with
+| 'size_words' = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftRight96M( aPtr, dist, zPtr ) softfloat_shiftRightM( 3, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftRightJamM
+/*----------------------------------------------------------------------------
+| Shifts the N-bit unsigned integer pointed to by 'aPtr' right by the number
+| of bits given in 'dist', where N = 'size_words' * 32.  The value of 'dist'
+| must not be zero.  If any nonzero bits are shifted off, they are "jammed"
+| into the least-significant bit of the shifted value by setting the least-
+| significant bit to 1.  This shifted-and-jammed N-bit result is stored
+| at the location pointed to by 'zPtr'.  Each of 'aPtr' and 'zPtr' points
+| to a 'size_words'-long array of 32-bit elements that concatenate in the
+| platform's normal endian order to form an N-bit integer.
+|   The value of 'dist' can be arbitrarily large.  In particular, if 'dist'
+| is greater than N, the stored result will be either 0 or 1, depending on
+| whether the original N bits are all zeros.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shiftRightJamM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint32_t dist,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_shiftRightJam96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftRightJamM' with
+| 'size_words' = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftRightJam96M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 3, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftRightJam128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftRightJamM' with
+| 'size_words' = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftRightJam128M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 4, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_shiftRightJam160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_shiftRightJamM' with
+| 'size_words' = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr )
+#endif
+
+#ifndef softfloat_addM
+/*----------------------------------------------------------------------------
+| Adds the two N-bit integers pointed to by 'aPtr' and 'bPtr', where N =
+| 'size_words' * 32.  The addition is modulo 2^N, so any carry out is lost.
+| The N-bit sum is stored at the location pointed to by 'zPtr'.  Each of
+| 'aPtr', 'bPtr', and 'zPtr' points to a 'size_words'-long array of 32-bit
+| elements that concatenate in the platform's normal endian order to form an
+| N-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_addM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_add96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_addM' with 'size_words'
+| = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr )
+#endif
+
+#ifndef softfloat_add128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_addM' with 'size_words'
+| = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr )
+#endif
+
+#ifndef softfloat_add160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_addM' with 'size_words'
+| = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr )
+#endif
+
+#ifndef softfloat_addCarryM
+/*----------------------------------------------------------------------------
+| Adds the two N-bit unsigned integers pointed to by 'aPtr' and 'bPtr', where
+| N = 'size_words' * 32, plus 'carry', which must be either 0 or 1.  The N-bit
+| sum (modulo 2^N) is stored at the location pointed to by 'zPtr', and any
+| carry out is returned as the result.  Each of 'aPtr', 'bPtr', and 'zPtr'
+| points to a 'size_words'-long array of 32-bit elements that concatenate in
+| the platform's normal endian order to form an N-bit integer.
+*----------------------------------------------------------------------------*/
+uint_fast8_t
+ softfloat_addCarryM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint_fast8_t carry,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_addComplCarryM
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_addCarryM', except that
+| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
+| before the addition.
+*----------------------------------------------------------------------------*/
+uint_fast8_t
+ softfloat_addComplCarryM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint_fast8_t carry,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_addComplCarry96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_addComplCarryM' with
+| 'size_words' = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr )
+#endif
+
+#ifndef softfloat_negXM
+/*----------------------------------------------------------------------------
+| Replaces the N-bit unsigned integer pointed to by 'zPtr' by the
+| 2s-complement of itself, where N = 'size_words' * 32.  Argument 'zPtr'
+| points to a 'size_words'-long array of 32-bit elements that concatenate in
+| the platform's normal endian order to form an N-bit integer.
+*----------------------------------------------------------------------------*/
+void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
+#endif
+
+#ifndef softfloat_negX96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_negXM' with 'size_words'
+| = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr )
+#endif
+
+#ifndef softfloat_negX128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_negXM' with 'size_words'
+| = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr )
+#endif
+
+#ifndef softfloat_negX160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_negXM' with 'size_words'
+| = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr )
+#endif
+
+#ifndef softfloat_negX256M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_negXM' with 'size_words'
+| = 8 (N = 256).
+*----------------------------------------------------------------------------*/
+#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr )
+#endif
+
+#ifndef softfloat_sub1XM
+/*----------------------------------------------------------------------------
+| Subtracts 1 from the N-bit integer pointed to by 'zPtr', where N =
+| 'size_words' * 32.  The subtraction is modulo 2^N, so any borrow out (carry
+| out) is lost.  Argument 'zPtr' points to a 'size_words'-long array of 32-bit
+| elements that concatenate in the platform's normal endian order to form an
+| N-bit integer.
+*----------------------------------------------------------------------------*/
+void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
+#endif
+
+#ifndef softfloat_sub1X96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_sub1XM' with 'size_words'
+| = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr )
+#endif
+
+#ifndef softfloat_sub1X160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_sub1XM' with 'size_words'
+| = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr )
+#endif
+
+#ifndef softfloat_subM
+/*----------------------------------------------------------------------------
+| Subtracts the two N-bit integers pointed to by 'aPtr' and 'bPtr', where N =
+| 'size_words' * 32.  The subtraction is modulo 2^N, so any borrow out (carry
+| out) is lost.  The N-bit difference is stored at the location pointed to by
+| 'zPtr'.  Each of 'aPtr', 'bPtr', and 'zPtr' points to a 'size_words'-long
+| array of 32-bit elements that concatenate in the platform's normal endian
+| order to form an N-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_subM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_sub96M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_subM' with 'size_words'
+| = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr )
+#endif
+
+#ifndef softfloat_sub128M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_subM' with 'size_words'
+| = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr )
+#endif
+
+#ifndef softfloat_sub160M
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_subM' with 'size_words'
+| = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr )
+#endif
+
+#ifndef softfloat_mul64To128M
+/*----------------------------------------------------------------------------
+| Multiplies 'a' and 'b' and stores the 128-bit product at the location
+| pointed to by 'zPtr'.  Argument 'zPtr' points to an array of four 32-bit
+| elements that concatenate in the platform's normal endian order to form a
+| 128-bit integer.
+*----------------------------------------------------------------------------*/
+void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr );
+#endif
+
+#ifndef softfloat_mul128MTo256M
+/*----------------------------------------------------------------------------
+| Multiplies the two 128-bit unsigned integers pointed to by 'aPtr' and
+| 'bPtr', and stores the 256-bit product at the location pointed to by 'zPtr'.
+| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
+| concatenate in the platform's normal endian order to form a 128-bit integer.
+| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate
+| to form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_mul128MTo256M(
+     const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr );
+#endif
+
+#ifndef softfloat_remStepMBy32
+/*----------------------------------------------------------------------------
+| Performs a "remainder reduction step" as follows:  Arguments 'remPtr' and
+| 'bPtr' both point to N-bit unsigned integers, where N = 'size_words' * 32.
+| Defining R and B as the values of those integers, the expression (R<<'dist')
+| - B * q is computed modulo 2^N, and the N-bit result is stored at the
+| location pointed to by 'zPtr'.  Each of 'remPtr', 'bPtr', and 'zPtr' points
+| to a 'size_words'-long array of 32-bit elements that concatenate in the
+| platform's normal endian order to form an N-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_remStepMBy32(
+     uint_fast8_t size_words,
+     const uint32_t *remPtr,
+     uint_fast8_t dist,
+     const uint32_t *bPtr,
+     uint32_t q,
+     uint32_t *zPtr
+ );
+#endif
+
+#ifndef softfloat_remStep96MBy32
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_remStepMBy32' with
+| 'size_words' = 3 (N = 96).
+*----------------------------------------------------------------------------*/
+#define softfloat_remStep96MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, dist, bPtr, q, zPtr )
+#endif
+
+#ifndef softfloat_remStep128MBy32
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_remStepMBy32' with
+| 'size_words' = 4 (N = 128).
+*----------------------------------------------------------------------------*/
+#define softfloat_remStep128MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, dist, bPtr, q, zPtr )
+#endif
+
+#ifndef softfloat_remStep160MBy32
+/*----------------------------------------------------------------------------
+| This function or macro is the same as 'softfloat_remStepMBy32' with
+| 'size_words' = 5 (N = 160).
+*----------------------------------------------------------------------------*/
+#define softfloat_remStep160MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, dist, bPtr, q, zPtr )
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_add128.c b/tb/riscv-isa-sim/softfloat/s_add128.c
new file mode 100644
index 0000000000000000000000000000000000000000..8065656a7606ba8c42fd7de9e56473c627b608b2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_add128.c
@@ -0,0 +1,55 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_add128
+
+struct uint128
+ softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+    struct uint128 z;
+
+    z.v0 = a0 + b0;
+    z.v64 = a64 + b64 + (z.v0 < a0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_add256M.c b/tb/riscv-isa-sim/softfloat/s_add256M.c
new file mode 100644
index 0000000000000000000000000000000000000000..d07b0046a4c2317a77a4f599d565fa39ed4f9a48
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_add256M.c
@@ -0,0 +1,65 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_add256M
+
+void
+ softfloat_add256M(
+     const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr )
+{
+    unsigned int index;
+    uint_fast8_t carry;
+    uint64_t wordA, wordZ;
+
+    index = indexWordLo( 4 );
+    carry = 0;
+    for (;;) {
+        wordA = aPtr[index];
+        wordZ = wordA + bPtr[index] + carry;
+        zPtr[index] = wordZ;
+        if ( index == indexWordHi( 4 ) ) break;
+        if ( wordZ != wordA ) carry = (wordZ < wordA);
+        index += wordIncr;
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addCarryM.c b/tb/riscv-isa-sim/softfloat/s_addCarryM.c
new file mode 100644
index 0000000000000000000000000000000000000000..fae1db49811ed8c834581069afb7567d38bda2cd
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addCarryM.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_addCarryM
+
+uint_fast8_t
+ softfloat_addCarryM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint_fast8_t carry,
+     uint32_t *zPtr
+ )
+{
+    unsigned int index, lastIndex;
+    uint32_t wordA, wordZ;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    for (;;) {
+        wordA = aPtr[index];
+        wordZ = wordA + bPtr[index] + carry;
+        zPtr[index] = wordZ;
+        if ( wordZ != wordA ) carry = (wordZ < wordA);
+        if ( index == lastIndex ) break;
+        index += wordIncr;
+    }
+    return carry;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addComplCarryM.c b/tb/riscv-isa-sim/softfloat/s_addComplCarryM.c
new file mode 100644
index 0000000000000000000000000000000000000000..02f2bce431d42169f73660b3ca7faeca3bd54832
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addComplCarryM.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_addComplCarryM
+
+uint_fast8_t
+ softfloat_addComplCarryM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint_fast8_t carry,
+     uint32_t *zPtr
+ )
+{
+    unsigned int index, lastIndex;
+    uint32_t wordA, wordZ;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    for (;;) {
+        wordA = aPtr[index];
+        wordZ = wordA + ~bPtr[index] + carry;
+        zPtr[index] = wordZ;
+        if ( wordZ != wordA ) carry = (wordZ < wordA);
+        if ( index == lastIndex ) break;
+        index += wordIncr;
+    }
+    return carry;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addM.c b/tb/riscv-isa-sim/softfloat/s_addM.c
new file mode 100644
index 0000000000000000000000000000000000000000..a06eda65ac454e3e36a649e12fcd552d5dd2d6bc
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addM.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_addM
+
+void
+ softfloat_addM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint32_t *zPtr
+ )
+{
+    unsigned int index, lastIndex;
+    uint_fast8_t carry;
+    uint32_t wordA, wordZ;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    carry = 0;
+    for (;;) {
+        wordA = aPtr[index];
+        wordZ = wordA + bPtr[index] + carry;
+        zPtr[index] = wordZ;
+        if ( index == lastIndex ) break;
+        if ( wordZ != wordA ) carry = (wordZ < wordA);
+        index += wordIncr;
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addMagsF128.c b/tb/riscv-isa-sim/softfloat/s_addMagsF128.c
new file mode 100644
index 0000000000000000000000000000000000000000..292f0aa5fcd83d6bb02f4d1177b5befb3a4410b2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addMagsF128.c
@@ -0,0 +1,154 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+
+float128_t
+ softfloat_addMagsF128(
+     uint_fast64_t uiA64,
+     uint_fast64_t uiA0,
+     uint_fast64_t uiB64,
+     uint_fast64_t uiB0,
+     bool signZ
+ )
+{
+    int_fast32_t expA;
+    struct uint128 sigA;
+    int_fast32_t expB;
+    struct uint128 sigB;
+    int_fast32_t expDiff;
+    struct uint128 uiZ, sigZ;
+    int_fast32_t expZ;
+    uint_fast64_t sigZExtra;
+    struct uint128_extra sig128Extra;
+    union ui128_f128 uZ;
+
+    expA = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    expB = expF128UI64( uiB64 );
+    sigB.v64 = fracF128UI64( uiB64 );
+    sigB.v0  = uiB0;
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        if ( expA == 0x7FFF ) {
+            if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
+            uiZ.v64 = uiA64;
+            uiZ.v0  = uiA0;
+            goto uiZ;
+        }
+        sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
+        if ( ! expA ) {
+            uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 );
+            uiZ.v0  = sigZ.v0;
+            goto uiZ;
+        }
+        expZ = expA;
+        sigZ.v64 |= UINT64_C( 0x0002000000000000 );
+        sigZExtra = 0;
+        goto shiftRight1;
+    }
+    if ( expDiff < 0 ) {
+        if ( expB == 0x7FFF ) {
+            if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
+            uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
+            uiZ.v0  = 0;
+            goto uiZ;
+        }
+        expZ = expB;
+        if ( expA ) {
+            sigA.v64 |= UINT64_C( 0x0001000000000000 );
+        } else {
+            ++expDiff;
+            sigZExtra = 0;
+            if ( ! expDiff ) goto newlyAligned;
+        }
+        sig128Extra =
+            softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff );
+        sigA = sig128Extra.v;
+        sigZExtra = sig128Extra.extra;
+    } else {
+        if ( expA == 0x7FFF ) {
+            if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
+            uiZ.v64 = uiA64;
+            uiZ.v0  = uiA0;
+            goto uiZ;
+        }
+        expZ = expA;
+        if ( expB ) {
+            sigB.v64 |= UINT64_C( 0x0001000000000000 );
+        } else {
+            --expDiff;
+            sigZExtra = 0;
+            if ( ! expDiff ) goto newlyAligned;
+        }
+        sig128Extra =
+            softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff );
+        sigB = sig128Extra.v;
+        sigZExtra = sig128Extra.extra;
+    }
+ newlyAligned:
+    sigZ =
+        softfloat_add128(
+            sigA.v64 | UINT64_C( 0x0001000000000000 ),
+            sigA.v0,
+            sigB.v64,
+            sigB.v0
+        );
+    --expZ;
+    if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack;
+    ++expZ;
+ shiftRight1:
+    sig128Extra =
+        softfloat_shortShiftRightJam128Extra(
+            sigZ.v64, sigZ.v0, sigZExtra, 1 );
+    sigZ = sig128Extra.v;
+    sigZExtra = sig128Extra.extra;
+ roundAndPack:
+    return
+        softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addMagsF16.c b/tb/riscv-isa-sim/softfloat/s_addMagsF16.c
new file mode 100644
index 0000000000000000000000000000000000000000..4204c1e0297967385a46bdc717c30ccc2ea4bdba
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addMagsF16.c
@@ -0,0 +1,183 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t softfloat_addMagsF16( uint_fast16_t uiA, uint_fast16_t uiB )
+{
+    int_fast8_t expA;
+    uint_fast16_t sigA;
+    int_fast8_t expB;
+    uint_fast16_t sigB;
+    int_fast8_t expDiff;
+    uint_fast16_t uiZ;
+    bool signZ;
+    int_fast8_t expZ;
+    uint_fast16_t sigZ;
+    uint_fast16_t sigX, sigY;
+    int_fast8_t shiftDist;
+    uint_fast32_t sig32Z;
+    int_fast8_t roundingMode;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expA = expF16UI( uiA );
+    sigA = fracF16UI( uiA );
+    expB = expF16UI( uiB );
+    sigB = fracF16UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( ! expA ) {
+            uiZ = uiA + sigB;
+            goto uiZ;
+        }
+        if ( expA == 0x1F ) {
+            if ( sigA | sigB ) goto propagateNaN;
+            uiZ = uiA;
+            goto uiZ;
+        }
+        signZ = signF16UI( uiA );
+        expZ = expA;
+        sigZ = 0x0800 + sigA + sigB;
+        if ( ! (sigZ & 1) && (expZ < 0x1E) ) {
+            sigZ >>= 1;
+            goto pack;
+        }
+        sigZ <<= 3;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        signZ = signF16UI( uiA );
+        if ( expDiff < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            if ( expB == 0x1F ) {
+                if ( sigB ) goto propagateNaN;
+                uiZ = packToF16UI( signZ, 0x1F, 0 );
+                goto uiZ;
+            }
+            if ( expDiff <= -13 ) {
+                uiZ = packToF16UI( signZ, expB, sigB );
+                if ( expA | sigA ) goto addEpsilon;
+                goto uiZ;
+            }
+            expZ = expB;
+            sigX = sigB | 0x0400;
+            sigY = sigA + (expA ? 0x0400 : sigA);
+            shiftDist = 19 + expDiff;
+        } else {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            uiZ = uiA;
+            if ( expA == 0x1F ) {
+                if ( sigA ) goto propagateNaN;
+                goto uiZ;
+            }
+            if ( 13 <= expDiff ) {
+                if ( expB | sigB ) goto addEpsilon;
+                goto uiZ;
+            }
+            expZ = expA;
+            sigX = sigA | 0x0400;
+            sigY = sigB + (expB ? 0x0400 : sigB);
+            shiftDist = 19 - expDiff;
+        }
+        sig32Z =
+            ((uint_fast32_t) sigX<<19) + ((uint_fast32_t) sigY<<shiftDist);
+        if ( sig32Z < 0x40000000 ) {
+            --expZ;
+            sig32Z <<= 1;
+        }
+        sigZ = sig32Z>>16;
+        if ( sig32Z & 0xFFFF ) {
+            sigZ |= 1;
+        } else {
+            if ( ! (sigZ & 0xF) && (expZ < 0x1E) ) {
+                sigZ >>= 4;
+                goto pack;
+            }
+        }
+    }
+    return softfloat_roundPackToF16( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ addEpsilon:
+    roundingMode = softfloat_roundingMode;
+    if ( roundingMode != softfloat_round_near_even ) {
+        if (
+            roundingMode
+                == (signF16UI( uiZ ) ? softfloat_round_min
+                        : softfloat_round_max)
+        ) {
+            ++uiZ;
+            if ( (uint16_t) (uiZ<<1) == 0xF800 ) {
+                softfloat_raiseFlags(
+                    softfloat_flag_overflow | softfloat_flag_inexact );
+            }
+        }
+#ifdef SOFTFLOAT_ROUND_ODD
+        else if ( roundingMode == softfloat_round_odd ) {
+            uiZ |= 1;
+        }
+#endif
+    }
+    softfloat_exceptionFlags |= softfloat_flag_inexact;
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ pack:
+    uiZ = packToF16UI( signZ, expZ, sigZ );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addMagsF32.c b/tb/riscv-isa-sim/softfloat/s_addMagsF32.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba647814d7ff93e3f32a58c148c189cfc4b9e8b9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addMagsF32.c
@@ -0,0 +1,126 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+
+float32_t softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
+{
+    int_fast16_t expA;
+    uint_fast32_t sigA;
+    int_fast16_t expB;
+    uint_fast32_t sigB;
+    int_fast16_t expDiff;
+    uint_fast32_t uiZ;
+    bool signZ;
+    int_fast16_t expZ;
+    uint_fast32_t sigZ;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expA = expF32UI( uiA );
+    sigA = fracF32UI( uiA );
+    expB = expF32UI( uiB );
+    sigB = fracF32UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( ! expA ) {
+            uiZ = uiA + sigB;
+            goto uiZ;
+        }
+        if ( expA == 0xFF ) {
+            if ( sigA | sigB ) goto propagateNaN;
+            uiZ = uiA;
+            goto uiZ;
+        }
+        signZ = signF32UI( uiA );
+        expZ = expA;
+        sigZ = 0x01000000 + sigA + sigB;
+        if ( ! (sigZ & 1) && (expZ < 0xFE) ) {
+            uiZ = packToF32UI( signZ, expZ, sigZ>>1 );
+            goto uiZ;
+        }
+        sigZ <<= 6;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        signZ = signF32UI( uiA );
+        sigA <<= 6;
+        sigB <<= 6;
+        if ( expDiff < 0 ) {
+            if ( expB == 0xFF ) {
+                if ( sigB ) goto propagateNaN;
+                uiZ = packToF32UI( signZ, 0xFF, 0 );
+                goto uiZ;
+            }
+            expZ = expB;
+            sigA += expA ? 0x20000000 : sigA;
+            sigA = softfloat_shiftRightJam32( sigA, -expDiff );
+        } else {
+            if ( expA == 0xFF ) {
+                if ( sigA ) goto propagateNaN;
+                uiZ = uiA;
+                goto uiZ;
+            }
+            expZ = expA;
+            sigB += expB ? 0x20000000 : sigB;
+            sigB = softfloat_shiftRightJam32( sigB, expDiff );
+        }
+        sigZ = 0x20000000 + sigA + sigB;
+        if ( sigZ < 0x40000000 ) {
+            --expZ;
+            sigZ <<= 1;
+        }
+    }
+    return softfloat_roundPackToF32( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_addMagsF64.c b/tb/riscv-isa-sim/softfloat/s_addMagsF64.c
new file mode 100644
index 0000000000000000000000000000000000000000..63e1afe9d4da78603d1cc2bcb19d4cac5d60b1e3
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_addMagsF64.c
@@ -0,0 +1,128 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+
+float64_t
+ softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ )
+{
+    int_fast16_t expA;
+    uint_fast64_t sigA;
+    int_fast16_t expB;
+    uint_fast64_t sigB;
+    int_fast16_t expDiff;
+    uint_fast64_t uiZ;
+    int_fast16_t expZ;
+    uint_fast64_t sigZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expA = expF64UI( uiA );
+    sigA = fracF64UI( uiA );
+    expB = expF64UI( uiB );
+    sigB = fracF64UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( ! expA ) {
+            uiZ = uiA + sigB;
+            goto uiZ;
+        }
+        if ( expA == 0x7FF ) {
+            if ( sigA | sigB ) goto propagateNaN;
+            uiZ = uiA;
+            goto uiZ;
+        }
+        expZ = expA;
+        sigZ = UINT64_C( 0x0020000000000000 ) + sigA + sigB;
+        sigZ <<= 9;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sigA <<= 9;
+        sigB <<= 9;
+        if ( expDiff < 0 ) {
+            if ( expB == 0x7FF ) {
+                if ( sigB ) goto propagateNaN;
+                uiZ = packToF64UI( signZ, 0x7FF, 0 );
+                goto uiZ;
+            }
+            expZ = expB;
+            if ( expA ) {
+                sigA += UINT64_C( 0x2000000000000000 );
+            } else {
+                sigA <<= 1;
+            }
+            sigA = softfloat_shiftRightJam64( sigA, -expDiff );
+        } else {
+            if ( expA == 0x7FF ) {
+                if ( sigA ) goto propagateNaN;
+                uiZ = uiA;
+                goto uiZ;
+            }
+            expZ = expA;
+            if ( expB ) {
+                sigB += UINT64_C( 0x2000000000000000 );
+            } else {
+                sigB <<= 1;
+            }
+            sigB = softfloat_shiftRightJam64( sigB, expDiff );
+        }
+        sigZ = UINT64_C( 0x2000000000000000 ) + sigA + sigB;
+        if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
+            --expZ;
+            sigZ <<= 1;
+        }
+    }
+    return softfloat_roundPackToF64( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_approxRecip32_1.c b/tb/riscv-isa-sim/softfloat/s_approxRecip32_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a06192ed5b10b59c09e7af08f850e026e61203f2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_approxRecip32_1.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_approxRecip32_1
+
+extern const uint16_t softfloat_approxRecip_1k0s[16];
+extern const uint16_t softfloat_approxRecip_1k1s[16];
+
+uint32_t softfloat_approxRecip32_1( uint32_t a )
+{
+    int index;
+    uint16_t eps, r0;
+    uint32_t sigma0;
+    uint_fast32_t r;
+    uint32_t sqrSigma0;
+
+    index = a>>27 & 0xF;
+    eps = (uint16_t) (a>>11);
+    r0 = softfloat_approxRecip_1k0s[index]
+             - ((softfloat_approxRecip_1k1s[index] * (uint_fast32_t) eps)>>20);
+    sigma0 = ~(uint_fast32_t) ((r0 * (uint_fast64_t) a)>>7);
+    r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) sigma0)>>24);
+    sqrSigma0 = ((uint_fast64_t) sigma0 * sigma0)>>32;
+    r += ((uint32_t) r * (uint_fast64_t) sqrSigma0)>>48;
+    return r;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_approxRecipSqrt32_1.c b/tb/riscv-isa-sim/softfloat/s_approxRecipSqrt32_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ab71a25a611ef88d558b7b68504b738dbf3fe8a
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_approxRecipSqrt32_1.c
@@ -0,0 +1,73 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_approxRecipSqrt32_1
+
+extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
+extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
+
+uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a )
+{
+    int index;
+    uint16_t eps, r0;
+    uint_fast32_t ESqrR0;
+    uint32_t sigma0;
+    uint_fast32_t r;
+    uint32_t sqrSigma0;
+
+    index = (a>>27 & 0xE) + oddExpA;
+    eps = (uint16_t) (a>>12);
+    r0 = softfloat_approxRecipSqrt_1k0s[index]
+             - ((softfloat_approxRecipSqrt_1k1s[index] * (uint_fast32_t) eps)
+                    >>20);
+    ESqrR0 = (uint_fast32_t) r0 * r0;
+    if ( ! oddExpA ) ESqrR0 <<= 1;
+    sigma0 = ~(uint_fast32_t) (((uint32_t) ESqrR0 * (uint_fast64_t) a)>>23);
+    r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) sigma0)>>25);
+    sqrSigma0 = ((uint_fast64_t) sigma0 * sigma0)>>32;
+    r += ((uint32_t) ((r>>1) + (r>>3) - ((uint_fast32_t) r0<<14))
+              * (uint_fast64_t) sqrSigma0)
+             >>48;
+    if ( ! (r & 0x80000000) ) r = 0x80000000;
+    return r;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_approxRecipSqrt_1Ks.c b/tb/riscv-isa-sim/softfloat/s_approxRecipSqrt_1Ks.c
new file mode 100644
index 0000000000000000000000000000000000000000..a60cf8255714828e1c4fdfb4cfea02434747caa9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_approxRecipSqrt_1Ks.c
@@ -0,0 +1,49 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitives.h"
+
+const uint16_t softfloat_approxRecipSqrt_1k0s[16] = {
+    0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29,
+    0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1
+};
+const uint16_t softfloat_approxRecipSqrt_1k1s[16] = {
+    0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6,
+    0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD
+};
+
diff --git a/tb/riscv-isa-sim/softfloat/s_approxRecip_1Ks.c b/tb/riscv-isa-sim/softfloat/s_approxRecip_1Ks.c
new file mode 100644
index 0000000000000000000000000000000000000000..1108fcbe81979c25e1964d7878eddeaa20c232be
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_approxRecip_1Ks.c
@@ -0,0 +1,49 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitives.h"
+
+const uint16_t softfloat_approxRecip_1k0s[16] = {
+    0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201,
+    0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417
+};
+const uint16_t softfloat_approxRecip_1k1s[16] = {
+    0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA,
+    0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211
+};
+
diff --git a/tb/riscv-isa-sim/softfloat/s_commonNaNToF128UI.c b/tb/riscv-isa-sim/softfloat/s_commonNaNToF128UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b97f3437dbe63db18299243853848c88211a15e
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_commonNaNToF128UI.c
@@ -0,0 +1,56 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#define softfloat_commonNaNToF128UI softfloat_commonNaNToF128UI
+#include "specialize.h"
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
+| NaN, and returns the bit pattern of this value as an unsigned integer.
+*----------------------------------------------------------------------------*/
+struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
+{
+    struct uint128 uiZ;
+
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+    return uiZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_commonNaNToF16UI.c b/tb/riscv-isa-sim/softfloat/s_commonNaNToF16UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_commonNaNToF16UI.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_commonNaNToF32UI.c b/tb/riscv-isa-sim/softfloat/s_commonNaNToF32UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_commonNaNToF32UI.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_commonNaNToF64UI.c b/tb/riscv-isa-sim/softfloat/s_commonNaNToF64UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_commonNaNToF64UI.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_compare128M.c b/tb/riscv-isa-sim/softfloat/s_compare128M.c
new file mode 100644
index 0000000000000000000000000000000000000000..c2819e20d23cdc24ea90d4d0728fb9320019ca29
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_compare128M.c
@@ -0,0 +1,62 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_compare128M
+
+int_fast8_t softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr )
+{
+    unsigned int index, lastIndex;
+    uint32_t wordA, wordB;
+
+    index = indexWordHi( 4 );
+    lastIndex = indexWordLo( 4 );
+    for (;;) {
+        wordA = aPtr[index];
+        wordB = bPtr[index];
+        if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1;
+        if ( index == lastIndex ) break;
+        index -= wordIncr;
+    }
+    return 0;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_compare96M.c b/tb/riscv-isa-sim/softfloat/s_compare96M.c
new file mode 100644
index 0000000000000000000000000000000000000000..0dc39f5dba657ebc34e045db10a9edbf39c6e867
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_compare96M.c
@@ -0,0 +1,62 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_compare96M
+
+int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr )
+{
+    unsigned int index, lastIndex;
+    uint32_t wordA, wordB;
+
+    index = indexWordHi( 3 );
+    lastIndex = indexWordLo( 3 );
+    for (;;) {
+        wordA = aPtr[index];
+        wordB = bPtr[index];
+        if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1;
+        if ( index == lastIndex ) break;
+        index -= wordIncr;
+    }
+    return 0;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_countLeadingZeros16.c b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros16.c
new file mode 100644
index 0000000000000000000000000000000000000000..950db6c84c60e3e14ee6d18fbaadcb7341fac996
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros16.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_countLeadingZeros16
+
+#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
+#include "primitives.h"
+
+uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
+{
+    uint_fast8_t count;
+
+    count = 8;
+    if ( 0x100 <= a ) {
+        count = 0;
+        a >>= 8;
+    }
+    count += softfloat_countLeadingZeros8[a];
+    return count;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_countLeadingZeros32.c b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros32.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbf8ab6afbc09cbb2a942ae3afb7aa5b65bd50b1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros32.c
@@ -0,0 +1,64 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_countLeadingZeros32
+
+#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
+#include "primitives.h"
+
+uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
+{
+    uint_fast8_t count;
+
+    count = 0;
+    if ( a < 0x10000 ) {
+        count = 16;
+        a <<= 16;
+    }
+    if ( a < 0x1000000 ) {
+        count += 8;
+        a <<= 8;
+    }
+    count += softfloat_countLeadingZeros8[a>>24];
+    return count;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_countLeadingZeros64.c b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros64.c
new file mode 100644
index 0000000000000000000000000000000000000000..00457418befa1c10e5864e42f3892c25835f02a4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros64.c
@@ -0,0 +1,73 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_countLeadingZeros64
+
+#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
+#include "primitives.h"
+
+uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
+{
+    uint_fast8_t count;
+    uint32_t a32;
+
+    count = 0;
+    a32 = a>>32;
+    if ( ! a32 ) {
+        count = 32;
+        a32 = a;
+    }
+    /*------------------------------------------------------------------------
+    | From here, result is current count + count leading zeros of `a32'.
+    *------------------------------------------------------------------------*/
+    if ( a32 < 0x10000 ) {
+        count += 16;
+        a32 <<= 16;
+    }
+    if ( a32 < 0x1000000 ) {
+        count += 8;
+        a32 <<= 8;
+    }
+    count += softfloat_countLeadingZeros8[a32>>24];
+    return count;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_countLeadingZeros8.c b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros8.c
new file mode 100644
index 0000000000000000000000000000000000000000..1158d01c318925986f8708683597dc5113fcba3d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_countLeadingZeros8.c
@@ -0,0 +1,59 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitives.h"
+
+const uint_least8_t softfloat_countLeadingZeros8[256] = {
+    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
diff --git a/tb/riscv-isa-sim/softfloat/s_eq128.c b/tb/riscv-isa-sim/softfloat/s_eq128.c
new file mode 100644
index 0000000000000000000000000000000000000000..625ef002dd3e1339a5da49ae6c9694b954581e9f
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_eq128.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_eq128
+
+bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+
+    return (a64 == b64) && (a0 == b0);
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_f128UIToCommonNaN.c b/tb/riscv-isa-sim/softfloat/s_f128UIToCommonNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_f128UIToCommonNaN.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_f16UIToCommonNaN.c b/tb/riscv-isa-sim/softfloat/s_f16UIToCommonNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_f16UIToCommonNaN.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_f32UIToCommonNaN.c b/tb/riscv-isa-sim/softfloat/s_f32UIToCommonNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_f32UIToCommonNaN.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_f64UIToCommonNaN.c b/tb/riscv-isa-sim/softfloat/s_f64UIToCommonNaN.c
new file mode 100644
index 0000000000000000000000000000000000000000..861b2696589370d44eb446994ad57482b47e5580
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_f64UIToCommonNaN.c
@@ -0,0 +1,5 @@
+
+/*----------------------------------------------------------------------------
+| This file intentionally contains no code.
+*----------------------------------------------------------------------------*/
+
diff --git a/tb/riscv-isa-sim/softfloat/s_le128.c b/tb/riscv-isa-sim/softfloat/s_le128.c
new file mode 100644
index 0000000000000000000000000000000000000000..7261012f3418dfdd4fbf1397fec0d6f1d0eba268
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_le128.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_le128
+
+bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+
+    return (a64 < b64) || ((a64 == b64) && (a0 <= b0));
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_lt128.c b/tb/riscv-isa-sim/softfloat/s_lt128.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d461c363ecc6b360f17bb587c239ae6d794c1f0
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_lt128.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_lt128
+
+bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+
+    return (a64 < b64) || ((a64 == b64) && (a0 < b0));
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mul128By32.c b/tb/riscv-isa-sim/softfloat/s_mul128By32.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e71dd0c530a96c4e7f5bdba3749b8290d4d4571
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mul128By32.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_mul128By32
+
+struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
+{
+    struct uint128 z;
+    uint_fast64_t mid;
+    uint_fast32_t carry;
+
+    z.v0 = a0 * b;
+    mid = (uint_fast64_t) (uint32_t) (a0>>32) * b;
+    carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid);
+    z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mul128MTo256M.c b/tb/riscv-isa-sim/softfloat/s_mul128MTo256M.c
new file mode 100644
index 0000000000000000000000000000000000000000..49a1d294d60c5420fbdf898b9184427f24e48c97
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mul128MTo256M.c
@@ -0,0 +1,100 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_mul128MTo256M
+
+void
+ softfloat_mul128MTo256M(
+     const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr )
+{
+    uint32_t *lastZPtr, wordB;
+    uint64_t dwordProd;
+    uint32_t wordZ;
+    uint_fast8_t carry;
+
+    bPtr += indexWordLo( 4 );
+    lastZPtr = zPtr + indexMultiwordHi( 8, 5 );
+    zPtr += indexMultiwordLo( 8, 5 );
+    wordB = *bPtr;
+    dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB;
+    zPtr[indexWord( 5, 0 )] = dwordProd;
+    dwordProd = (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32);
+    zPtr[indexWord( 5, 1 )] = dwordProd;
+    dwordProd = (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32);
+    zPtr[indexWord( 5, 2 )] = dwordProd;
+    dwordProd = (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32);
+    zPtr[indexWord( 5, 3 )] = dwordProd;
+    zPtr[indexWord( 5, 4 )] = dwordProd>>32;
+    do {
+        bPtr += wordIncr;
+        zPtr += wordIncr;
+        wordB = *bPtr;
+        dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB;
+        wordZ = zPtr[indexWord( 5, 0 )] + (uint32_t) dwordProd;
+        zPtr[indexWord( 5, 0 )] = wordZ;
+        carry = (wordZ < (uint32_t) dwordProd);
+        dwordProd =
+            (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32);
+        wordZ = zPtr[indexWord( 5, 1 )] + (uint32_t) dwordProd + carry;
+        zPtr[indexWord( 5, 1 )] = wordZ;
+        if ( wordZ != (uint32_t) dwordProd ) {
+            carry = (wordZ < (uint32_t) dwordProd);
+        }
+        dwordProd =
+            (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32);
+        wordZ = zPtr[indexWord( 5, 2 )] + (uint32_t) dwordProd + carry;
+        zPtr[indexWord( 5, 2 )] = wordZ;
+        if ( wordZ != (uint32_t) dwordProd ) {
+            carry = (wordZ < (uint32_t) dwordProd);
+        }
+        dwordProd =
+            (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32);
+        wordZ = zPtr[indexWord( 5, 3 )] + (uint32_t) dwordProd + carry;
+        zPtr[indexWord( 5, 3 )] = wordZ;
+        if ( wordZ != (uint32_t) dwordProd ) {
+            carry = (wordZ < (uint32_t) dwordProd);
+        }
+        zPtr[indexWord( 5, 4 )] = (dwordProd>>32) + carry;
+    } while ( zPtr != lastZPtr );
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mul128To256M.c b/tb/riscv-isa-sim/softfloat/s_mul128To256M.c
new file mode 100644
index 0000000000000000000000000000000000000000..fccc2a698d548fed9b03fbe16616d9e4b137fffc
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mul128To256M.c
@@ -0,0 +1,71 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_mul128To256M
+
+#define softfloat_mul128To256M softfloat_mul128To256M
+#include "primitives.h"
+
+void
+ softfloat_mul128To256M(
+     uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr )
+{
+    struct uint128 p0, p64, p128;
+    uint_fast64_t z64, z128, z192;
+
+    p0 = softfloat_mul64To128( a0, b0 );
+    zPtr[indexWord( 4, 0 )] = p0.v0;
+    p64 = softfloat_mul64To128( a64, b0 );
+    z64 = p64.v0 + p0.v64;
+    z128 = p64.v64 + (z64 < p64.v0);
+    p128 = softfloat_mul64To128( a64, b64 );
+    z128 += p128.v0;
+    z192 = p128.v64 + (z128 < p128.v0);
+    p64 = softfloat_mul64To128( a0, b64 );
+    z64 += p64.v0;
+    zPtr[indexWord( 4, 1 )] = z64;
+    p64.v64 += (z64 < p64.v0);
+    z128 += p64.v64;
+    zPtr[indexWord( 4, 2 )] = z128;
+    zPtr[indexWord( 4, 3 )] = z192 + (z128 < p64.v64);
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mul64ByShifted32To128.c b/tb/riscv-isa-sim/softfloat/s_mul64ByShifted32To128.c
new file mode 100644
index 0000000000000000000000000000000000000000..f7e7104ea510f03e5bdd37cc278beff0df23de79
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mul64ByShifted32To128.c
@@ -0,0 +1,56 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_mul64ByShifted32To128
+
+struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
+{
+    uint_fast64_t mid;
+    struct uint128 z;
+
+    mid = (uint_fast64_t) (uint32_t) a * b;
+    z.v0 = mid<<32;
+    z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mul64To128.c b/tb/riscv-isa-sim/softfloat/s_mul64To128.c
new file mode 100644
index 0000000000000000000000000000000000000000..6620a20bc166f26001d622fa473d059683d5f658
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mul64To128.c
@@ -0,0 +1,66 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_mul64To128
+
+struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
+{
+    uint32_t a32, a0, b32, b0;
+    struct uint128 z;
+    uint64_t mid1, mid;
+
+    a32 = a>>32;
+    a0 = a;
+    b32 = b>>32;
+    b0 = b;
+    z.v0 = (uint_fast64_t) a0 * b0;
+    mid1 = (uint_fast64_t) a32 * b0;
+    mid = mid1 + (uint_fast64_t) a0 * b32;
+    z.v64 = (uint_fast64_t) a32 * b32;
+    z.v64 += (uint_fast64_t) (mid < mid1)<<32 | mid>>32;
+    mid <<= 32;
+    z.v0 += mid;
+    z.v64 += (z.v0 < mid);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mul64To128M.c b/tb/riscv-isa-sim/softfloat/s_mul64To128M.c
new file mode 100644
index 0000000000000000000000000000000000000000..e3f9a481ebb294a1da76c9474f61a3795a6e3940
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mul64To128M.c
@@ -0,0 +1,68 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_mul64To128M
+
+void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr )
+{
+    uint32_t a32, a0, b32, b0;
+    uint64_t z0, mid1, z64, mid;
+
+    a32 = a>>32;
+    a0 = a;
+    b32 = b>>32;
+    b0 = b;
+    z0 = (uint64_t) a0 * b0;
+    mid1 = (uint64_t) a32 * b0;
+    mid = mid1 + (uint64_t) a0 * b32;
+    z64 = (uint64_t) a32 * b32;
+    z64 += (uint64_t) (mid < mid1)<<32 | mid>>32;
+    mid <<= 32;
+    z0 += mid;
+    zPtr[indexWord( 4, 1 )] = z0>>32;
+    zPtr[indexWord( 4, 0 )] = z0;
+    z64 += (z0 < mid);
+    zPtr[indexWord( 4, 3 )] = z64>>32;
+    zPtr[indexWord( 4, 2 )] = z64;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mulAddF128.c b/tb/riscv-isa-sim/softfloat/s_mulAddF128.c
new file mode 100644
index 0000000000000000000000000000000000000000..877b33d2312a4df578e245539699eedf5ee3350d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mulAddF128.c
@@ -0,0 +1,350 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t
+ softfloat_mulAddF128(
+     uint_fast64_t uiA64,
+     uint_fast64_t uiA0,
+     uint_fast64_t uiB64,
+     uint_fast64_t uiB0,
+     uint_fast64_t uiC64,
+     uint_fast64_t uiC0,
+     uint_fast8_t op
+ )
+{
+    bool signA;
+    int_fast32_t expA;
+    struct uint128 sigA;
+    bool signB;
+    int_fast32_t expB;
+    struct uint128 sigB;
+    bool signC;
+    int_fast32_t expC;
+    struct uint128 sigC;
+    bool signZ;
+    uint_fast64_t magBits;
+    struct uint128 uiZ;
+    struct exp32_sig128 normExpSig;
+    int_fast32_t expZ;
+    uint64_t sig256Z[4];
+    struct uint128 sigZ;
+    int_fast32_t shiftDist, expDiff;
+    struct uint128 x128;
+    uint64_t sig256C[4];
+    static uint64_t zero256[4] = INIT_UINTM4( 0, 0, 0, 0 );
+    uint_fast64_t sigZExtra, sig256Z0;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    signA = signF128UI64( uiA64 );
+    expA  = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    signB = signF128UI64( uiB64 );
+    expB  = expF128UI64( uiB64 );
+    sigB.v64 = fracF128UI64( uiB64 );
+    sigB.v0  = uiB0;
+    signC = signF128UI64( uiC64 ) ^ (op == softfloat_mulAdd_subC);
+    expC  = expF128UI64( uiC64 );
+    sigC.v64 = fracF128UI64( uiC64 );
+    sigC.v0  = uiC0;
+    signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FFF ) {
+        if (
+            (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
+        ) {
+            goto propagateNaN_ABC;
+        }
+        magBits = expB | sigB.v64 | sigB.v0;
+        goto infProdArg;
+    }
+    if ( expB == 0x7FFF ) {
+        if ( sigB.v64 | sigB.v0 ) goto propagateNaN_ABC;
+        magBits = expA | sigA.v64 | sigA.v0;
+        goto infProdArg;
+    }
+    if ( expC == 0x7FFF ) {
+        if ( sigC.v64 | sigC.v0 ) {
+            uiZ.v64 = 0;
+            uiZ.v0  = 0;
+            goto propagateNaN_ZC;
+        }
+        uiZ.v64 = uiC64;
+        uiZ.v0  = uiC0;
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! (sigA.v64 | sigA.v0) ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! (sigB.v64 | sigB.v0) ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0x3FFE;
+    sigA.v64 |= UINT64_C( 0x0001000000000000 );
+    sigB.v64 |= UINT64_C( 0x0001000000000000 );
+    sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 8 );
+    sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 15 );
+    softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
+    sigZ.v64 = sig256Z[indexWord( 4, 3 )];
+    sigZ.v0  = sig256Z[indexWord( 4, 2 )];
+    shiftDist = 0;
+    if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) {
+        --expZ;
+        shiftDist = -1;
+    }
+    if ( ! expC ) {
+        if ( ! (sigC.v64 | sigC.v0) ) {
+            shiftDist += 8;
+            goto sigZ;
+        }
+        normExpSig = softfloat_normSubnormalF128Sig( sigC.v64, sigC.v0 );
+        expC = normExpSig.exp;
+        sigC = normExpSig.sig;
+    }
+    sigC.v64 |= UINT64_C( 0x0001000000000000 );
+    sigC = softfloat_shortShiftLeft128( sigC.v64, sigC.v0, 8 );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expZ - expC;
+    if ( expDiff < 0 ) {
+        expZ = expC;
+        if ( (signZ == signC) || (expDiff < -1) ) {
+            shiftDist -= expDiff;
+            if ( shiftDist ) {
+                sigZ =
+                    softfloat_shiftRightJam128( sigZ.v64, sigZ.v0, shiftDist );
+            }
+        } else {
+            if ( ! shiftDist ) {
+                x128 =
+                    softfloat_shortShiftRight128(
+                        sig256Z[indexWord( 4, 1 )], sig256Z[indexWord( 4, 0 )],
+                        1
+                    );
+                sig256Z[indexWord( 4, 1 )] = (sigZ.v0<<63) | x128.v64;
+                sig256Z[indexWord( 4, 0 )] = x128.v0;
+                sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, 1 );
+                sig256Z[indexWord( 4, 3 )] = sigZ.v64;
+                sig256Z[indexWord( 4, 2 )] = sigZ.v0;
+            }
+        }
+    } else {
+        if ( shiftDist ) softfloat_add256M( sig256Z, sig256Z, sig256Z );
+        if ( ! expDiff ) {
+            sigZ.v64 = sig256Z[indexWord( 4, 3 )];
+            sigZ.v0  = sig256Z[indexWord( 4, 2 )];
+        } else {
+            sig256C[indexWord( 4, 3 )] = sigC.v64;
+            sig256C[indexWord( 4, 2 )] = sigC.v0;
+            sig256C[indexWord( 4, 1 )] = 0;
+            sig256C[indexWord( 4, 0 )] = 0;
+            softfloat_shiftRightJam256M( sig256C, expDiff, sig256C );
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    shiftDist = 8;
+    if ( signZ == signC ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff <= 0 ) {
+            sigZ = softfloat_add128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 );
+        } else {
+            softfloat_add256M( sig256Z, sig256C, sig256Z );
+            sigZ.v64 = sig256Z[indexWord( 4, 3 )];
+            sigZ.v0  = sig256Z[indexWord( 4, 2 )];
+        }
+        if ( sigZ.v64 & UINT64_C( 0x0200000000000000 ) ) {
+            ++expZ;
+            shiftDist = 9;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff < 0 ) {
+            signZ = signC;
+            if ( expDiff < -1 ) {
+                sigZ =
+                    softfloat_sub128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 );
+                sigZExtra =
+                    sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )];
+                if ( sigZExtra ) {
+                    sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 );
+                }
+                if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) {
+                    --expZ;
+                    shiftDist = 7;
+                }
+                goto shiftRightRoundPack;
+            } else {
+                sig256C[indexWord( 4, 3 )] = sigC.v64;
+                sig256C[indexWord( 4, 2 )] = sigC.v0;
+                sig256C[indexWord( 4, 1 )] = 0;
+                sig256C[indexWord( 4, 0 )] = 0;
+                softfloat_sub256M( sig256C, sig256Z, sig256Z );
+            }
+        } else if ( ! expDiff ) {
+            sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, sigC.v64, sigC.v0 );
+            if (
+                ! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord( 4, 1 )]
+                    && ! sig256Z[indexWord( 4, 0 )]
+            ) {
+                goto completeCancellation;
+            }
+            sig256Z[indexWord( 4, 3 )] = sigZ.v64;
+            sig256Z[indexWord( 4, 2 )] = sigZ.v0;
+            if ( sigZ.v64 & UINT64_C( 0x8000000000000000 ) ) {
+                signZ = ! signZ;
+                softfloat_sub256M( zero256, sig256Z, sig256Z );
+            }
+        } else {
+            softfloat_sub256M( sig256Z, sig256C, sig256Z );
+            if ( 1 < expDiff ) {
+                sigZ.v64 = sig256Z[indexWord( 4, 3 )];
+                sigZ.v0  = sig256Z[indexWord( 4, 2 )];
+                if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) {
+                    --expZ;
+                    shiftDist = 7;
+                }
+                goto sigZ;
+            }
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sigZ.v64  = sig256Z[indexWord( 4, 3 )];
+        sigZ.v0   = sig256Z[indexWord( 4, 2 )];
+        sigZExtra = sig256Z[indexWord( 4, 1 )];
+        sig256Z0  = sig256Z[indexWord( 4, 0 )];
+        if ( sigZ.v64 ) {
+            if ( sig256Z0 ) sigZExtra |= 1;
+        } else {
+            expZ -= 64;
+            sigZ.v64  = sigZ.v0;
+            sigZ.v0   = sigZExtra;
+            sigZExtra = sig256Z0;
+            if ( ! sigZ.v64 ) {
+                expZ -= 64;
+                sigZ.v64  = sigZ.v0;
+                sigZ.v0   = sigZExtra;
+                sigZExtra = 0;
+                if ( ! sigZ.v64 ) {
+                    expZ -= 64;
+                    sigZ.v64 = sigZ.v0;
+                    sigZ.v0  = 0;
+                }
+            }
+        }
+        shiftDist = softfloat_countLeadingZeros64( sigZ.v64 );
+        expZ += 7 - shiftDist;
+        shiftDist = 15 - shiftDist;
+        if ( 0 < shiftDist ) goto shiftRightRoundPack;
+        if ( shiftDist ) {
+            shiftDist = -shiftDist;
+            sigZ = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, shiftDist );
+            x128 = softfloat_shortShiftLeft128( 0, sigZExtra, shiftDist );
+            sigZ.v0 |= x128.v64;
+            sigZExtra = x128.v0;
+        }
+        goto roundPack;
+    }
+ sigZ:
+    sigZExtra = sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )];
+ shiftRightRoundPack:
+    sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0);
+    sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, shiftDist );
+ roundPack:
+    return
+        softfloat_roundPackToF128(
+            signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN_ABC:
+    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
+    goto propagateNaN_ZC;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infProdArg:
+    if ( magBits ) {
+        uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
+        uiZ.v0 = 0;
+        if ( expC != 0x7FFF ) goto uiZ;
+        if ( sigC.v64 | sigC.v0 ) goto propagateNaN_ZC;
+        if ( signZ == signC ) goto uiZ;
+    }
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+ propagateNaN_ZC:
+    uiZ = softfloat_propagateNaNF128UI( uiZ.v64, uiZ.v0, uiC64, uiC0 );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zeroProd:
+    uiZ.v64 = uiC64;
+    uiZ.v0  = uiC0;
+    if ( ! (expC | sigC.v64 | sigC.v0) && (signZ != signC) ) {
+ completeCancellation:
+        uiZ.v64 =
+            packToF128UI64(
+                (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+        uiZ.v0 = 0;
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mulAddF16.c b/tb/riscv-isa-sim/softfloat/s_mulAddF16.c
new file mode 100644
index 0000000000000000000000000000000000000000..b604007232b40218000d660d71424b25515c85b9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mulAddF16.c
@@ -0,0 +1,226 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t
+ softfloat_mulAddF16(
+     uint_fast16_t uiA, uint_fast16_t uiB, uint_fast16_t uiC, uint_fast8_t op )
+{
+    bool signA;
+    int_fast8_t expA;
+    uint_fast16_t sigA;
+    bool signB;
+    int_fast8_t expB;
+    uint_fast16_t sigB;
+    bool signC;
+    int_fast8_t expC;
+    uint_fast16_t sigC;
+    bool signProd;
+    uint_fast16_t magBits, uiZ;
+    struct exp8_sig16 normExpSig;
+    int_fast8_t expProd;
+    uint_fast32_t sigProd;
+    bool signZ;
+    int_fast8_t expZ;
+    uint_fast16_t sigZ;
+    int_fast8_t expDiff;
+    uint_fast32_t sig32Z, sig32C;
+    int_fast8_t shiftDist;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    signA = signF16UI( uiA );
+    expA  = expF16UI( uiA );
+    sigA  = fracF16UI( uiA );
+    signB = signF16UI( uiB );
+    expB  = expF16UI( uiB );
+    sigB  = fracF16UI( uiB );
+    signC = signF16UI( uiC ) ^ (op == softfloat_mulAdd_subC);
+    expC  = expF16UI( uiC );
+    sigC  = fracF16UI( uiC );
+    signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x1F ) {
+        if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN_ABC;
+        magBits = expB | sigB;
+        goto infProdArg;
+    }
+    if ( expB == 0x1F ) {
+        if ( sigB ) goto propagateNaN_ABC;
+        magBits = expA | sigA;
+        goto infProdArg;
+    }
+    if ( expC == 0x1F ) {
+        if ( sigC ) {
+            uiZ = 0;
+            goto propagateNaN_ZC;
+        }
+        uiZ = uiC;
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF16Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF16Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expProd = expA + expB - 0xE;
+    sigA = (sigA | 0x0400)<<4;
+    sigB = (sigB | 0x0400)<<4;
+    sigProd = (uint_fast32_t) sigA * sigB;
+    if ( sigProd < 0x20000000 ) {
+        --expProd;
+        sigProd <<= 1;
+    }
+    signZ = signProd;
+    if ( ! expC ) {
+        if ( ! sigC ) {
+            expZ = expProd - 1;
+            sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0);
+            goto roundPack;
+        }
+        normExpSig = softfloat_normSubnormalF16Sig( sigC );
+        expC = normExpSig.exp;
+        sigC = normExpSig.sig;
+    }
+    sigC = (sigC | 0x0400)<<3;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expProd - expC;
+    if ( signProd == signC ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff <= 0 ) {
+            expZ = expC;
+            sigZ = sigC + softfloat_shiftRightJam32( sigProd, 16 - expDiff );
+        } else {
+            expZ = expProd;
+            sig32Z =
+                sigProd
+                    + softfloat_shiftRightJam32(
+                          (uint_fast32_t) sigC<<16, expDiff );
+            sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0 );
+        }
+        if ( sigZ < 0x4000 ) {
+            --expZ;
+            sigZ <<= 1;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig32C = (uint_fast32_t) sigC<<16;
+        if ( expDiff < 0 ) {
+            signZ = signC;
+            expZ = expC;
+            sig32Z = sig32C - softfloat_shiftRightJam32( sigProd, -expDiff );
+        } else if ( ! expDiff ) {
+            expZ = expProd;
+            sig32Z = sigProd - sig32C;
+            if ( ! sig32Z ) goto completeCancellation;
+            if ( sig32Z & 0x80000000 ) {
+                signZ = ! signZ;
+                sig32Z = -sig32Z;
+            }
+        } else {
+            expZ = expProd;
+            sig32Z = sigProd - softfloat_shiftRightJam32( sig32C, expDiff );
+        }
+        shiftDist = softfloat_countLeadingZeros32( sig32Z ) - 1;
+        expZ -= shiftDist;
+        shiftDist -= 16;
+        if ( shiftDist < 0 ) {
+            sigZ =
+                sig32Z>>(-shiftDist)
+                    | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0);
+        } else {
+            sigZ = (uint_fast16_t) sig32Z<<shiftDist;
+        }
+    }
+ roundPack:
+    return softfloat_roundPackToF16( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN_ABC:
+    uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
+    goto propagateNaN_ZC;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infProdArg:
+    if ( magBits ) {
+        uiZ = packToF16UI( signProd, 0x1F, 0 );
+        if ( expC != 0x1F ) goto uiZ;
+        if ( sigC ) goto propagateNaN_ZC;
+        if ( signProd == signC ) goto uiZ;
+    }
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF16UI;
+ propagateNaN_ZC:
+    uiZ = softfloat_propagateNaNF16UI( uiZ, uiC );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zeroProd:
+    uiZ = uiC;
+    if ( ! (expC | sigC) && (signProd != signC) ) {
+ completeCancellation:
+        uiZ =
+            packToF16UI(
+                (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mulAddF32.c b/tb/riscv-isa-sim/softfloat/s_mulAddF32.c
new file mode 100644
index 0000000000000000000000000000000000000000..d163ea02eda25578d26d61e2d34826e4137c1bb9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mulAddF32.c
@@ -0,0 +1,224 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t
+ softfloat_mulAddF32(
+     uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op )
+{
+    bool signA;
+    int_fast16_t expA;
+    uint_fast32_t sigA;
+    bool signB;
+    int_fast16_t expB;
+    uint_fast32_t sigB;
+    bool signC;
+    int_fast16_t expC;
+    uint_fast32_t sigC;
+    bool signProd;
+    uint_fast32_t magBits, uiZ;
+    struct exp16_sig32 normExpSig;
+    int_fast16_t expProd;
+    uint_fast64_t sigProd;
+    bool signZ;
+    int_fast16_t expZ;
+    uint_fast32_t sigZ;
+    int_fast16_t expDiff;
+    uint_fast64_t sig64Z, sig64C;
+    int_fast8_t shiftDist;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    signA = signF32UI( uiA );
+    expA  = expF32UI( uiA );
+    sigA  = fracF32UI( uiA );
+    signB = signF32UI( uiB );
+    expB  = expF32UI( uiB );
+    sigB  = fracF32UI( uiB );
+    signC = signF32UI( uiC ) ^ (op == softfloat_mulAdd_subC);
+    expC  = expF32UI( uiC );
+    sigC  = fracF32UI( uiC );
+    signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0xFF ) {
+        if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN_ABC;
+        magBits = expB | sigB;
+        goto infProdArg;
+    }
+    if ( expB == 0xFF ) {
+        if ( sigB ) goto propagateNaN_ABC;
+        magBits = expA | sigA;
+        goto infProdArg;
+    }
+    if ( expC == 0xFF ) {
+        if ( sigC ) {
+            uiZ = 0;
+            goto propagateNaN_ZC;
+        }
+        uiZ = uiC;
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF32Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF32Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expProd = expA + expB - 0x7E;
+    sigA = (sigA | 0x00800000)<<7;
+    sigB = (sigB | 0x00800000)<<7;
+    sigProd = (uint_fast64_t) sigA * sigB;
+    if ( sigProd < UINT64_C( 0x2000000000000000 ) ) {
+        --expProd;
+        sigProd <<= 1;
+    }
+    signZ = signProd;
+    if ( ! expC ) {
+        if ( ! sigC ) {
+            expZ = expProd - 1;
+            sigZ = softfloat_shortShiftRightJam64( sigProd, 31 );
+            goto roundPack;
+        }
+        normExpSig = softfloat_normSubnormalF32Sig( sigC );
+        expC = normExpSig.exp;
+        sigC = normExpSig.sig;
+    }
+    sigC = (sigC | 0x00800000)<<6;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expProd - expC;
+    if ( signProd == signC ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff <= 0 ) {
+            expZ = expC;
+            sigZ = sigC + softfloat_shiftRightJam64( sigProd, 32 - expDiff );
+        } else {
+            expZ = expProd;
+            sig64Z =
+                sigProd
+                    + softfloat_shiftRightJam64(
+                          (uint_fast64_t) sigC<<32, expDiff );
+            sigZ = softfloat_shortShiftRightJam64( sig64Z, 32 );
+        }
+        if ( sigZ < 0x40000000 ) {
+            --expZ;
+            sigZ <<= 1;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sig64C = (uint_fast64_t) sigC<<32;
+        if ( expDiff < 0 ) {
+            signZ = signC;
+            expZ = expC;
+            sig64Z = sig64C - softfloat_shiftRightJam64( sigProd, -expDiff );
+        } else if ( ! expDiff ) {
+            expZ = expProd;
+            sig64Z = sigProd - sig64C;
+            if ( ! sig64Z ) goto completeCancellation;
+            if ( sig64Z & UINT64_C( 0x8000000000000000 ) ) {
+                signZ = ! signZ;
+                sig64Z = -sig64Z;
+            }
+        } else {
+            expZ = expProd;
+            sig64Z = sigProd - softfloat_shiftRightJam64( sig64C, expDiff );
+        }
+        shiftDist = softfloat_countLeadingZeros64( sig64Z ) - 1;
+        expZ -= shiftDist;
+        shiftDist -= 32;
+        if ( shiftDist < 0 ) {
+            sigZ = softfloat_shortShiftRightJam64( sig64Z, -shiftDist );
+        } else {
+            sigZ = (uint_fast32_t) sig64Z<<shiftDist;
+        }
+    }
+ roundPack:
+    return softfloat_roundPackToF32( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN_ABC:
+    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
+    goto propagateNaN_ZC;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infProdArg:
+    if ( magBits ) {
+        uiZ = packToF32UI( signProd, 0xFF, 0 );
+        if ( expC != 0xFF ) goto uiZ;
+        if ( sigC ) goto propagateNaN_ZC;
+        if ( signProd == signC ) goto uiZ;
+    }
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF32UI;
+ propagateNaN_ZC:
+    uiZ = softfloat_propagateNaNF32UI( uiZ, uiC );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zeroProd:
+    uiZ = uiC;
+    if ( ! (expC | sigC) && (signProd != signC) ) {
+ completeCancellation:
+        uiZ =
+            packToF32UI(
+                (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_mulAddF64.c b/tb/riscv-isa-sim/softfloat/s_mulAddF64.c
new file mode 100644
index 0000000000000000000000000000000000000000..484ac586d82367b0eb0b406b4e9615567031a1b8
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_mulAddF64.c
@@ -0,0 +1,496 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+#ifdef SOFTFLOAT_FAST_INT64
+
+float64_t
+ softfloat_mulAddF64(
+     uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op )
+{
+    bool signA;
+    int_fast16_t expA;
+    uint_fast64_t sigA;
+    bool signB;
+    int_fast16_t expB;
+    uint_fast64_t sigB;
+    bool signC;
+    int_fast16_t expC;
+    uint_fast64_t sigC;
+    bool signZ;
+    uint_fast64_t magBits, uiZ;
+    struct exp16_sig64 normExpSig;
+    int_fast16_t expZ;
+    struct uint128 sig128Z;
+    uint_fast64_t sigZ;
+    int_fast16_t expDiff;
+    struct uint128 sig128C;
+    int_fast8_t shiftDist;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    signA = signF64UI( uiA );
+    expA  = expF64UI( uiA );
+    sigA  = fracF64UI( uiA );
+    signB = signF64UI( uiB );
+    expB  = expF64UI( uiB );
+    sigB  = fracF64UI( uiB );
+    signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC);
+    expC  = expF64UI( uiC );
+    sigC  = fracF64UI( uiC );
+    signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FF ) {
+        if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC;
+        magBits = expB | sigB;
+        goto infProdArg;
+    }
+    if ( expB == 0x7FF ) {
+        if ( sigB ) goto propagateNaN_ABC;
+        magBits = expA | sigA;
+        goto infProdArg;
+    }
+    if ( expC == 0x7FF ) {
+        if ( sigC ) {
+            uiZ = 0;
+            goto propagateNaN_ZC;
+        }
+        uiZ = uiC;
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF64Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF64Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0x3FE;
+    sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10;
+    sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<10;
+    sig128Z = softfloat_mul64To128( sigA, sigB );
+    if ( sig128Z.v64 < UINT64_C( 0x2000000000000000 ) ) {
+        --expZ;
+        sig128Z =
+            softfloat_add128(
+                sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 );
+    }
+    if ( ! expC ) {
+        if ( ! sigC ) {
+            --expZ;
+            sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0);
+            goto roundPack;
+        }
+        normExpSig = softfloat_normSubnormalF64Sig( sigC );
+        expC = normExpSig.exp;
+        sigC = normExpSig.sig;
+    }
+    sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<9;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expZ - expC;
+    if ( expDiff < 0 ) {
+        expZ = expC;
+        if ( (signZ == signC) || (expDiff < -1) ) {
+            sig128Z.v64 = softfloat_shiftRightJam64( sig128Z.v64, -expDiff );
+        } else {
+            sig128Z =
+                softfloat_shortShiftRightJam128( sig128Z.v64, sig128Z.v0, 1 );
+        }
+    } else if ( expDiff ) {
+        sig128C = softfloat_shiftRightJam128( sigC, 0, expDiff );
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( signZ == signC ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff <= 0 ) {
+            sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0);
+        } else {
+            sig128Z =
+                softfloat_add128(
+                    sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 );
+            sigZ = sig128Z.v64 | (sig128Z.v0 != 0);
+        }
+        if ( sigZ < UINT64_C( 0x4000000000000000 ) ) {
+            --expZ;
+            sigZ <<= 1;
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff < 0 ) {
+            signZ = signC;
+            sig128Z = softfloat_sub128( sigC, 0, sig128Z.v64, sig128Z.v0 );
+        } else if ( ! expDiff ) {
+            sig128Z.v64 = sig128Z.v64 - sigC;
+            if ( ! (sig128Z.v64 | sig128Z.v0) ) goto completeCancellation;
+            if ( sig128Z.v64 & UINT64_C( 0x8000000000000000 ) ) {
+                signZ = ! signZ;
+                sig128Z = softfloat_sub128( 0, 0, sig128Z.v64, sig128Z.v0 );
+            }
+        } else {
+            sig128Z =
+                softfloat_sub128(
+                    sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 );
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( ! sig128Z.v64 ) {
+            expZ -= 64;
+            sig128Z.v64 = sig128Z.v0;
+            sig128Z.v0 = 0;
+        }
+        shiftDist = softfloat_countLeadingZeros64( sig128Z.v64 ) - 1;
+        expZ -= shiftDist;
+        if ( shiftDist < 0 ) {
+            sigZ = softfloat_shortShiftRightJam64( sig128Z.v64, -shiftDist );
+        } else {
+            sig128Z =
+                softfloat_shortShiftLeft128(
+                    sig128Z.v64, sig128Z.v0, shiftDist );
+            sigZ = sig128Z.v64;
+        }
+        sigZ |= (sig128Z.v0 != 0);
+    }
+ roundPack:
+    return softfloat_roundPackToF64( signZ, expZ, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN_ABC:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+    goto propagateNaN_ZC;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infProdArg:
+    if ( magBits ) {
+        uiZ = packToF64UI( signZ, 0x7FF, 0 );
+        if ( expC != 0x7FF ) goto uiZ;
+        if ( sigC ) goto propagateNaN_ZC;
+        if ( signZ == signC ) goto uiZ;
+    }
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF64UI;
+ propagateNaN_ZC:
+    uiZ = softfloat_propagateNaNF64UI( uiZ, uiC );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zeroProd:
+    uiZ = uiC;
+    if ( ! (expC | sigC) && (signZ != signC) ) {
+ completeCancellation:
+        uiZ =
+            packToF64UI(
+                (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
+#else
+
+float64_t
+ softfloat_mulAddF64(
+     uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op )
+{
+    bool signA;
+    int_fast16_t expA;
+    uint64_t sigA;
+    bool signB;
+    int_fast16_t expB;
+    uint64_t sigB;
+    bool signC;
+    int_fast16_t expC;
+    uint64_t sigC;
+    bool signZ;
+    uint64_t magBits, uiZ;
+    struct exp16_sig64 normExpSig;
+    int_fast16_t expZ;
+    uint32_t sig128Z[4];
+    uint64_t sigZ;
+    int_fast16_t shiftDist, expDiff;
+    uint32_t sig128C[4];
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    signA = signF64UI( uiA );
+    expA  = expF64UI( uiA );
+    sigA  = fracF64UI( uiA );
+    signB = signF64UI( uiB );
+    expB  = expF64UI( uiB );
+    sigB  = fracF64UI( uiB );
+    signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC);
+    expC  = expF64UI( uiC );
+    sigC  = fracF64UI( uiC );
+    signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( expA == 0x7FF ) {
+        if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC;
+        magBits = expB | sigB;
+        goto infProdArg;
+    }
+    if ( expB == 0x7FF ) {
+        if ( sigB ) goto propagateNaN_ABC;
+        magBits = expA | sigA;
+        goto infProdArg;
+    }
+    if ( expC == 0x7FF ) {
+        if ( sigC ) {
+            uiZ = 0;
+            goto propagateNaN_ZC;
+        }
+        uiZ = uiC;
+        goto uiZ;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( ! expA ) {
+        if ( ! sigA ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF64Sig( sigA );
+        expA = normExpSig.exp;
+        sigA = normExpSig.sig;
+    }
+    if ( ! expB ) {
+        if ( ! sigB ) goto zeroProd;
+        normExpSig = softfloat_normSubnormalF64Sig( sigB );
+        expB = normExpSig.exp;
+        sigB = normExpSig.sig;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expZ = expA + expB - 0x3FE;
+    sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10;
+    sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11;
+    softfloat_mul64To128M( sigA, sigB, sig128Z );
+    sigZ =
+        (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )];
+    shiftDist = 0;
+    if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
+        --expZ;
+        shiftDist = -1;
+    }
+    if ( ! expC ) {
+        if ( ! sigC ) {
+            if ( shiftDist ) sigZ <<= 1;
+            goto sigZ;
+        }
+        normExpSig = softfloat_normSubnormalF64Sig( sigC );
+        expC = normExpSig.exp;
+        sigC = normExpSig.sig;
+    }
+    sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expZ - expC;
+    if ( expDiff < 0 ) {
+        expZ = expC;
+        if ( (signZ == signC) || (expDiff < -1) ) {
+            shiftDist -= expDiff;
+            if ( shiftDist) {
+                sigZ = softfloat_shiftRightJam64( sigZ, shiftDist );
+            }
+        } else {
+            if ( ! shiftDist ) {
+                softfloat_shortShiftRight128M( sig128Z, 1, sig128Z );
+            }
+        }
+    } else {
+        if ( shiftDist ) softfloat_add128M( sig128Z, sig128Z, sig128Z );
+        if ( ! expDiff ) {
+            sigZ =
+                (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
+                    | sig128Z[indexWord( 4, 2 )];
+        } else {
+            sig128C[indexWord( 4, 3 )] = sigC>>32;
+            sig128C[indexWord( 4, 2 )] = sigC;
+            sig128C[indexWord( 4, 1 )] = 0;
+            sig128C[indexWord( 4, 0 )] = 0;
+            softfloat_shiftRightJam128M( sig128C, expDiff, sig128C );
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( signZ == signC ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff <= 0 ) {
+            sigZ += sigC;
+        } else {
+            softfloat_add128M( sig128Z, sig128C, sig128Z );
+            sigZ =
+                (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
+                    | sig128Z[indexWord( 4, 2 )];
+        }
+        if ( sigZ & UINT64_C( 0x8000000000000000 ) ) {
+            ++expZ;
+            sigZ = softfloat_shortShiftRightJam64( sigZ, 1 );
+        }
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expDiff < 0 ) {
+            signZ = signC;
+            if ( expDiff < -1 ) {
+                sigZ = sigC - sigZ;
+                if (
+                    sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )]
+                ) {
+                    sigZ = (sigZ - 1) | 1;
+                }
+                if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
+                    --expZ;
+                    sigZ <<= 1;
+                }
+                goto roundPack;
+            } else {
+                sig128C[indexWord( 4, 3 )] = sigC>>32;
+                sig128C[indexWord( 4, 2 )] = sigC;
+                sig128C[indexWord( 4, 1 )] = 0;
+                sig128C[indexWord( 4, 0 )] = 0;
+                softfloat_sub128M( sig128C, sig128Z, sig128Z );
+            }
+        } else if ( ! expDiff ) {
+            sigZ -= sigC;
+            if (
+                ! sigZ && ! sig128Z[indexWord( 4, 1 )]
+                    && ! sig128Z[indexWord( 4, 0 )]
+            ) {
+                goto completeCancellation;
+            }
+            sig128Z[indexWord( 4, 3 )] = sigZ>>32;
+            sig128Z[indexWord( 4, 2 )] = sigZ;
+            if ( sigZ & UINT64_C( 0x8000000000000000 ) ) {
+                signZ = ! signZ;
+                softfloat_negX128M( sig128Z );
+            }
+        } else {
+            softfloat_sub128M( sig128Z, sig128C, sig128Z );
+            if ( 1 < expDiff ) {
+                sigZ =
+                    (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
+                        | sig128Z[indexWord( 4, 2 )];
+                if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) {
+                    --expZ;
+                    sigZ <<= 1;
+                }
+                goto sigZ;
+            }
+        }
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        shiftDist = 0;
+        sigZ =
+            (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
+                | sig128Z[indexWord( 4, 2 )];
+        if ( ! sigZ ) {
+            shiftDist = 64;
+            sigZ =
+                (uint64_t) sig128Z[indexWord( 4, 1 )]<<32
+                    | sig128Z[indexWord( 4, 0 )];
+        }
+        shiftDist += softfloat_countLeadingZeros64( sigZ ) - 1;
+        if ( shiftDist ) {
+            expZ -= shiftDist;
+            softfloat_shiftLeft128M( sig128Z, shiftDist, sig128Z );
+            sigZ =
+                (uint64_t) sig128Z[indexWord( 4, 3 )]<<32
+                    | sig128Z[indexWord( 4, 2 )];
+        }
+    }
+ sigZ:
+    if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1;
+ roundPack:
+    return softfloat_roundPackToF64( signZ, expZ - 1, sigZ );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN_ABC:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+    goto propagateNaN_ZC;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ infProdArg:
+    if ( magBits ) {
+        uiZ = packToF64UI( signZ, 0x7FF, 0 );
+        if ( expC != 0x7FF ) goto uiZ;
+        if ( sigC ) goto propagateNaN_ZC;
+        if ( signZ == signC ) goto uiZ;
+    }
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    uiZ = defaultNaNF64UI;
+ propagateNaN_ZC:
+    uiZ = softfloat_propagateNaNF64UI( uiZ, uiC );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ zeroProd:
+    uiZ = uiC;
+    if ( ! (expC | sigC) && (signZ != signC) ) {
+ completeCancellation:
+        uiZ =
+            packToF64UI(
+                (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+    }
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_negXM.c b/tb/riscv-isa-sim/softfloat/s_negXM.c
new file mode 100644
index 0000000000000000000000000000000000000000..76f110c1cf8cec850227ca3d5ad970c3581ce896
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_negXM.c
@@ -0,0 +1,63 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_negXM
+
+void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr )
+{
+    unsigned int index, lastIndex;
+    uint_fast8_t carry;
+    uint32_t word;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    carry = 1;
+    for (;;) {
+        word = ~zPtr[index] + carry;
+        zPtr[index] = word;
+        if ( index == lastIndex ) break;
+        index += wordIncr;
+        if ( word ) carry = 0;
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normRoundPackToF128.c b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF128.c
new file mode 100644
index 0000000000000000000000000000000000000000..148cb2c80c734cef4ded8f1cdc4f7b068c85199d
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF128.c
@@ -0,0 +1,81 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+float128_t
+ softfloat_normRoundPackToF128(
+     bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 )
+{
+    int_fast8_t shiftDist;
+    struct uint128 sig128;
+    union ui128_f128 uZ;
+    uint_fast64_t sigExtra;
+    struct uint128_extra sig128Extra;
+
+    if ( ! sig64 ) {
+        exp -= 64;
+        sig64 = sig0;
+        sig0 = 0;
+    }
+    shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
+    exp -= shiftDist;
+    if ( 0 <= shiftDist ) {
+        if ( shiftDist ) {
+            sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
+            sig64 = sig128.v64;
+            sig0  = sig128.v0;
+        }
+        if ( (uint32_t) exp < 0x7FFD ) {
+            uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 );
+            uZ.ui.v0  = sig0;
+            return uZ.f;
+        }
+        sigExtra = 0;
+    } else {
+        sig128Extra =
+            softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftDist );
+        sig64 = sig128Extra.v.v64;
+        sig0  = sig128Extra.v.v0;
+        sigExtra = sig128Extra.extra;
+    }
+    return softfloat_roundPackToF128( sign, exp, sig64, sig0, sigExtra );
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normRoundPackToF16.c b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF16.c
new file mode 100644
index 0000000000000000000000000000000000000000..6788f2e14aab89193525afe9a124b9badfab2b98
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF16.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+float16_t
+ softfloat_normRoundPackToF16( bool sign, int_fast16_t exp, uint_fast16_t sig )
+{
+    int_fast8_t shiftDist;
+    union ui16_f16 uZ;
+
+    shiftDist = softfloat_countLeadingZeros16( sig ) - 1;
+    exp -= shiftDist;
+    if ( (4 <= shiftDist) && ((unsigned int) exp < 0x1D) ) {
+        uZ.ui = packToF16UI( sign, sig ? exp : 0, sig<<(shiftDist - 4) );
+        return uZ.f;
+    } else {
+        return softfloat_roundPackToF16( sign, exp, sig<<shiftDist );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normRoundPackToF32.c b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF32.c
new file mode 100644
index 0000000000000000000000000000000000000000..14e08116b9b3a4e7b8f008972e682f808fe692f4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF32.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+float32_t
+ softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig )
+{
+    int_fast8_t shiftDist;
+    union ui32_f32 uZ;
+
+    shiftDist = softfloat_countLeadingZeros32( sig ) - 1;
+    exp -= shiftDist;
+    if ( (7 <= shiftDist) && ((unsigned int) exp < 0xFD) ) {
+        uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<(shiftDist - 7) );
+        return uZ.f;
+    } else {
+        return softfloat_roundPackToF32( sign, exp, sig<<shiftDist );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normRoundPackToF64.c b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF64.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f5d6a22fcd2c55c425c9330cc8834f8c05d88ee
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normRoundPackToF64.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+float64_t
+ softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig )
+{
+    int_fast8_t shiftDist;
+    union ui64_f64 uZ;
+
+    shiftDist = softfloat_countLeadingZeros64( sig ) - 1;
+    exp -= shiftDist;
+    if ( (10 <= shiftDist) && ((unsigned int) exp < 0x7FD) ) {
+        uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<(shiftDist - 10) );
+        return uZ.f;
+    } else {
+        return softfloat_roundPackToF64( sign, exp, sig<<shiftDist );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normSubnormalF128Sig.c b/tb/riscv-isa-sim/softfloat/s_normSubnormalF128Sig.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf02e102286d2761d39db8d2738528c6ee08ce9e
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normSubnormalF128Sig.c
@@ -0,0 +1,65 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+struct exp32_sig128
+ softfloat_normSubnormalF128Sig( uint_fast64_t sig64, uint_fast64_t sig0 )
+{
+    int_fast8_t shiftDist;
+    struct exp32_sig128 z;
+
+    if ( ! sig64 ) {
+        shiftDist = softfloat_countLeadingZeros64( sig0 ) - 15;
+        z.exp = -63 - shiftDist;
+        if ( shiftDist < 0 ) {
+            z.sig.v64 = sig0>>-shiftDist;
+            z.sig.v0  = sig0<<(shiftDist & 63);
+        } else {
+            z.sig.v64 = sig0<<shiftDist;
+            z.sig.v0  = 0;
+        }
+    } else {
+        shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
+        z.exp = 1 - shiftDist;
+        z.sig = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
+    }
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normSubnormalF16Sig.c b/tb/riscv-isa-sim/softfloat/s_normSubnormalF16Sig.c
new file mode 100644
index 0000000000000000000000000000000000000000..e612a9eb6d7edc4d4c23fd20f209332c44979ba4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normSubnormalF16Sig.c
@@ -0,0 +1,52 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t sig )
+{
+    int_fast8_t shiftDist;
+    struct exp8_sig16 z;
+
+    shiftDist = softfloat_countLeadingZeros16( sig ) - 5;
+    z.exp = 1 - shiftDist;
+    z.sig = sig<<shiftDist;
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normSubnormalF32Sig.c b/tb/riscv-isa-sim/softfloat/s_normSubnormalF32Sig.c
new file mode 100644
index 0000000000000000000000000000000000000000..e3e8ce44c8c078a86560d67c738b85e2900d5ff1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normSubnormalF32Sig.c
@@ -0,0 +1,52 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig )
+{
+    int_fast8_t shiftDist;
+    struct exp16_sig32 z;
+
+    shiftDist = softfloat_countLeadingZeros32( sig ) - 8;
+    z.exp = 1 - shiftDist;
+    z.sig = sig<<shiftDist;
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_normSubnormalF64Sig.c b/tb/riscv-isa-sim/softfloat/s_normSubnormalF64Sig.c
new file mode 100644
index 0000000000000000000000000000000000000000..fddfc32262fd45558fba8a7f07aa8441844200c2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_normSubnormalF64Sig.c
@@ -0,0 +1,52 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+
+struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig )
+{
+    int_fast8_t shiftDist;
+    struct exp16_sig64 z;
+
+    shiftDist = softfloat_countLeadingZeros64( sig ) - 11;
+    z.exp = 1 - shiftDist;
+    z.sig = sig<<shiftDist;
+    return z;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_propagateNaNF128UI.c b/tb/riscv-isa-sim/softfloat/s_propagateNaNF128UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..ad7e83b0fa640241033ffe079bc37ca0469496ef
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_propagateNaNF128UI.c
@@ -0,0 +1,73 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Interpreting the unsigned integer formed from concatenating `uiA64' and
+| `uiA0' as a 128-bit floating-point value, and likewise interpreting the
+| unsigned integer formed from concatenating `uiB64' and `uiB0' as another
+| 128-bit floating-point value, and assuming at least on of these floating-
+| point values is a NaN, returns the bit pattern of the combined NaN result.
+| If either original floating-point value is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+struct uint128
+ softfloat_propagateNaNF128UI(
+     uint_fast64_t uiA64,
+     uint_fast64_t uiA0,
+     uint_fast64_t uiB64,
+     uint_fast64_t uiB0
+ )
+{
+    struct uint128 uiZ;
+
+    if (
+           softfloat_isSigNaNF128UI( uiA64, uiA0 )
+        || softfloat_isSigNaNF128UI( uiB64, uiB0 )
+    ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+    }
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+    return uiZ;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_propagateNaNF16UI.c b/tb/riscv-isa-sim/softfloat/s_propagateNaNF16UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ecd4c982515d521289b9039894227023c57c6ca
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_propagateNaNF16UI.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Interpreting `uiA' and `uiB' as the bit patterns of two 16-bit floating-
+| point values, at least one of which is a NaN, returns the bit pattern of
+| the combined NaN result.  If either `uiA' or `uiB' has the pattern of a
+| signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+uint_fast16_t
+ softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB )
+{
+
+    if ( softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+    }
+    return defaultNaNF16UI;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_propagateNaNF32UI.c b/tb/riscv-isa-sim/softfloat/s_propagateNaNF32UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..b97fa41458e1c82f1f406a1fc713e0c506984873
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_propagateNaNF32UI.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating-
+| point values, at least one of which is a NaN, returns the bit pattern of
+| the combined NaN result.  If either `uiA' or `uiB' has the pattern of a
+| signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+uint_fast32_t
+ softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB )
+{
+
+    if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+    }
+    return defaultNaNF32UI;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_propagateNaNF64UI.c b/tb/riscv-isa-sim/softfloat/s_propagateNaNF64UI.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c2d359831910819cd0030c4911014f9db02a358
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_propagateNaNF64UI.c
@@ -0,0 +1,58 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating-
+| point values, at least one of which is a NaN, returns the bit pattern of
+| the combined NaN result.  If either `uiA' or `uiB' has the pattern of a
+| signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+uint_fast64_t
+ softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB )
+{
+
+    if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) {
+        softfloat_raiseFlags( softfloat_flag_invalid );
+    }
+    return defaultNaNF64UI;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_remStepMBy32.c b/tb/riscv-isa-sim/softfloat/s_remStepMBy32.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe787a430547552094d41407313a643e91dcf197
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_remStepMBy32.c
@@ -0,0 +1,86 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_remStepMBy32
+
+void
+ softfloat_remStepMBy32(
+     uint_fast8_t size_words,
+     const uint32_t *remPtr,
+     uint_fast8_t dist,
+     const uint32_t *bPtr,
+     uint32_t q,
+     uint32_t *zPtr
+ )
+{
+    unsigned int index, lastIndex;
+    uint64_t dwordProd;
+    uint32_t wordRem, wordShiftedRem, wordProd;
+    uint_fast8_t uNegDist, borrow;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    dwordProd = (uint64_t) bPtr[index] * q;
+    wordRem = remPtr[index];
+    wordShiftedRem = wordRem<<dist;
+    wordProd = dwordProd;
+    zPtr[index] = wordShiftedRem - wordProd;
+    if ( index != lastIndex ) {
+        uNegDist = -dist;
+        borrow = (wordShiftedRem < wordProd);
+        for (;;) {
+            wordShiftedRem = wordRem>>(uNegDist & 31);
+            index += wordIncr;
+            dwordProd = (uint64_t) bPtr[index] * q + (dwordProd>>32);
+            wordRem = remPtr[index];
+            wordShiftedRem |= wordRem<<dist;
+            wordProd = dwordProd;
+            zPtr[index] = wordShiftedRem - wordProd - borrow;
+            if ( index == lastIndex ) break;
+            borrow =
+                borrow ? (wordShiftedRem <= wordProd)
+                    : (wordShiftedRem < wordProd);
+        }
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundMToI64.c b/tb/riscv-isa-sim/softfloat/s_roundMToI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..a73f7f80325f185846668e7e630c61a1ae939cd5
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundMToI64.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t
+ softfloat_roundMToI64(
+     bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint32_t sigExtra;
+    bool doIncrement;
+    uint64_t sig;
+    union { uint64_t ui; int64_t i; } uZ;
+    int64_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    sigExtra = extSigPtr[indexWordLo( 3 )];
+    doIncrement = (0x80000000 <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    sig =
+        (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
+            | extSigPtr[indexWord( 3, 1 )];
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1;
+    }
+    uZ.ui = sign ? -sig : sig;
+    z = uZ.i;
+    if ( z && ((z < 0) ^ sign) ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundMToUI64.c b/tb/riscv-isa-sim/softfloat/s_roundMToUI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..0377c5bb6b3e3612fc3955e472408fbecb292ed2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundMToUI64.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t
+ softfloat_roundMToUI64(
+     bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint32_t sigExtra;
+    bool doIncrement;
+    uint64_t sig;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    sigExtra = extSigPtr[indexWordLo( 3 )];
+    doIncrement = (0x80000000 <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    sig =
+        (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
+            | extSigPtr[indexWord( 3, 1 )];
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1;
+    }
+    if ( sign && sig ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sig;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackMToI64.c b/tb/riscv-isa-sim/softfloat/s_roundPackMToI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..4d5efbb725ee36285e4ff76ca2156190dffc5c6c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackMToI64.c
@@ -0,0 +1,88 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a+, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t
+ softfloat_roundPackMToI64(
+     bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint32_t sigExtra;
+    bool doIncrement;
+    uint64_t sig;
+    union { uint64_t ui; int64_t i; } uZ;
+    int64_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    sigExtra = extSigPtr[indexWordLo( 3 )];
+    doIncrement = (0x80000000 <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    sig =
+        (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
+            | extSigPtr[indexWord( 3, 1 )];
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1;
+    }
+    uZ.ui = sign ? -sig : sig;
+    z = uZ.i;
+    if ( z && ((z < 0) ^ sign) ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackMToUI64.c b/tb/riscv-isa-sim/softfloat/s_roundPackMToUI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a64fdf98d49c14dab393f506c60f2b59bbece36
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackMToUI64.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a+, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t
+ softfloat_roundPackMToUI64(
+     bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint32_t sigExtra;
+    bool doIncrement;
+    uint64_t sig;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    sigExtra = extSigPtr[indexWordLo( 3 )];
+    doIncrement = (0x80000000 <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    sig =
+        (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32
+            | extSigPtr[indexWord( 3, 1 )];
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1;
+    }
+    if ( sign && sig ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sig;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToF128.c b/tb/riscv-isa-sim/softfloat/s_roundPackToF128.c
new file mode 100644
index 0000000000000000000000000000000000000000..eaaa375c9b52035a4ac228501596022a7bddaa6e
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToF128.c
@@ -0,0 +1,171 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t
+ softfloat_roundPackToF128(
+     bool sign,
+     int_fast32_t exp,
+     uint_fast64_t sig64,
+     uint_fast64_t sig0,
+     uint_fast64_t sigExtra
+ )
+{
+    uint_fast8_t roundingMode;
+    bool roundNearEven, doIncrement, isTiny;
+    struct uint128_extra sig128Extra;
+    uint_fast64_t uiZ64, uiZ0;
+    struct uint128 sig128;
+    union ui128_f128 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundingMode = softfloat_roundingMode;
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x7FFD <= (uint32_t) exp ) {
+        if ( exp < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            isTiny =
+                   (softfloat_detectTininess
+                        == softfloat_tininess_beforeRounding)
+                || (exp < -1)
+                || ! doIncrement
+                || softfloat_lt128(
+                       sig64,
+                       sig0,
+                       UINT64_C( 0x0001FFFFFFFFFFFF ),
+                       UINT64_C( 0xFFFFFFFFFFFFFFFF )
+                   );
+            sig128Extra =
+                softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp );
+            sig64 = sig128Extra.v.v64;
+            sig0  = sig128Extra.v.v0;
+            sigExtra = sig128Extra.extra;
+            exp = 0;
+            if ( isTiny && sigExtra ) {
+                softfloat_raiseFlags( softfloat_flag_underflow );
+            }
+            doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
+            if (
+                   ! roundNearEven
+                && (roundingMode != softfloat_round_near_maxMag)
+            ) {
+                doIncrement =
+                    (roundingMode
+                         == (sign ? softfloat_round_min : softfloat_round_max))
+                        && sigExtra;
+            }
+        } else if (
+               (0x7FFD < exp)
+            || ((exp == 0x7FFD)
+                    && softfloat_eq128( 
+                           sig64,
+                           sig0,
+                           UINT64_C( 0x0001FFFFFFFFFFFF ),
+                           UINT64_C( 0xFFFFFFFFFFFFFFFF )
+                       )
+                    && doIncrement)
+        ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            softfloat_raiseFlags(
+                softfloat_flag_overflow | softfloat_flag_inexact );
+            if (
+                   roundNearEven
+                || (roundingMode == softfloat_round_near_maxMag)
+                || (roundingMode
+                        == (sign ? softfloat_round_min : softfloat_round_max))
+            ) {
+                uiZ64 = packToF128UI64( sign, 0x7FFF, 0 );
+                uiZ0  = 0;
+            } else {
+                uiZ64 =
+                    packToF128UI64(
+                        sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) );
+                uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+            }
+            goto uiZ;
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+#ifdef SOFTFLOAT_ROUND_ODD
+        if ( roundingMode == softfloat_round_odd ) {
+            sig0 |= 1;
+            goto packReturn;
+        }
+#endif
+    }
+    if ( doIncrement ) {
+        sig128 = softfloat_add128( sig64, sig0, 0, 1 );
+        sig64 = sig128.v64;
+        sig0 =
+            sig128.v0
+                & ~(uint64_t)
+                       (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                            & roundNearEven);
+    } else {
+        if ( ! (sig64 | sig0) ) exp = 0;
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ packReturn:
+    uiZ64 = packToF128UI64( sign, exp, sig64 );
+    uiZ0  = sig0;
+ uiZ:
+    uZ.ui.v64 = uiZ64;
+    uZ.ui.v0  = uiZ0;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToF16.c b/tb/riscv-isa-sim/softfloat/s_roundPackToF16.c
new file mode 100644
index 0000000000000000000000000000000000000000..0eaa73a5f00c02786f71ae0f750e77bbaef7328f
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToF16.c
@@ -0,0 +1,113 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t
+ softfloat_roundPackToF16( bool sign, int_fast16_t exp, uint_fast16_t sig )
+{
+    uint_fast8_t roundingMode;
+    bool roundNearEven;
+    uint_fast8_t roundIncrement, roundBits;
+    bool isTiny;
+    uint_fast16_t uiZ;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundingMode = softfloat_roundingMode;
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x8;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0xF
+                : 0;
+    }
+    roundBits = sig & 0xF;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x1D <= (unsigned int) exp ) {
+        if ( exp < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            isTiny =
+                (softfloat_detectTininess == softfloat_tininess_beforeRounding)
+                    || (exp < -1) || (sig + roundIncrement < 0x8000);
+            sig = softfloat_shiftRightJam32( sig, -exp );
+            exp = 0;
+            roundBits = sig & 0xF;
+            if ( isTiny && roundBits ) {
+                softfloat_raiseFlags( softfloat_flag_underflow );
+            }
+        } else if ( (0x1D < exp) || (0x8000 <= sig + roundIncrement) ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            softfloat_raiseFlags(
+                softfloat_flag_overflow | softfloat_flag_inexact );
+            uiZ = packToF16UI( sign, 0x1F, 0 ) - ! roundIncrement;
+            goto uiZ;
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig = (sig + roundIncrement)>>4;
+    if ( roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+#ifdef SOFTFLOAT_ROUND_ODD
+        if ( roundingMode == softfloat_round_odd ) {
+            sig |= 1;
+            goto packReturn;
+        }
+#endif
+    }
+    sig &= ~(uint_fast16_t) (! (roundBits ^ 8) & roundNearEven);
+    if ( ! sig ) exp = 0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ packReturn:
+    uiZ = packToF16UI( sign, exp, sig );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToF32.c b/tb/riscv-isa-sim/softfloat/s_roundPackToF32.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc3450857036558ec5848b9acc5f1fcf14356e83
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToF32.c
@@ -0,0 +1,113 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t
+ softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig )
+{
+    uint_fast8_t roundingMode;
+    bool roundNearEven;
+    uint_fast8_t roundIncrement, roundBits;
+    bool isTiny;
+    uint_fast32_t uiZ;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundingMode = softfloat_roundingMode;
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x40;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0x7F
+                : 0;
+    }
+    roundBits = sig & 0x7F;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0xFD <= (unsigned int) exp ) {
+        if ( exp < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            isTiny =
+                (softfloat_detectTininess == softfloat_tininess_beforeRounding)
+                    || (exp < -1) || (sig + roundIncrement < 0x80000000);
+            sig = softfloat_shiftRightJam32( sig, -exp );
+            exp = 0;
+            roundBits = sig & 0x7F;
+            if ( isTiny && roundBits ) {
+                softfloat_raiseFlags( softfloat_flag_underflow );
+            }
+        } else if ( (0xFD < exp) || (0x80000000 <= sig + roundIncrement) ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            softfloat_raiseFlags(
+                softfloat_flag_overflow | softfloat_flag_inexact );
+            uiZ = packToF32UI( sign, 0xFF, 0 ) - ! roundIncrement;
+            goto uiZ;
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig = (sig + roundIncrement)>>7;
+    if ( roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+#ifdef SOFTFLOAT_ROUND_ODD
+        if ( roundingMode == softfloat_round_odd ) {
+            sig |= 1;
+            goto packReturn;
+        }
+#endif
+    }
+    sig &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven);
+    if ( ! sig ) exp = 0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ packReturn:
+    uiZ = packToF32UI( sign, exp, sig );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToF64.c b/tb/riscv-isa-sim/softfloat/s_roundPackToF64.c
new file mode 100644
index 0000000000000000000000000000000000000000..aaff008c1d377d9fd2b9639a4af4195492ac19e6
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToF64.c
@@ -0,0 +1,117 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t
+ softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig )
+{
+    uint_fast8_t roundingMode;
+    bool roundNearEven;
+    uint_fast16_t roundIncrement, roundBits;
+    bool isTiny;
+    uint_fast64_t uiZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundingMode = softfloat_roundingMode;
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x200;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0x3FF
+                : 0;
+    }
+    roundBits = sig & 0x3FF;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    if ( 0x7FD <= (uint16_t) exp ) {
+        if ( exp < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            isTiny =
+                (softfloat_detectTininess == softfloat_tininess_beforeRounding)
+                    || (exp < -1)
+                    || (sig + roundIncrement < UINT64_C( 0x8000000000000000 ));
+            sig = softfloat_shiftRightJam64( sig, -exp );
+            exp = 0;
+            roundBits = sig & 0x3FF;
+            if ( isTiny && roundBits ) {
+                softfloat_raiseFlags( softfloat_flag_underflow );
+            }
+        } else if (
+            (0x7FD < exp)
+                || (UINT64_C( 0x8000000000000000 ) <= sig + roundIncrement)
+        ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            softfloat_raiseFlags(
+                softfloat_flag_overflow | softfloat_flag_inexact );
+            uiZ = packToF64UI( sign, 0x7FF, 0 ) - ! roundIncrement;
+            goto uiZ;
+        }
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    sig = (sig + roundIncrement)>>10;
+    if ( roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+#ifdef SOFTFLOAT_ROUND_ODD
+        if ( roundingMode == softfloat_round_odd ) {
+            sig |= 1;
+            goto packReturn;
+        }
+#endif
+    }
+    sig &= ~(uint_fast64_t) (! (roundBits ^ 0x200) & roundNearEven);
+    if ( ! sig ) exp = 0;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ packReturn:
+    uiZ = packToF64UI( sign, exp, sig );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToI32.c b/tb/riscv-isa-sim/softfloat/s_roundPackToI32.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ece8f052e80e102df292c26b0e87f61d577b965
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToI32.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a+, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t
+ softfloat_roundPackToI32(
+     bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint_fast8_t roundIncrement, roundBits;
+    uint_fast32_t sig32;
+    union { uint32_t ui; int32_t i; } uZ;
+    int_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x40;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0x7F
+                : 0;
+    }
+    roundBits = sig & 0x7F;
+    sig += roundIncrement;
+    if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid;
+    sig32 = sig>>7;
+    sig32 &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven);
+    uZ.ui = sign ? -sig32 : sig32;
+    z = uZ.i;
+    if ( z && ((z < 0) ^ sign) ) goto invalid;
+    if ( exact && roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToI64.c b/tb/riscv-isa-sim/softfloat/s_roundPackToI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..ebef7f3647b1890aee5137820603082e224fd3fc
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToI64.c
@@ -0,0 +1,89 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a+, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t
+ softfloat_roundPackToI64(
+     bool sign,
+     uint_fast64_t sig,
+     uint_fast64_t sigExtra,
+     uint_fast8_t roundingMode,
+     bool exact
+ )
+{
+    bool roundNearEven, doIncrement;
+    union { uint64_t ui; int64_t i; } uZ;
+    int_fast64_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        sig &=
+            ~(uint_fast64_t)
+                 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                      & roundNearEven);
+    }
+    uZ.ui = sign ? -sig : sig;
+    z = uZ.i;
+    if ( z && ((z < 0) ^ sign) ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToUI32.c b/tb/riscv-isa-sim/softfloat/s_roundPackToUI32.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0021fe54cdd2e92fc053dd1c2612c21fbfbb045
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToUI32.c
@@ -0,0 +1,80 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a+, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t
+ softfloat_roundPackToUI32(
+     bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint_fast8_t roundIncrement, roundBits;
+    uint_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x40;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0x7F
+                : 0;
+    }
+    roundBits = sig & 0x7F;
+    sig += roundIncrement;
+    if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid;
+    z = sig>>7;
+    z &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven);
+    if ( sign && z ) goto invalid;
+    if ( exact && roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundPackToUI64.c b/tb/riscv-isa-sim/softfloat/s_roundPackToUI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..fada1840c6eeb28f362d8437ba4535334fd776cc
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundPackToUI64.c
@@ -0,0 +1,85 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3a+, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t
+ softfloat_roundPackToUI64(
+     bool sign,
+     uint_fast64_t sig,
+     uint_fast64_t sigExtra,
+     uint_fast8_t roundingMode,
+     bool exact
+ )
+{
+    bool roundNearEven, doIncrement;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        sig &=
+            ~(uint_fast64_t)
+                 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                      & roundNearEven);
+    }
+    if ( sign && sig ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sig;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundToI32.c b/tb/riscv-isa-sim/softfloat/s_roundToI32.c
new file mode 100644
index 0000000000000000000000000000000000000000..20a3ff4f65296f2e865e7edfefc865bce5e558ce
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundToI32.c
@@ -0,0 +1,84 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast32_t
+ softfloat_roundToI32(
+     bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint_fast16_t roundIncrement, roundBits;
+    uint_fast32_t sig32;
+    union { uint32_t ui; int32_t i; } uZ;
+    int_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x800;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0xFFF
+                : 0;
+    }
+    roundBits = sig & 0xFFF;
+    sig += roundIncrement;
+    if ( sig & UINT64_C( 0xFFFFF00000000000 ) ) goto invalid;
+    sig32 = sig>>12;
+    sig32 &= ~(uint_fast32_t) (! (roundBits ^ 0x800) & roundNearEven);
+    uZ.ui = sign ? -sig32 : sig32;
+    z = uZ.i;
+    if ( z && ((z < 0) ^ sign) ) goto invalid;
+    if ( exact && roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundToI64.c b/tb/riscv-isa-sim/softfloat/s_roundToI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..fcddbc2785e724779e94ce029efd373a8996651e
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundToI64.c
@@ -0,0 +1,89 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int_fast64_t
+ softfloat_roundToI64(
+     bool sign,
+     uint_fast64_t sig,
+     uint_fast64_t sigExtra,
+     uint_fast8_t roundingMode,
+     bool exact
+ )
+{
+    bool roundNearEven, doIncrement;
+    union { uint64_t ui; int64_t i; } uZ;
+    int_fast64_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        sig &=
+            ~(uint_fast64_t)
+                 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                      & roundNearEven);
+    }
+    uZ.ui = sign ? -sig : sig;
+    z = uZ.i;
+    if ( z && ((z < 0) ^ sign) ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundToUI32.c b/tb/riscv-isa-sim/softfloat/s_roundToUI32.c
new file mode 100644
index 0000000000000000000000000000000000000000..180899bd854ec44016518ff1a588a03a1289ed40
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundToUI32.c
@@ -0,0 +1,80 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast32_t
+ softfloat_roundToUI32(
+     bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact )
+{
+    bool roundNearEven;
+    uint_fast16_t roundIncrement, roundBits;
+    uint_fast32_t z;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    roundIncrement = 0x800;
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        roundIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                ? 0xFFF
+                : 0;
+    }
+    roundBits = sig & 0xFFF;
+    sig += roundIncrement;
+    if ( sig & UINT64_C( 0xFFFFF00000000000 ) ) goto invalid;
+    z = sig>>12;
+    z &= ~(uint_fast32_t) (! (roundBits ^ 0x800) & roundNearEven);
+    if ( sign && z ) goto invalid;
+    if ( exact && roundBits ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return z;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_roundToUI64.c b/tb/riscv-isa-sim/softfloat/s_roundToUI64.c
new file mode 100644
index 0000000000000000000000000000000000000000..de35b5eb0e6ff9b8c9b39e21251e02e427cde625
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_roundToUI64.c
@@ -0,0 +1,85 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint_fast64_t
+ softfloat_roundToUI64(
+     bool sign,
+     uint_fast64_t sig,
+     uint_fast64_t sigExtra,
+     uint_fast8_t roundingMode,
+     bool exact
+ )
+{
+    bool roundNearEven, doIncrement;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    roundNearEven = (roundingMode == softfloat_round_near_even);
+    doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
+    if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
+        doIncrement =
+            (roundingMode
+                 == (sign ? softfloat_round_min : softfloat_round_max))
+                && sigExtra;
+    }
+    if ( doIncrement ) {
+        ++sig;
+        if ( ! sig ) goto invalid;
+        sig &=
+            ~(uint_fast64_t)
+                 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
+                      & roundNearEven);
+    }
+    if ( sign && sig ) goto invalid;
+    if ( exact && sigExtra ) {
+        softfloat_exceptionFlags |= softfloat_flag_inexact;
+    }
+    return sig;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ invalid:
+    softfloat_raiseFlags( softfloat_flag_invalid );
+    return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shiftRightJam128.c b/tb/riscv-isa-sim/softfloat/s_shiftRightJam128.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d2b91e87df1d5d4bdf3d6c03bcc949f108d77ad
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shiftRightJam128.c
@@ -0,0 +1,69 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shiftRightJam128
+
+struct uint128
+ softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist )
+{
+    uint_fast8_t u8NegDist;
+    struct uint128 z;
+
+    if ( dist < 64 ) {
+        u8NegDist = -dist;
+        z.v64 = a64>>dist;
+        z.v0 =
+            a64<<(u8NegDist & 63) | a0>>dist
+                | ((uint64_t) (a0<<(u8NegDist & 63)) != 0);
+    } else {
+        z.v64 = 0;
+        z.v0 =
+            (dist < 127)
+                ? a64>>(dist & 63)
+                      | (((a64 & (((uint_fast64_t) 1<<(dist & 63)) - 1)) | a0)
+                             != 0)
+                : ((a64 | a0) != 0);
+    }
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shiftRightJam128Extra.c b/tb/riscv-isa-sim/softfloat/s_shiftRightJam128Extra.c
new file mode 100644
index 0000000000000000000000000000000000000000..4e1293c74a4ff3b1d59a50790e7299e6a7539aa1
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shiftRightJam128Extra.c
@@ -0,0 +1,77 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shiftRightJam128Extra
+
+struct uint128_extra
+ softfloat_shiftRightJam128Extra(
+     uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist )
+{
+    uint_fast8_t u8NegDist;
+    struct uint128_extra z;
+
+    u8NegDist = -dist;
+    if ( dist < 64 ) {
+        z.v.v64 = a64>>dist;
+        z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist;
+        z.extra = a0<<(u8NegDist & 63);
+    } else {
+        z.v.v64 = 0;
+        if ( dist == 64 ) {
+            z.v.v0 = a64;
+            z.extra = a0;
+        } else {
+            extra |= a0;
+            if ( dist < 128 ) {
+                z.v.v0 = a64>>(dist & 63);
+                z.extra = a64<<(u8NegDist & 63);
+            } else {
+                z.v.v0 = 0;
+                z.extra = (dist == 128) ? a64 : (a64 != 0);
+            }
+        }
+    }
+    z.extra |= (extra != 0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shiftRightJam256M.c b/tb/riscv-isa-sim/softfloat/s_shiftRightJam256M.c
new file mode 100644
index 0000000000000000000000000000000000000000..04cd1e50843f6f8a5b9829653eda328e2d1c41cb
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shiftRightJam256M.c
@@ -0,0 +1,126 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shiftRightJam256M
+
+static
+ void
+  softfloat_shortShiftRightJamM(
+      uint_fast8_t size_words,
+      const uint64_t *aPtr,
+      uint_fast8_t dist,
+      uint64_t *zPtr
+  )
+{
+    uint_fast8_t uNegDist;
+    unsigned int index, lastIndex;
+    uint64_t partWordZ, wordA;
+
+    uNegDist = -dist;
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    wordA = aPtr[index];
+    partWordZ = wordA>>dist;
+    if ( partWordZ<<dist != wordA ) partWordZ |= 1;
+    while ( index != lastIndex ) {
+        wordA = aPtr[index + wordIncr];
+        zPtr[index] = wordA<<(uNegDist & 63) | partWordZ;
+        index += wordIncr;
+        partWordZ = wordA>>dist;
+    }
+    zPtr[index] = partWordZ;
+
+}
+
+void
+ softfloat_shiftRightJam256M(
+     const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr )
+{
+    uint64_t wordJam;
+    uint_fast32_t wordDist;
+    uint64_t *ptr;
+    uint_fast8_t i, innerDist;
+
+    wordJam = 0;
+    wordDist = dist>>6;
+    if ( wordDist ) {
+        if ( 4 < wordDist ) wordDist = 4;
+        ptr = (uint64_t *) (aPtr + indexMultiwordLo( 4, wordDist ));
+        i = wordDist;
+        do {
+            wordJam = *ptr++;
+            if ( wordJam ) break;
+            --i;
+        } while ( i );
+        ptr = zPtr;
+    }
+    if ( wordDist < 4 ) {
+        aPtr += indexMultiwordHiBut( 4, wordDist );
+        innerDist = dist & 63;
+        if ( innerDist ) {
+            softfloat_shortShiftRightJamM(
+                4 - wordDist,
+                aPtr,
+                innerDist,
+                zPtr + indexMultiwordLoBut( 4, wordDist )
+            );
+            if ( ! wordDist ) goto wordJam;
+        } else {
+            aPtr += indexWordLo( 4 - wordDist );
+            ptr = zPtr + indexWordLo( 4 );
+            for ( i = 4 - wordDist; i; --i ) {
+                *ptr = *aPtr;
+                aPtr += wordIncr;
+                ptr += wordIncr;
+            }
+        }
+        ptr = zPtr + indexMultiwordHi( 4, wordDist );
+    }
+    do {
+        *ptr++ = 0;
+        --wordDist;
+    } while ( wordDist );
+ wordJam:
+    if ( wordJam ) zPtr[indexWordLo( 4 )] |= 1;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shiftRightJam32.c b/tb/riscv-isa-sim/softfloat/s_shiftRightJam32.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbc3aa01100243ebf7e13fb93b0c252d73649771
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shiftRightJam32.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_shiftRightJam32
+
+uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
+{
+
+    return
+        (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shiftRightJam64.c b/tb/riscv-isa-sim/softfloat/s_shiftRightJam64.c
new file mode 100644
index 0000000000000000000000000000000000000000..34edd7bf8fbca47455b604c1217101174d757e08
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shiftRightJam64.c
@@ -0,0 +1,51 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_shiftRightJam64
+
+uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
+{
+
+    return
+        (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shiftRightJam64Extra.c b/tb/riscv-isa-sim/softfloat/s_shiftRightJam64Extra.c
new file mode 100644
index 0000000000000000000000000000000000000000..4d7871226e56107ed72458fe5f6183a948ac78c0
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shiftRightJam64Extra.c
@@ -0,0 +1,62 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shiftRightJam64Extra
+
+struct uint64_extra
+ softfloat_shiftRightJam64Extra(
+     uint64_t a, uint64_t extra, uint_fast32_t dist )
+{
+    struct uint64_extra z;
+
+    if ( dist < 64 ) {
+        z.v = a>>dist;
+        z.extra = a<<(-dist & 63);
+    } else {
+        z.v = 0;
+        z.extra = (dist == 64) ? a : (a != 0);
+    }
+    z.extra |= (extra != 0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftLeft128.c b/tb/riscv-isa-sim/softfloat/s_shortShiftLeft128.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b7c06726a706bbbde65979da279f35cd8b46272
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftLeft128.c
@@ -0,0 +1,55 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftLeft128
+
+struct uint128
+ softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
+{
+    struct uint128 z;
+
+    z.v64 = a64<<dist | a0>>(-dist & 63);
+    z.v0 = a0<<dist;
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftLeft64To96M.c b/tb/riscv-isa-sim/softfloat/s_shortShiftLeft64To96M.c
new file mode 100644
index 0000000000000000000000000000000000000000..4caf4b9d6ecc86f05a5b44a329c9820100e3fe62
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftLeft64To96M.c
@@ -0,0 +1,56 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftLeft64To96M
+
+void
+ softfloat_shortShiftLeft64To96M(
+     uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
+{
+
+    zPtr[indexWord( 3, 0 )] = (uint32_t) a<<dist;
+    a >>= 32 - dist;
+    zPtr[indexWord( 3, 2 )] = a>>32;
+    zPtr[indexWord( 3, 1 )] = a;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRight128.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRight128.c
new file mode 100644
index 0000000000000000000000000000000000000000..28c39bb273f57e10b6dd21090c0225e23f43fe5c
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRight128.c
@@ -0,0 +1,55 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftRight128
+
+struct uint128
+ softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
+{
+    struct uint128 z;
+
+    z.v64 = a64>>dist;
+    z.v0 = a64<<(-dist & 63) | a0>>dist;
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRightExtendM.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRightExtendM.c
new file mode 100644
index 0000000000000000000000000000000000000000..309188c356644943823e65e3b2caab0a0a470f30
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRightExtendM.c
@@ -0,0 +1,73 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftRightExtendM
+
+void
+ softfloat_shortShiftRightExtendM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint_fast8_t dist,
+     uint32_t *zPtr
+ )
+{
+    uint_fast8_t uNegDist;
+    unsigned int indexA, lastIndexA;
+    uint32_t partWordZ, wordA;
+
+    uNegDist = -dist;
+    indexA = indexWordLo( size_words );
+    lastIndexA = indexWordHi( size_words );
+    zPtr += indexWordLo( size_words + 1 );
+    partWordZ = 0;
+    for (;;) {
+        wordA = aPtr[indexA];
+        *zPtr = wordA<<(uNegDist & 31) | partWordZ;
+        zPtr += wordIncr;
+        partWordZ = wordA>>dist;
+        if ( indexA == lastIndexA ) break;
+        indexA += wordIncr;
+    }
+    *zPtr = partWordZ;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam128.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam128.c
new file mode 100644
index 0000000000000000000000000000000000000000..3eb0dd4006e500b32dca6681c33cb8ef8683a240
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam128.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftRightJam128
+
+struct uint128
+ softfloat_shortShiftRightJam128(
+     uint64_t a64, uint64_t a0, uint_fast8_t dist )
+{
+    uint_fast8_t uNegDist;
+    struct uint128 z;
+
+    uNegDist = -dist;
+    z.v64 = a64>>dist;
+    z.v0 =
+        a64<<(uNegDist & 63) | a0>>dist
+            | ((uint64_t) (a0<<(uNegDist & 63)) != 0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam128Extra.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam128Extra.c
new file mode 100644
index 0000000000000000000000000000000000000000..13692a0d6014b0da9f426ff882f56aab074014b2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam128Extra.c
@@ -0,0 +1,59 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftRightJam128Extra
+
+struct uint128_extra
+ softfloat_shortShiftRightJam128Extra(
+     uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
+{
+    uint_fast8_t uNegDist;
+    struct uint128_extra z;
+
+    uNegDist = -dist;
+    z.v.v64 = a64>>dist;
+    z.v.v0 = a64<<(uNegDist & 63) | a0>>dist;
+    z.extra = a0<<(uNegDist & 63) | (extra != 0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam64.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam64.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e93cd4fbd94b41fc50a84c0a14442ec1a558e7f
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam64.c
@@ -0,0 +1,50 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+
+#ifndef softfloat_shortShiftRightJam64
+
+uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
+{
+
+    return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0);
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam64Extra.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam64Extra.c
new file mode 100644
index 0000000000000000000000000000000000000000..25d23f4b9411ca12f18c2ffec084d6d2e6ca4684
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRightJam64Extra.c
@@ -0,0 +1,56 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftRightJam64Extra
+
+struct uint64_extra
+ softfloat_shortShiftRightJam64Extra(
+     uint64_t a, uint64_t extra, uint_fast8_t dist )
+{
+    struct uint64_extra z;
+
+    z.v = a>>dist;
+    z.extra = a<<(-dist & 63) | (extra != 0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_shortShiftRightM.c b/tb/riscv-isa-sim/softfloat/s_shortShiftRightM.c
new file mode 100644
index 0000000000000000000000000000000000000000..308ad59c5743c1a092f6fc2df45a88e2c01559c2
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_shortShiftRightM.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_shortShiftRightM
+
+void
+ softfloat_shortShiftRightM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     uint_fast8_t dist,
+     uint32_t *zPtr
+ )
+{
+    uint_fast8_t uNegDist;
+    unsigned int index, lastIndex;
+    uint32_t partWordZ, wordA;
+
+    uNegDist = -dist;
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    partWordZ = aPtr[index]>>dist;
+    while ( index != lastIndex ) {
+        wordA = aPtr[index + wordIncr];
+        zPtr[index] = wordA<<(uNegDist & 31) | partWordZ;
+        index += wordIncr;
+        partWordZ = wordA>>dist;
+    }
+    zPtr[index] = partWordZ;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_sub128.c b/tb/riscv-isa-sim/softfloat/s_sub128.c
new file mode 100644
index 0000000000000000000000000000000000000000..ed86e1000571dad3bf945e7c2a0bbe8daeae91c4
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_sub128.c
@@ -0,0 +1,55 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_sub128
+
+struct uint128
+ softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
+{
+    struct uint128 z;
+
+    z.v0 = a0 - b0;
+    z.v64 = a64 - b64 - (a0 < b0);
+    return z;
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_sub1XM.c b/tb/riscv-isa-sim/softfloat/s_sub1XM.c
new file mode 100644
index 0000000000000000000000000000000000000000..73773e5b0324b88720bf9c2c73bbc35001af7dbb
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_sub1XM.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_sub1XM
+
+void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr )
+{
+    unsigned int index, lastIndex;
+    uint32_t wordA;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    for (;;) {
+        wordA = zPtr[index];
+        zPtr[index] = wordA - 1;
+        if ( wordA || (index == lastIndex) ) break;
+        index += wordIncr;
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_sub256M.c b/tb/riscv-isa-sim/softfloat/s_sub256M.c
new file mode 100644
index 0000000000000000000000000000000000000000..c07b45eae9f6728f5ce4ea01298b7820b1b612d6
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_sub256M.c
@@ -0,0 +1,65 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_sub256M
+
+void
+ softfloat_sub256M(
+     const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr )
+{
+    unsigned int index;
+    uint_fast8_t borrow;
+    uint64_t wordA, wordB;
+
+    index = indexWordLo( 4 );
+    borrow = 0;
+    for (;;) {
+        wordA = aPtr[index];
+        wordB = bPtr[index];
+        zPtr[index] = wordA - wordB - borrow;
+        if ( index == indexWordHi( 4 ) ) break;
+        borrow = borrow ? (wordA <= wordB) : (wordA < wordB);
+        index += wordIncr;
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_subM.c b/tb/riscv-isa-sim/softfloat/s_subM.c
new file mode 100644
index 0000000000000000000000000000000000000000..003f699f14920be0eebf25ba011a9cf11b5c6760
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_subM.c
@@ -0,0 +1,70 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "primitiveTypes.h"
+
+#ifndef softfloat_subM
+
+void
+ softfloat_subM(
+     uint_fast8_t size_words,
+     const uint32_t *aPtr,
+     const uint32_t *bPtr,
+     uint32_t *zPtr
+ )
+{
+    unsigned int index, lastIndex;
+    uint_fast8_t borrow;
+    uint32_t wordA, wordB;
+
+    index = indexWordLo( size_words );
+    lastIndex = indexWordHi( size_words );
+    borrow = 0;
+    for (;;) {
+        wordA = aPtr[index];
+        wordB = bPtr[index];
+        zPtr[index] = wordA - wordB - borrow;
+        if ( index == lastIndex ) break;
+        borrow = borrow ? (wordA <= wordB) : (wordA < wordB);
+        index += wordIncr;
+    }
+
+}
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/s_subMagsF128.c b/tb/riscv-isa-sim/softfloat/s_subMagsF128.c
new file mode 100644
index 0000000000000000000000000000000000000000..c4264d542bb353cafa7933b901e1ed1a33aa12ef
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_subMagsF128.c
@@ -0,0 +1,139 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t
+ softfloat_subMagsF128(
+     uint_fast64_t uiA64,
+     uint_fast64_t uiA0,
+     uint_fast64_t uiB64,
+     uint_fast64_t uiB0,
+     bool signZ
+ )
+{
+    int_fast32_t expA;
+    struct uint128 sigA;
+    int_fast32_t expB;
+    struct uint128 sigB, sigZ;
+    int_fast32_t expDiff, expZ;
+    struct uint128 uiZ;
+    union ui128_f128 uZ;
+
+    expA = expF128UI64( uiA64 );
+    sigA.v64 = fracF128UI64( uiA64 );
+    sigA.v0  = uiA0;
+    expB = expF128UI64( uiB64 );
+    sigB.v64 = fracF128UI64( uiB64 );
+    sigB.v0  = uiB0;
+    sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 );
+    sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 );
+    expDiff = expA - expB;
+    if ( 0 < expDiff ) goto expABigger;
+    if ( expDiff < 0 ) goto expBBigger;
+    if ( expA == 0x7FFF ) {
+        if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
+        softfloat_raiseFlags( softfloat_flag_invalid );
+        uiZ.v64 = defaultNaNF128UI64;
+        uiZ.v0  = defaultNaNF128UI0;
+        goto uiZ;
+    }
+    expZ = expA;
+    if ( ! expZ ) expZ = 1;
+    if ( sigB.v64 < sigA.v64 ) goto aBigger;
+    if ( sigA.v64 < sigB.v64 ) goto bBigger;
+    if ( sigB.v0 < sigA.v0 ) goto aBigger;
+    if ( sigA.v0 < sigB.v0 ) goto bBigger;
+    uiZ.v64 =
+        packToF128UI64(
+            (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+    uiZ.v0 = 0;
+    goto uiZ;
+ expBBigger:
+    if ( expB == 0x7FFF ) {
+        if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
+        uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 );
+        uiZ.v0  = 0;
+        goto uiZ;
+    }
+    if ( expA ) {
+        sigA.v64 |= UINT64_C( 0x0010000000000000 );
+    } else {
+        ++expDiff;
+        if ( ! expDiff ) goto newlyAlignedBBigger;
+    }
+    sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff );
+ newlyAlignedBBigger:
+    expZ = expB;
+    sigB.v64 |= UINT64_C( 0x0010000000000000 );
+ bBigger:
+    signZ = ! signZ;
+    sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 );
+    goto normRoundPack;
+ expABigger:
+    if ( expA == 0x7FFF ) {
+        if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
+        uiZ.v64 = uiA64;
+        uiZ.v0  = uiA0;
+        goto uiZ;
+    }
+    if ( expB ) {
+        sigB.v64 |= UINT64_C( 0x0010000000000000 );
+    } else {
+        --expDiff;
+        if ( ! expDiff ) goto newlyAlignedABigger;
+    }
+    sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff );
+ newlyAlignedABigger:
+    expZ = expA;
+    sigA.v64 |= UINT64_C( 0x0010000000000000 );
+ aBigger:
+    sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
+ normRoundPack:
+    return softfloat_normRoundPackToF128( signZ, expZ - 5, sigZ.v64, sigZ.v0 );
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_subMagsF16.c b/tb/riscv-isa-sim/softfloat/s_subMagsF16.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ec579e8829f519ef0f5a379c7b34af5f0d29601
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_subMagsF16.c
@@ -0,0 +1,187 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16_t softfloat_subMagsF16( uint_fast16_t uiA, uint_fast16_t uiB )
+{
+    int_fast8_t expA;
+    uint_fast16_t sigA;
+    int_fast8_t expB;
+    uint_fast16_t sigB;
+    int_fast8_t expDiff;
+    uint_fast16_t uiZ;
+    int_fast16_t sigDiff;
+    bool signZ;
+    int_fast8_t shiftDist, expZ;
+    uint_fast16_t sigZ, sigX, sigY;
+    uint_fast32_t sig32Z;
+    int_fast8_t roundingMode;
+    union ui16_f16 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expA = expF16UI( uiA );
+    sigA = fracF16UI( uiA );
+    expB = expF16UI( uiB );
+    sigB = fracF16UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expA == 0x1F ) {
+            if ( sigA | sigB ) goto propagateNaN;
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            uiZ = defaultNaNF16UI;
+            goto uiZ;
+        }
+        sigDiff = sigA - sigB;
+        if ( ! sigDiff ) {
+            uiZ =
+                packToF16UI(
+                    (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+            goto uiZ;
+        }
+        if ( expA ) --expA;
+        signZ = signF16UI( uiA );
+        if ( sigDiff < 0 ) {
+            signZ = ! signZ;
+            sigDiff = -sigDiff;
+        }
+        shiftDist = softfloat_countLeadingZeros16( sigDiff ) - 5;
+        expZ = expA - shiftDist;
+        if ( expZ < 0 ) {
+            shiftDist = expA;
+            expZ = 0;
+        }
+        sigZ = sigDiff<<shiftDist;
+        goto pack;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        signZ = signF16UI( uiA );
+        if ( expDiff < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            signZ = ! signZ;
+            if ( expB == 0x1F ) {
+                if ( sigB ) goto propagateNaN;
+                uiZ = packToF16UI( signZ, 0x1F, 0 );
+                goto uiZ;
+            }
+            if ( expDiff <= -13 ) {
+                uiZ = packToF16UI( signZ, expB, sigB );
+                if ( expA | sigA ) goto subEpsilon;
+                goto uiZ;
+            }
+            expZ = expA + 19;
+            sigX = sigB | 0x0400;
+            sigY = sigA + (expA ? 0x0400 : sigA);
+            expDiff = -expDiff;
+        } else {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            uiZ = uiA;
+            if ( expA == 0x1F ) {
+                if ( sigA ) goto propagateNaN;
+                goto uiZ;
+            }
+            if ( 13 <= expDiff ) {
+                if ( expB | sigB ) goto subEpsilon;
+                goto uiZ;
+            }
+            expZ = expB + 19;
+            sigX = sigA | 0x0400;
+            sigY = sigB + (expB ? 0x0400 : sigB);
+        }
+        sig32Z = ((uint_fast32_t) sigX<<expDiff) - sigY;
+        shiftDist = softfloat_countLeadingZeros32( sig32Z ) - 1;
+        sig32Z <<= shiftDist;
+        expZ -= shiftDist;
+        sigZ = sig32Z>>16;
+        if ( sig32Z & 0xFFFF ) {
+            sigZ |= 1;
+        } else {
+            if ( ! (sigZ & 0xF) && ((unsigned int) expZ < 0x1E) ) {
+                sigZ >>= 4;
+                goto pack;
+            }
+        }
+        return softfloat_roundPackToF16( signZ, expZ, sigZ );
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ subEpsilon:
+    roundingMode = softfloat_roundingMode;
+    if ( roundingMode != softfloat_round_near_even ) {
+        if (
+            (roundingMode == softfloat_round_minMag)
+                || (roundingMode
+                        == (signF16UI( uiZ ) ? softfloat_round_max
+                                : softfloat_round_min))
+        ) {
+            --uiZ;
+        }
+#ifdef SOFTFLOAT_ROUND_ODD
+        else if ( roundingMode == softfloat_round_odd ) {
+            uiZ = (uiZ - 1) | 1;
+        }
+#endif
+    }
+    softfloat_exceptionFlags |= softfloat_flag_inexact;
+    goto uiZ;
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ pack:
+    uiZ = packToF16UI( signZ, expZ, sigZ );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_subMagsF32.c b/tb/riscv-isa-sim/softfloat/s_subMagsF32.c
new file mode 100644
index 0000000000000000000000000000000000000000..86e89f2ec3a852929a87d2b755257034a5dff648
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_subMagsF32.c
@@ -0,0 +1,143 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB )
+{
+    int_fast16_t expA;
+    uint_fast32_t sigA;
+    int_fast16_t expB;
+    uint_fast32_t sigB;
+    int_fast16_t expDiff;
+    uint_fast32_t uiZ;
+    int_fast32_t sigDiff;
+    bool signZ;
+    int_fast8_t shiftDist;
+    int_fast16_t expZ;
+    uint_fast32_t sigX, sigY;
+    union ui32_f32 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expA = expF32UI( uiA );
+    sigA = fracF32UI( uiA );
+    expB = expF32UI( uiB );
+    sigB = fracF32UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expA == 0xFF ) {
+            if ( sigA | sigB ) goto propagateNaN;
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            uiZ = defaultNaNF32UI;
+            goto uiZ;
+        }
+        sigDiff = sigA - sigB;
+        if ( ! sigDiff ) {
+            uiZ =
+                packToF32UI(
+                    (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+            goto uiZ;
+        }
+        if ( expA ) --expA;
+        signZ = signF32UI( uiA );
+        if ( sigDiff < 0 ) {
+            signZ = ! signZ;
+            sigDiff = -sigDiff;
+        }
+        shiftDist = softfloat_countLeadingZeros32( sigDiff ) - 8;
+        expZ = expA - shiftDist;
+        if ( expZ < 0 ) {
+            shiftDist = expA;
+            expZ = 0;
+        }
+        uiZ = packToF32UI( signZ, expZ, sigDiff<<shiftDist );
+        goto uiZ;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        signZ = signF32UI( uiA );
+        sigA <<= 7;
+        sigB <<= 7;
+        if ( expDiff < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            signZ = ! signZ;
+            if ( expB == 0xFF ) {
+                if ( sigB ) goto propagateNaN;
+                uiZ = packToF32UI( signZ, 0xFF, 0 );
+                goto uiZ;
+            }
+            expZ = expB - 1;
+            sigX = sigB | 0x40000000;
+            sigY = sigA + (expA ? 0x40000000 : sigA);
+            expDiff = -expDiff;
+        } else {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            if ( expA == 0xFF ) {
+                if ( sigA ) goto propagateNaN;
+                uiZ = uiA;
+                goto uiZ;
+            }
+            expZ = expA - 1;
+            sigX = sigA | 0x40000000;
+            sigY = sigB + (expB ? 0x40000000 : sigB);
+        }
+        return
+            softfloat_normRoundPackToF32(
+                signZ, expZ, sigX - softfloat_shiftRightJam32( sigY, expDiff )
+            );
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/s_subMagsF64.c b/tb/riscv-isa-sim/softfloat/s_subMagsF64.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ef9ea446ac8cd84080b1f8d897eb7f905d66ecb
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/s_subMagsF64.c
@@ -0,0 +1,141 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64_t
+ softfloat_subMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ )
+{
+    int_fast16_t expA;
+    uint_fast64_t sigA;
+    int_fast16_t expB;
+    uint_fast64_t sigB;
+    int_fast16_t expDiff;
+    uint_fast64_t uiZ;
+    int_fast64_t sigDiff;
+    int_fast8_t shiftDist;
+    int_fast16_t expZ;
+    uint_fast64_t sigZ;
+    union ui64_f64 uZ;
+
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expA = expF64UI( uiA );
+    sigA = fracF64UI( uiA );
+    expB = expF64UI( uiB );
+    sigB = fracF64UI( uiB );
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+    expDiff = expA - expB;
+    if ( ! expDiff ) {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        if ( expA == 0x7FF ) {
+            if ( sigA | sigB ) goto propagateNaN;
+            softfloat_raiseFlags( softfloat_flag_invalid );
+            uiZ = defaultNaNF64UI;
+            goto uiZ;
+        }
+        sigDiff = sigA - sigB;
+        if ( ! sigDiff ) {
+            uiZ =
+                packToF64UI(
+                    (softfloat_roundingMode == softfloat_round_min), 0, 0 );
+            goto uiZ;
+        }
+        if ( expA ) --expA;
+        if ( sigDiff < 0 ) {
+            signZ = ! signZ;
+            sigDiff = -sigDiff;
+        }
+        shiftDist = softfloat_countLeadingZeros64( sigDiff ) - 11;
+        expZ = expA - shiftDist;
+        if ( expZ < 0 ) {
+            shiftDist = expA;
+            expZ = 0;
+        }
+        uiZ = packToF64UI( signZ, expZ, sigDiff<<shiftDist );
+        goto uiZ;
+    } else {
+        /*--------------------------------------------------------------------
+        *--------------------------------------------------------------------*/
+        sigA <<= 10;
+        sigB <<= 10;
+        if ( expDiff < 0 ) {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            signZ = ! signZ;
+            if ( expB == 0x7FF ) {
+                if ( sigB ) goto propagateNaN;
+                uiZ = packToF64UI( signZ, 0x7FF, 0 );
+                goto uiZ;
+            }
+            sigA += expA ? UINT64_C( 0x4000000000000000 ) : sigA;
+            sigA = softfloat_shiftRightJam64( sigA, -expDiff );
+            sigB |= UINT64_C( 0x4000000000000000 );
+            expZ = expB;
+            sigZ = sigB - sigA;
+        } else {
+            /*----------------------------------------------------------------
+            *----------------------------------------------------------------*/
+            if ( expA == 0x7FF ) {
+                if ( sigA ) goto propagateNaN;
+                uiZ = uiA;
+                goto uiZ;
+            }
+            sigB += expB ? UINT64_C( 0x4000000000000000 ) : sigB;
+            sigB = softfloat_shiftRightJam64( sigB, expDiff );
+            sigA |= UINT64_C( 0x4000000000000000 );
+            expZ = expA;
+            sigZ = sigA - sigB;
+        }
+        return softfloat_normRoundPackToF64( signZ, expZ - 1, sigZ );
+    }
+    /*------------------------------------------------------------------------
+    *------------------------------------------------------------------------*/
+ propagateNaN:
+    uiZ = softfloat_propagateNaNF64UI( uiA, uiB );
+ uiZ:
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/softfloat.ac b/tb/riscv-isa-sim/softfloat/softfloat.ac
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tb/riscv-isa-sim/softfloat/softfloat.h b/tb/riscv-isa-sim/softfloat/softfloat.h
new file mode 100644
index 0000000000000000000000000000000000000000..b277281ec2c80706594e583f5d5f29e9d961e520
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/softfloat.h
@@ -0,0 +1,383 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
+University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+
+/*============================================================================
+| Note:  If SoftFloat is made available as a general library for programs to
+| use, it is strongly recommended that a platform-specific version of this
+| header, "softfloat.h", be created that folds in "softfloat_types.h" and that
+| eliminates all dependencies on compile-time macros.
+*============================================================================*/
+
+
+#ifndef softfloat_h
+#define softfloat_h 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "softfloat_types.h"
+
+#ifndef THREAD_LOCAL
+#define THREAD_LOCAL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------
+| Software floating-point underflow tininess-detection mode.
+*----------------------------------------------------------------------------*/
+extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
+enum {
+    softfloat_tininess_beforeRounding = 0,
+    softfloat_tininess_afterRounding  = 1
+};
+
+/*----------------------------------------------------------------------------
+| Software floating-point rounding mode.  (Mode "odd" is supported only if
+| SoftFloat is compiled with macro 'SOFTFLOAT_ROUND_ODD' defined.)
+*----------------------------------------------------------------------------*/
+extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode;
+enum {
+    softfloat_round_near_even   = 0,
+    softfloat_round_minMag      = 1,
+    softfloat_round_min         = 2,
+    softfloat_round_max         = 3,
+    softfloat_round_near_maxMag = 4,
+    softfloat_round_odd         = 5
+};
+
+/*----------------------------------------------------------------------------
+| Software floating-point exception flags.
+*----------------------------------------------------------------------------*/
+extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags;
+enum {
+    softfloat_flag_inexact   =  1,
+    softfloat_flag_underflow =  2,
+    softfloat_flag_overflow  =  4,
+    softfloat_flag_infinite  =  8,
+    softfloat_flag_invalid   = 16
+};
+
+/*----------------------------------------------------------------------------
+| Routine to raise any or all of the software floating-point exception flags.
+*----------------------------------------------------------------------------*/
+void softfloat_raiseFlags( uint_fast8_t );
+
+/*----------------------------------------------------------------------------
+| Integer-to-floating-point conversion routines.
+*----------------------------------------------------------------------------*/
+float16_t ui32_to_f16( uint32_t );
+float32_t ui32_to_f32( uint32_t );
+float64_t ui32_to_f64( uint32_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t ui32_to_extF80( uint32_t );
+float128_t ui32_to_f128( uint32_t );
+#endif
+void ui32_to_extF80M( uint32_t, extFloat80_t * );
+void ui32_to_f128M( uint32_t, float128_t * );
+float16_t ui64_to_f16( uint64_t );
+float32_t ui64_to_f32( uint64_t );
+float64_t ui64_to_f64( uint64_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t ui64_to_extF80( uint64_t );
+float128_t ui64_to_f128( uint64_t );
+#endif
+void ui64_to_extF80M( uint64_t, extFloat80_t * );
+void ui64_to_f128M( uint64_t, float128_t * );
+float16_t i32_to_f16( int32_t );
+float32_t i32_to_f32( int32_t );
+float64_t i32_to_f64( int32_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t i32_to_extF80( int32_t );
+float128_t i32_to_f128( int32_t );
+#endif
+void i32_to_extF80M( int32_t, extFloat80_t * );
+void i32_to_f128M( int32_t, float128_t * );
+float16_t i64_to_f16( int64_t );
+float32_t i64_to_f32( int64_t );
+float64_t i64_to_f64( int64_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t i64_to_extF80( int64_t );
+float128_t i64_to_f128( int64_t );
+#endif
+void i64_to_extF80M( int64_t, extFloat80_t * );
+void i64_to_f128M( int64_t, float128_t * );
+
+/*----------------------------------------------------------------------------
+| 16-bit (half-precision) floating-point operations.
+*----------------------------------------------------------------------------*/
+uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool );
+uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool );
+int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool );
+int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool );
+uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool );
+uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool );
+int_fast32_t f16_to_i32_r_minMag( float16_t, bool );
+int_fast64_t f16_to_i64_r_minMag( float16_t, bool );
+float32_t f16_to_f32( float16_t );
+float64_t f16_to_f64( float16_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t f16_to_extF80( float16_t );
+float128_t f16_to_f128( float16_t );
+#endif
+void f16_to_extF80M( float16_t, extFloat80_t * );
+void f16_to_f128M( float16_t, float128_t * );
+float16_t f16_roundToInt( float16_t, uint_fast8_t, bool );
+float16_t f16_add( float16_t, float16_t );
+float16_t f16_sub( float16_t, float16_t );
+float16_t f16_mul( float16_t, float16_t );
+float16_t f16_mulAdd( float16_t, float16_t, float16_t );
+float16_t f16_div( float16_t, float16_t );
+float16_t f16_rem( float16_t, float16_t );
+float16_t f16_sqrt( float16_t );
+bool f16_eq( float16_t, float16_t );
+bool f16_le( float16_t, float16_t );
+bool f16_lt( float16_t, float16_t );
+bool f16_eq_signaling( float16_t, float16_t );
+bool f16_le_quiet( float16_t, float16_t );
+bool f16_lt_quiet( float16_t, float16_t );
+bool f16_isSignalingNaN( float16_t );
+
+/*----------------------------------------------------------------------------
+| 32-bit (single-precision) floating-point operations.
+*----------------------------------------------------------------------------*/
+uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool );
+uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool );
+int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool );
+int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool );
+uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool );
+uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool );
+int_fast32_t f32_to_i32_r_minMag( float32_t, bool );
+int_fast64_t f32_to_i64_r_minMag( float32_t, bool );
+float16_t f32_to_f16( float32_t );
+float64_t f32_to_f64( float32_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t f32_to_extF80( float32_t );
+float128_t f32_to_f128( float32_t );
+#endif
+void f32_to_extF80M( float32_t, extFloat80_t * );
+void f32_to_f128M( float32_t, float128_t * );
+float32_t f32_roundToInt( float32_t, uint_fast8_t, bool );
+float32_t f32_add( float32_t, float32_t );
+float32_t f32_sub( float32_t, float32_t );
+float32_t f32_mul( float32_t, float32_t );
+float32_t f32_mulAdd( float32_t, float32_t, float32_t );
+float32_t f32_div( float32_t, float32_t );
+float32_t f32_rem( float32_t, float32_t );
+float32_t f32_sqrt( float32_t );
+bool f32_eq( float32_t, float32_t );
+bool f32_le( float32_t, float32_t );
+bool f32_lt( float32_t, float32_t );
+bool f32_eq_signaling( float32_t, float32_t );
+bool f32_le_quiet( float32_t, float32_t );
+bool f32_lt_quiet( float32_t, float32_t );
+bool f32_isSignalingNaN( float32_t );
+uint_fast16_t f32_classify( float32_t );
+
+/*----------------------------------------------------------------------------
+| 64-bit (double-precision) floating-point operations.
+*----------------------------------------------------------------------------*/
+uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool );
+uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool );
+int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool );
+int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool );
+uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool );
+uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool );
+int_fast32_t f64_to_i32_r_minMag( float64_t, bool );
+int_fast64_t f64_to_i64_r_minMag( float64_t, bool );
+float16_t f64_to_f16( float64_t );
+float32_t f64_to_f32( float64_t );
+#ifdef SOFTFLOAT_FAST_INT64
+extFloat80_t f64_to_extF80( float64_t );
+float128_t f64_to_f128( float64_t );
+#endif
+void f64_to_extF80M( float64_t, extFloat80_t * );
+void f64_to_f128M( float64_t, float128_t * );
+float64_t f64_roundToInt( float64_t, uint_fast8_t, bool );
+float64_t f64_add( float64_t, float64_t );
+float64_t f64_sub( float64_t, float64_t );
+float64_t f64_mul( float64_t, float64_t );
+float64_t f64_mulAdd( float64_t, float64_t, float64_t );
+float64_t f64_div( float64_t, float64_t );
+float64_t f64_rem( float64_t, float64_t );
+float64_t f64_sqrt( float64_t );
+bool f64_eq( float64_t, float64_t );
+bool f64_le( float64_t, float64_t );
+bool f64_lt( float64_t, float64_t );
+bool f64_eq_signaling( float64_t, float64_t );
+bool f64_le_quiet( float64_t, float64_t );
+bool f64_lt_quiet( float64_t, float64_t );
+bool f64_isSignalingNaN( float64_t );
+uint_fast16_t f64_classify( float64_t );
+
+/*----------------------------------------------------------------------------
+| Rounding precision for 80-bit extended double-precision floating-point.
+| Valid values are 32, 64, and 80.
+*----------------------------------------------------------------------------*/
+extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision;
+
+/*----------------------------------------------------------------------------
+| 80-bit extended double-precision floating-point operations.
+*----------------------------------------------------------------------------*/
+#ifdef SOFTFLOAT_FAST_INT64
+uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool );
+uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool );
+int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool );
+int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool );
+uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool );
+uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool );
+int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool );
+int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool );
+float16_t extF80_to_f16( extFloat80_t );
+float32_t extF80_to_f32( extFloat80_t );
+float64_t extF80_to_f64( extFloat80_t );
+float128_t extF80_to_f128( extFloat80_t );
+extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool );
+extFloat80_t extF80_add( extFloat80_t, extFloat80_t );
+extFloat80_t extF80_sub( extFloat80_t, extFloat80_t );
+extFloat80_t extF80_mul( extFloat80_t, extFloat80_t );
+extFloat80_t extF80_div( extFloat80_t, extFloat80_t );
+extFloat80_t extF80_rem( extFloat80_t, extFloat80_t );
+extFloat80_t extF80_sqrt( extFloat80_t );
+bool extF80_eq( extFloat80_t, extFloat80_t );
+bool extF80_le( extFloat80_t, extFloat80_t );
+bool extF80_lt( extFloat80_t, extFloat80_t );
+bool extF80_eq_signaling( extFloat80_t, extFloat80_t );
+bool extF80_le_quiet( extFloat80_t, extFloat80_t );
+bool extF80_lt_quiet( extFloat80_t, extFloat80_t );
+bool extF80_isSignalingNaN( extFloat80_t );
+#endif
+uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool );
+uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool );
+int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool );
+int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool );
+uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool );
+uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool );
+int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool );
+int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool );
+float16_t extF80M_to_f16( const extFloat80_t * );
+float32_t extF80M_to_f32( const extFloat80_t * );
+float64_t extF80M_to_f64( const extFloat80_t * );
+void extF80M_to_f128M( const extFloat80_t *, float128_t * );
+void
+ extF80M_roundToInt(
+     const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * );
+void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
+void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
+void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
+void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
+void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
+void extF80M_sqrt( const extFloat80_t *, extFloat80_t * );
+bool extF80M_eq( const extFloat80_t *, const extFloat80_t * );
+bool extF80M_le( const extFloat80_t *, const extFloat80_t * );
+bool extF80M_lt( const extFloat80_t *, const extFloat80_t * );
+bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * );
+bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * );
+bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * );
+bool extF80M_isSignalingNaN( const extFloat80_t * );
+
+/*----------------------------------------------------------------------------
+| 128-bit (quadruple-precision) floating-point operations.
+*----------------------------------------------------------------------------*/
+#ifdef SOFTFLOAT_FAST_INT64
+uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool );
+uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool );
+int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool );
+int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool );
+uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool );
+uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool );
+int_fast32_t f128_to_i32_r_minMag( float128_t, bool );
+int_fast64_t f128_to_i64_r_minMag( float128_t, bool );
+float16_t f128_to_f16( float128_t );
+float32_t f128_to_f32( float128_t );
+float64_t f128_to_f64( float128_t );
+extFloat80_t f128_to_extF80( float128_t );
+float128_t f128_roundToInt( float128_t, uint_fast8_t, bool );
+float128_t f128_add( float128_t, float128_t );
+float128_t f128_sub( float128_t, float128_t );
+float128_t f128_mul( float128_t, float128_t );
+float128_t f128_mulAdd( float128_t, float128_t, float128_t );
+float128_t f128_div( float128_t, float128_t );
+float128_t f128_rem( float128_t, float128_t );
+float128_t f128_sqrt( float128_t );
+bool f128_eq( float128_t, float128_t );
+bool f128_le( float128_t, float128_t );
+bool f128_lt( float128_t, float128_t );
+bool f128_eq_signaling( float128_t, float128_t );
+bool f128_le_quiet( float128_t, float128_t );
+bool f128_lt_quiet( float128_t, float128_t );
+bool f128_isSignalingNaN( float128_t );
+uint_fast16_t f128_classify( float128_t );
+#endif
+uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool );
+uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool );
+int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool );
+int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool );
+uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool );
+uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool );
+int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool );
+int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool );
+float16_t f128M_to_f16( const float128_t * );
+float32_t f128M_to_f32( const float128_t * );
+float64_t f128M_to_f64( const float128_t * );
+void f128M_to_extF80M( const float128_t *, extFloat80_t * );
+void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * );
+void f128M_add( const float128_t *, const float128_t *, float128_t * );
+void f128M_sub( const float128_t *, const float128_t *, float128_t * );
+void f128M_mul( const float128_t *, const float128_t *, float128_t * );
+void
+ f128M_mulAdd(
+     const float128_t *, const float128_t *, const float128_t *, float128_t *
+ );
+void f128M_div( const float128_t *, const float128_t *, float128_t * );
+void f128M_rem( const float128_t *, const float128_t *, float128_t * );
+void f128M_sqrt( const float128_t *, float128_t * );
+bool f128M_eq( const float128_t *, const float128_t * );
+bool f128M_le( const float128_t *, const float128_t * );
+bool f128M_lt( const float128_t *, const float128_t * );
+bool f128M_eq_signaling( const float128_t *, const float128_t * );
+bool f128M_le_quiet( const float128_t *, const float128_t * );
+bool f128M_lt_quiet( const float128_t *, const float128_t * );
+bool f128M_isSignalingNaN( const float128_t * );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/softfloat.mk.in b/tb/riscv-isa-sim/softfloat/softfloat.mk.in
new file mode 100644
index 0000000000000000000000000000000000000000..ff7637b13e512d2fbea29cff1504aa8c58c99f09
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/softfloat.mk.in
@@ -0,0 +1,230 @@
+softfloat_subproject_deps =
+
+softfloat_hdrs = \
+  internals.h \
+  platform.h \
+  primitives.h \
+  primitiveTypes.h \
+  softfloat.h \
+  softfloat_types.h \
+  specialize.h \
+
+softfloat_c_srcs = \
+	f128_add.c \
+	f128_classify.c \
+	f128_div.c \
+	f128_eq.c \
+	f128_eq_signaling.c \
+	f128_isSignalingNaN.c \
+	f128_le.c \
+	f128_le_quiet.c \
+	f128_lt.c \
+	f128_lt_quiet.c \
+	f128_mulAdd.c \
+	f128_mul.c \
+	f128_rem.c \
+	f128_roundToInt.c \
+	f128_sqrt.c \
+	f128_sub.c \
+	f128_to_f16.c \
+	f128_to_f32.c \
+	f128_to_f64.c \
+	f128_to_i32.c \
+	f128_to_i32_r_minMag.c \
+	f128_to_i64.c \
+	f128_to_i64_r_minMag.c \
+	f128_to_ui32.c \
+	f128_to_ui32_r_minMag.c \
+	f128_to_ui64.c \
+	f128_to_ui64_r_minMag.c \
+	f16_add.c \
+	f16_div.c \
+	f16_eq.c \
+	f16_eq_signaling.c \
+	f16_isSignalingNaN.c \
+	f16_le.c \
+	f16_le_quiet.c \
+	f16_lt.c \
+	f16_lt_quiet.c \
+	f16_mulAdd.c \
+	f16_mul.c \
+	f16_rem.c \
+	f16_roundToInt.c \
+	f16_sqrt.c \
+	f16_sub.c \
+	f16_to_f128.c \
+	f16_to_f32.c \
+	f16_to_f64.c \
+	f16_to_i32.c \
+	f16_to_i32_r_minMag.c \
+	f16_to_i64.c \
+	f16_to_i64_r_minMag.c \
+	f16_to_ui32.c \
+	f16_to_ui32_r_minMag.c \
+	f16_to_ui64.c \
+	f16_to_ui64_r_minMag.c \
+	f32_add.c \
+	f32_classify.c \
+	f32_div.c \
+	f32_eq.c \
+	f32_eq_signaling.c \
+	f32_isSignalingNaN.c \
+	f32_le.c \
+	f32_le_quiet.c \
+	f32_lt.c \
+	f32_lt_quiet.c \
+	f32_mulAdd.c \
+	f32_mul.c \
+	f32_rem.c \
+	f32_roundToInt.c \
+	f32_sqrt.c \
+	f32_sub.c \
+	f32_to_f128.c \
+	f32_to_f16.c \
+	f32_to_f64.c \
+	f32_to_i32.c \
+	f32_to_i32_r_minMag.c \
+	f32_to_i64.c \
+	f32_to_i64_r_minMag.c \
+	f32_to_ui32.c \
+	f32_to_ui32_r_minMag.c \
+	f32_to_ui64.c \
+	f32_to_ui64_r_minMag.c \
+	f64_add.c \
+	f64_classify.c \
+	f64_div.c \
+	f64_eq.c \
+	f64_eq_signaling.c \
+	f64_isSignalingNaN.c \
+	f64_le.c \
+	f64_le_quiet.c \
+	f64_lt.c \
+	f64_lt_quiet.c \
+	f64_mulAdd.c \
+	f64_mul.c \
+	f64_rem.c \
+	f64_roundToInt.c \
+	f64_sqrt.c \
+	f64_sub.c \
+	f64_to_f128.c \
+	f64_to_f16.c \
+	f64_to_f32.c \
+	f64_to_i32.c \
+	f64_to_i32_r_minMag.c \
+	f64_to_i64.c \
+	f64_to_i64_r_minMag.c \
+	f64_to_ui32.c \
+	f64_to_ui32_r_minMag.c \
+	f64_to_ui64.c \
+	f64_to_ui64_r_minMag.c \
+	i32_to_f128.c \
+	i32_to_f16.c \
+	i32_to_f32.c \
+	i32_to_f64.c \
+	i64_to_f128.c \
+	i64_to_f16.c \
+	i64_to_f32.c \
+	i64_to_f64.c \
+	s_add128.c \
+	s_add256M.c \
+	s_addCarryM.c \
+	s_addComplCarryM.c \
+	s_addMagsF128.c \
+	s_addMagsF16.c \
+	s_addMagsF32.c \
+	s_addMagsF64.c \
+	s_addM.c \
+	s_approxRecip_1Ks.c \
+	s_approxRecip32_1.c \
+	s_approxRecipSqrt_1Ks.c \
+	s_approxRecipSqrt32_1.c \
+	s_commonNaNToF32UI.c \
+	s_commonNaNToF64UI.c \
+	s_compare128M.c \
+	s_compare96M.c \
+	s_countLeadingZeros16.c \
+	s_countLeadingZeros32.c \
+	s_countLeadingZeros64.c \
+	s_countLeadingZeros8.c \
+	s_eq128.c \
+	s_f32UIToCommonNaN.c \
+	s_f64UIToCommonNaN.c \
+	s_le128.c \
+	s_lt128.c \
+	s_mul128By32.c \
+	s_mul128MTo256M.c \
+	s_mul128To256M.c \
+	s_mul64ByShifted32To128.c \
+	s_mul64To128.c \
+	s_mul64To128M.c \
+	s_mulAddF128.c \
+	s_mulAddF16.c \
+	s_mulAddF32.c \
+	s_mulAddF64.c \
+	s_negXM.c \
+	s_normRoundPackToF128.c \
+	s_normRoundPackToF16.c \
+	s_normRoundPackToF32.c \
+	s_normRoundPackToF64.c \
+	s_normSubnormalF128Sig.c \
+	s_normSubnormalF16Sig.c \
+	s_normSubnormalF32Sig.c \
+	s_normSubnormalF64Sig.c \
+	softfloat_raiseFlags.c \
+	softfloat_state.c \
+	s_propagateNaNF16UI.c \
+	s_propagateNaNF32UI.c \
+	s_propagateNaNF64UI.c \
+	s_propagateNaNF128UI.c \
+	s_remStepMBy32.c \
+	s_roundMToI64.c \
+	s_roundMToUI64.c \
+	s_roundPackMToI64.c \
+	s_roundPackMToUI64.c \
+	s_roundPackToF128.c \
+	s_roundPackToF16.c \
+	s_roundPackToF32.c \
+	s_roundPackToF64.c \
+	s_roundPackToI32.c \
+	s_roundPackToI64.c \
+	s_roundPackToUI32.c \
+	s_roundPackToUI64.c \
+	s_roundToI32.c \
+	s_roundToI64.c \
+	s_roundToUI32.c \
+	s_roundToUI64.c \
+	s_shiftRightJam128.c \
+	s_shiftRightJam128Extra.c \
+	s_shiftRightJam256M.c \
+	s_shiftRightJam32.c \
+	s_shiftRightJam64.c \
+	s_shiftRightJam64Extra.c \
+	s_shortShiftLeft128.c \
+	s_shortShiftLeft64To96M.c \
+	s_shortShiftRight128.c \
+	s_shortShiftRightExtendM.c \
+	s_shortShiftRightJam128.c \
+	s_shortShiftRightJam128Extra.c \
+	s_shortShiftRightJam64.c \
+	s_shortShiftRightJam64Extra.c \
+	s_shortShiftRightM.c \
+	s_sub128.c \
+	s_sub1XM.c \
+	s_sub256M.c \
+	s_subMagsF128.c \
+	s_subMagsF16.c \
+	s_subMagsF32.c \
+	s_subMagsF64.c \
+	s_subM.c \
+	ui32_to_f128.c \
+	ui32_to_f16.c \
+	ui32_to_f32.c \
+	ui32_to_f64.c \
+	ui64_to_f128.c \
+	ui64_to_f16.c \
+	ui64_to_f32.c \
+	ui64_to_f64.c \
+
+softfloat_test_srcs =
+
+softfloat_install_prog_srcs =
diff --git a/tb/riscv-isa-sim/softfloat/softfloat_raiseFlags.c b/tb/riscv-isa-sim/softfloat/softfloat_raiseFlags.c
new file mode 100644
index 0000000000000000000000000000000000000000..f2c25adeeaffa83a23b9dd93fe2a01f4bf1c4764
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/softfloat_raiseFlags.c
@@ -0,0 +1,52 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include "platform.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Raises the exceptions specified by `flags'.  Floating-point traps can be
+| defined here if desired.  It is currently not possible for such a trap
+| to substitute a result value.  If traps are not implemented, this routine
+| should be simply `softfloat_exceptionFlags |= flags;'.
+*----------------------------------------------------------------------------*/
+void softfloat_raiseFlags( uint_fast8_t flags )
+{
+
+    softfloat_exceptionFlags |= flags;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/softfloat_state.c b/tb/riscv-isa-sim/softfloat/softfloat_state.c
new file mode 100644
index 0000000000000000000000000000000000000000..a105e6f6473989f8bdc9207199b07953f3f586b9
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/softfloat_state.c
@@ -0,0 +1,52 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+#ifndef THREAD_LOCAL
+#define THREAD_LOCAL
+#endif
+
+THREAD_LOCAL uint_fast8_t softfloat_roundingMode = softfloat_round_near_even;
+THREAD_LOCAL uint_fast8_t softfloat_detectTininess = init_detectTininess;
+THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags = 0;
+
+THREAD_LOCAL uint_fast8_t extF80_roundingPrecision = 80;
+
diff --git a/tb/riscv-isa-sim/softfloat/softfloat_types.h b/tb/riscv-isa-sim/softfloat/softfloat_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..af1888f9b9f593d8bff47817d1e9b6a64fa02ebd
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/softfloat_types.h
@@ -0,0 +1,81 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#ifndef softfloat_types_h
+#define softfloat_types_h 1
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+| Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point
+| arguments and results to/from functions.  These types must be exactly
+| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively.  Where a
+| platform has "native" support for IEEE-Standard floating-point formats,
+| the types below may, if desired, be defined as aliases for the native types
+| (typically 'float' and 'double', and possibly 'long double').
+*----------------------------------------------------------------------------*/
+typedef struct { uint16_t v; } float16_t;
+typedef struct { uint32_t v; } float32_t;
+typedef struct { uint64_t v; } float64_t;
+typedef struct { uint64_t v[2]; } float128_t;
+
+/*----------------------------------------------------------------------------
+| The format of an 80-bit extended floating-point number in memory.  This
+| structure must contain a 16-bit field named 'signExp' and a 64-bit field
+| named 'signif'.
+*----------------------------------------------------------------------------*/
+#ifdef LITTLEENDIAN
+struct extFloat80M { uint64_t signif; uint16_t signExp; };
+#else
+struct extFloat80M { uint16_t signExp; uint64_t signif; };
+#endif
+
+/*----------------------------------------------------------------------------
+| The type used to pass 80-bit extended floating-point arguments and
+| results to/from functions.  This type must have size identical to
+| 'struct extFloat80M'.  Type 'extFloat80_t' can be defined as an alias for
+| 'struct extFloat80M'.  Alternatively, if a platform has "native" support
+| for IEEE-Standard 80-bit extended floating-point, it may be possible,
+| if desired, to define 'extFloat80_t' as an alias for the native type
+| (presumably either 'long double' or a nonstandard compiler-intrinsic type).
+| In that case, the 'signif' and 'signExp' fields of 'struct extFloat80M'
+| must align exactly with the locations in memory of the sign, exponent, and
+| significand of the native type.
+*----------------------------------------------------------------------------*/
+typedef struct extFloat80M extFloat80_t;
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/specialize.h b/tb/riscv-isa-sim/softfloat/specialize.h
new file mode 100644
index 0000000000000000000000000000000000000000..629d5185b9224601716eee66c03b1cfe72e57958
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/specialize.h
@@ -0,0 +1,415 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#ifndef specialize_h
+#define specialize_h 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "primitiveTypes.h"
+#include "softfloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------
+| Default value for `softfloat_detectTininess'.
+*----------------------------------------------------------------------------*/
+#define init_detectTininess softfloat_tininess_afterRounding
+
+/*----------------------------------------------------------------------------
+| The values to return on conversions to 32-bit integer formats that raise an
+| invalid exception.
+*----------------------------------------------------------------------------*/
+#define ui32_fromPosOverflow 0xFFFFFFFF
+#define ui32_fromNegOverflow 0
+#define ui32_fromNaN         0xFFFFFFFF
+#define i32_fromPosOverflow  0x7FFFFFFF
+#define i32_fromNegOverflow  (-0x7FFFFFFF - 1)
+#define i32_fromNaN          0x7FFFFFFF
+
+/*----------------------------------------------------------------------------
+| The values to return on conversions to 64-bit integer formats that raise an
+| invalid exception.
+*----------------------------------------------------------------------------*/
+#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
+#define ui64_fromNegOverflow 0
+#define ui64_fromNaN         UINT64_C( 0xFFFFFFFFFFFFFFFF )
+#define i64_fromPosOverflow  UINT64_C( 0x7FFFFFFFFFFFFFFF )
+#define i64_fromNegOverflow  (-UINT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
+#define i64_fromNaN          UINT64_C( 0x7FFFFFFFFFFFFFFF )
+
+/*----------------------------------------------------------------------------
+| "Common NaN" structure, used to transfer NaN representations from one format
+| to another.
+*----------------------------------------------------------------------------*/
+struct commonNaN { char _unused; };
+
+/*----------------------------------------------------------------------------
+| The bit pattern for a default generated 16-bit floating-point NaN.
+*----------------------------------------------------------------------------*/
+#define defaultNaNF16UI 0x7E00
+
+/*----------------------------------------------------------------------------
+| Returns true when 16-bit unsigned integer `uiA' has the bit pattern of a
+| 16-bit floating-point signaling NaN.
+| Note:  This macro evaluates its argument more than once.
+*----------------------------------------------------------------------------*/
+#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
+
+/*----------------------------------------------------------------------------
+| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts
+| this NaN to the common NaN form, and stores the resulting common NaN at the
+| location pointed to by `zPtr'.  If the NaN is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point
+| NaN, and returns the bit pattern of this value as an unsigned integer.
+*----------------------------------------------------------------------------*/
+#define softfloat_commonNaNToF16UI( aPtr ) ((uint_fast16_t) defaultNaNF16UI)
+
+/*----------------------------------------------------------------------------
+| Interpreting `uiA' and `uiB' as the bit patterns of two 16-bit floating-
+| point values, at least one of which is a NaN, returns the bit pattern of
+| the combined NaN result.  If either `uiA' or `uiB' has the pattern of a
+| signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+uint_fast16_t
+ softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
+
+/*----------------------------------------------------------------------------
+| The bit pattern for a default generated 32-bit floating-point NaN.
+*----------------------------------------------------------------------------*/
+#define defaultNaNF32UI 0x7FC00000
+
+/*----------------------------------------------------------------------------
+| Returns true when 32-bit unsigned integer `uiA' has the bit pattern of a
+| 32-bit floating-point signaling NaN.
+| Note:  This macro evaluates its argument more than once.
+*----------------------------------------------------------------------------*/
+#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
+
+/*----------------------------------------------------------------------------
+| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts
+| this NaN to the common NaN form, and stores the resulting common NaN at the
+| location pointed to by `zPtr'.  If the NaN is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point
+| NaN, and returns the bit pattern of this value as an unsigned integer.
+*----------------------------------------------------------------------------*/
+#define softfloat_commonNaNToF32UI( aPtr ) ((uint_fast32_t) defaultNaNF32UI)
+
+/*----------------------------------------------------------------------------
+| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating-
+| point values, at least one of which is a NaN, returns the bit pattern of
+| the combined NaN result.  If either `uiA' or `uiB' has the pattern of a
+| signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+uint_fast32_t
+ softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
+
+/*----------------------------------------------------------------------------
+| The bit pattern for a default generated 64-bit floating-point NaN.
+*----------------------------------------------------------------------------*/
+#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
+
+/*----------------------------------------------------------------------------
+| Returns true when 64-bit unsigned integer `uiA' has the bit pattern of a
+| 64-bit floating-point signaling NaN.
+| Note:  This macro evaluates its argument more than once.
+*----------------------------------------------------------------------------*/
+#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
+
+/*----------------------------------------------------------------------------
+| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts
+| this NaN to the common NaN form, and stores the resulting common NaN at the
+| location pointed to by `zPtr'.  If the NaN is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point
+| NaN, and returns the bit pattern of this value as an unsigned integer.
+*----------------------------------------------------------------------------*/
+#define softfloat_commonNaNToF64UI( aPtr ) ((uint_fast64_t) defaultNaNF64UI)
+
+/*----------------------------------------------------------------------------
+| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating-
+| point values, at least one of which is a NaN, returns the bit pattern of
+| the combined NaN result.  If either `uiA' or `uiB' has the pattern of a
+| signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+uint_fast64_t
+ softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
+
+/*----------------------------------------------------------------------------
+| The bit pattern for a default generated 80-bit extended floating-point NaN.
+*----------------------------------------------------------------------------*/
+#define defaultNaNExtF80UI64 0x7FFF
+#define defaultNaNExtF80UI0  UINT64_C( 0xC000000000000000 )
+
+/*----------------------------------------------------------------------------
+| Returns true when the 80-bit unsigned integer formed from concatenating
+| 16-bit `uiA64' and 64-bit `uiA0' has the bit pattern of an 80-bit extended
+| floating-point signaling NaN.
+| Note:  This macro evaluates its arguments more than once.
+*----------------------------------------------------------------------------*/
+#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
+
+#ifdef SOFTFLOAT_FAST_INT64
+
+/*----------------------------------------------------------------------------
+| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is
+| defined.
+*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
+| has the bit pattern of an 80-bit extended floating-point NaN, converts
+| this NaN to the common NaN form, and stores the resulting common NaN at the
+| location pointed to by `zPtr'.  If the NaN is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into an 80-bit extended
+| floating-point NaN, and returns the bit pattern of this value as an unsigned
+| integer.
+*----------------------------------------------------------------------------*/
+#if defined INLINE && ! defined softfloat_commonNaNToExtF80UI
+INLINE
+struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
+{
+    struct uint128 uiZ;
+    uiZ.v64 = defaultNaNExtF80UI64;
+    uiZ.v0  = defaultNaNExtF80UI0;
+    return uiZ;
+}
+#else
+struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
+#endif
+
+/*----------------------------------------------------------------------------
+| Interpreting the unsigned integer formed from concatenating `uiA64' and
+| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting
+| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another
+| 80-bit extended floating-point value, and assuming at least on of these
+| floating-point values is a NaN, returns the bit pattern of the combined NaN
+| result.  If either original floating-point value is a signaling NaN, the
+| invalid exception is raised.
+*----------------------------------------------------------------------------*/
+struct uint128
+ softfloat_propagateNaNExtF80UI(
+     uint_fast16_t uiA64,
+     uint_fast64_t uiA0,
+     uint_fast16_t uiB64,
+     uint_fast64_t uiB0
+ );
+
+/*----------------------------------------------------------------------------
+| The bit pattern for a default generated 128-bit floating-point NaN.
+*----------------------------------------------------------------------------*/
+#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 )
+#define defaultNaNF128UI0  UINT64_C( 0 )
+
+/*----------------------------------------------------------------------------
+| Returns true when the 128-bit unsigned integer formed from concatenating
+| 64-bit `uiA64' and 64-bit `uiA0' has the bit pattern of a 128-bit floating-
+| point signaling NaN.
+| Note:  This macro evaluates its arguments more than once.
+*----------------------------------------------------------------------------*/
+#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
+
+/*----------------------------------------------------------------------------
+| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
+| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
+| the common NaN form, and stores the resulting common NaN at the location
+| pointed to by `zPtr'.  If the NaN is a signaling NaN, the invalid exception
+| is raised.
+*----------------------------------------------------------------------------*/
+#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
+| NaN, and returns the bit pattern of this value as an unsigned integer.
+*----------------------------------------------------------------------------*/
+#if defined INLINE && ! defined softfloat_commonNaNToF128UI
+INLINE
+struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
+{
+    struct uint128 uiZ;
+    uiZ.v64 = defaultNaNF128UI64;
+    uiZ.v0  = defaultNaNF128UI0;
+    return uiZ;
+}
+#else
+struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
+#endif
+
+/*----------------------------------------------------------------------------
+| Interpreting the unsigned integer formed from concatenating `uiA64' and
+| `uiA0' as a 128-bit floating-point value, and likewise interpreting the
+| unsigned integer formed from concatenating `uiB64' and `uiB0' as another
+| 128-bit floating-point value, and assuming at least on of these floating-
+| point values is a NaN, returns the bit pattern of the combined NaN result.
+| If either original floating-point value is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+struct uint128
+ softfloat_propagateNaNF128UI(
+     uint_fast64_t uiA64,
+     uint_fast64_t uiA0,
+     uint_fast64_t uiB64,
+     uint_fast64_t uiB0
+ );
+
+#else
+
+/*----------------------------------------------------------------------------
+| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not
+| defined.
+*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is
+| a NaN, converts this NaN to the common NaN form, and stores the resulting
+| common NaN at the location pointed to by `zPtr'.  If the NaN is a signaling
+| NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into an 80-bit extended
+| floating-point NaN, and stores this NaN at the location pointed to by
+| `zSPtr'.
+*----------------------------------------------------------------------------*/
+#if defined INLINE && ! defined softfloat_commonNaNToExtF80M
+INLINE
+void
+ softfloat_commonNaNToExtF80M(
+     const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
+{
+    zSPtr->signExp = defaultNaNExtF80UI64;
+    zSPtr->signif  = defaultNaNExtF80UI0;
+}
+#else
+void
+ softfloat_commonNaNToExtF80M(
+     const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
+#endif
+
+/*----------------------------------------------------------------------------
+| Assuming at least one of the two 80-bit extended floating-point values
+| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result
+| at the location pointed to by `zSPtr'.  If either original floating-point
+| value is a signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_propagateNaNExtF80M(
+     const struct extFloat80M *aSPtr,
+     const struct extFloat80M *bSPtr,
+     struct extFloat80M *zSPtr
+ );
+
+/*----------------------------------------------------------------------------
+| The bit pattern for a default generated 128-bit floating-point NaN.
+*----------------------------------------------------------------------------*/
+#define defaultNaNF128UI96 0x7FFF8000
+#define defaultNaNF128UI64 0
+#define defaultNaNF128UI32 0
+#define defaultNaNF128UI0  0
+
+/*----------------------------------------------------------------------------
+| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN,
+| converts this NaN to the common NaN form, and stores the resulting common
+| NaN at the location pointed to by `zPtr'.  If the NaN is a signaling NaN,
+| the invalid exception is raised.  Argument `aWPtr' points to an array of
+| four 32-bit elements that concatenate in the platform's normal endian order
+| to form a 128-bit floating-point value.
+*----------------------------------------------------------------------------*/
+#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
+
+/*----------------------------------------------------------------------------
+| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point
+| NaN, and stores this NaN at the location pointed to by `zWPtr'.  Argument
+| `zWPtr' points to an array of four 32-bit elements that concatenate in the
+| platform's normal endian order to form a 128-bit floating-point value.
+*----------------------------------------------------------------------------*/
+#if defined INLINE && ! defined softfloat_commonNaNToF128M
+INLINE
+void
+ softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
+{
+    zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
+    zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
+    zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
+    zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
+}
+#else
+void
+ softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
+#endif
+
+/*----------------------------------------------------------------------------
+| Assuming at least one of the two 128-bit floating-point values pointed to by
+| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location
+| pointed to by `zWPtr'.  If either original floating-point value is a
+| signaling NaN, the invalid exception is raised.  Each of `aWPtr', `bWPtr',
+| and `zWPtr' points to an array of four 32-bit elements that concatenate in
+| the platform's normal endian order to form a 128-bit floating-point value.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_propagateNaNF128M(
+     const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tb/riscv-isa-sim/softfloat/ui32_to_f128.c b/tb/riscv-isa-sim/softfloat/ui32_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..78d3eb64c6b3ea15c02224ff61763eb1f349d176
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui32_to_f128.c
@@ -0,0 +1,60 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t ui32_to_f128( uint32_t a )
+{
+    uint_fast64_t uiZ64;
+    int_fast8_t shiftDist;
+    union ui128_f128 uZ;
+
+    uiZ64 = 0;
+    if ( a ) {
+        shiftDist = softfloat_countLeadingZeros32( a ) + 17;
+        uiZ64 =
+            packToF128UI64(
+                0, 0x402E - shiftDist, (uint_fast64_t) a<<shiftDist );
+    }
+    uZ.ui.v64 = uiZ64;
+    uZ.ui.v0  = 0;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui32_to_f16.c b/tb/riscv-isa-sim/softfloat/ui32_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..09dcc8c3fa49e8d17d86e61b4391d9171f3b3061
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui32_to_f16.c
@@ -0,0 +1,65 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t ui32_to_f16( uint32_t a )
+{
+    int_fast8_t shiftDist;
+    union ui16_f16 u;
+    uint_fast16_t sig;
+
+    shiftDist = softfloat_countLeadingZeros32( a ) - 21;
+    if ( 0 <= shiftDist ) {
+        u.ui =
+            a ? packToF16UI(
+                    0, 0x18 - shiftDist, (uint_fast16_t) a<<shiftDist )
+                : 0;
+        return u.f;
+    } else {
+        shiftDist += 4;
+        sig =
+            (shiftDist < 0)
+                ? a>>(-shiftDist) | ((uint32_t) (a<<(shiftDist & 31)) != 0)
+                : (uint_fast16_t) a<<shiftDist;
+        return softfloat_roundPackToF16( 0, 0x1C - shiftDist, sig );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui32_to_f32.c b/tb/riscv-isa-sim/softfloat/ui32_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e5ece68aec50535dd882a9706adf8c387fbfc16
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui32_to_f32.c
@@ -0,0 +1,57 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t ui32_to_f32( uint32_t a )
+{
+    union ui32_f32 uZ;
+
+    if ( ! a ) {
+        uZ.ui = 0;
+        return uZ.f;
+    }
+    if ( a & 0x80000000 ) {
+        return softfloat_roundPackToF32( 0, 0x9D, a>>1 | (a & 1) );
+    } else {
+        return softfloat_normRoundPackToF32( 0, 0x9C, a );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui32_to_f64.c b/tb/riscv-isa-sim/softfloat/ui32_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..5e5f843aff74441834aee1f10955bc7b40343476
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui32_to_f64.c
@@ -0,0 +1,59 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t ui32_to_f64( uint32_t a )
+{
+    uint_fast64_t uiZ;
+    int_fast8_t shiftDist;
+    union ui64_f64 uZ;
+
+    if ( ! a ) {
+        uiZ = 0;
+    } else {
+        shiftDist = softfloat_countLeadingZeros32( a ) + 21;
+        uiZ =
+            packToF64UI( 0, 0x432 - shiftDist, (uint_fast64_t) a<<shiftDist );
+    }
+    uZ.ui = uiZ;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui64_to_f128.c b/tb/riscv-isa-sim/softfloat/ui64_to_f128.c
new file mode 100644
index 0000000000000000000000000000000000000000..0124bc5a60571798a05ffdcc438cfaaa893d3122
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui64_to_f128.c
@@ -0,0 +1,68 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float128_t ui64_to_f128( uint64_t a )
+{
+    uint_fast64_t uiZ64, uiZ0;
+    int_fast8_t shiftDist;
+    struct uint128 zSig;
+    union ui128_f128 uZ;
+
+    if ( ! a ) {
+        uiZ64 = 0;
+        uiZ0  = 0;
+    } else {
+        shiftDist = softfloat_countLeadingZeros64( a ) + 49;
+        if ( 64 <= shiftDist ) {
+            zSig.v64 = a<<(shiftDist - 64);
+            zSig.v0  = 0;
+        } else {
+            zSig = softfloat_shortShiftLeft128( 0, a, shiftDist );
+        }
+        uiZ64 = packToF128UI64( 0, 0x406E - shiftDist, zSig.v64 );
+        uiZ0  = zSig.v0;
+    }
+    uZ.ui.v64 = uiZ64;
+    uZ.ui.v0  = uiZ0;
+    return uZ.f;
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui64_to_f16.c b/tb/riscv-isa-sim/softfloat/ui64_to_f16.c
new file mode 100644
index 0000000000000000000000000000000000000000..ecca02bc454ce176f494e57aafc97fcaccf870c0
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui64_to_f16.c
@@ -0,0 +1,64 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float16_t ui64_to_f16( uint64_t a )
+{
+    int_fast8_t shiftDist;
+    union ui16_f16 u;
+    uint_fast16_t sig;
+
+    shiftDist = softfloat_countLeadingZeros64( a ) - 53;
+    if ( 0 <= shiftDist ) {
+        u.ui =
+            a ? packToF16UI(
+                    0, 0x18 - shiftDist, (uint_fast16_t) a<<shiftDist )
+                : 0;
+        return u.f;
+    } else {
+        shiftDist += 4;
+        sig =
+            (shiftDist < 0) ? softfloat_shortShiftRightJam64( a, -shiftDist )
+                : (uint_fast16_t) a<<shiftDist;
+        return softfloat_roundPackToF16( 0, 0x1C - shiftDist, sig );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui64_to_f32.c b/tb/riscv-isa-sim/softfloat/ui64_to_f32.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d946c2fe4fa3c0ff3a372b8f15d26223a15cf1b
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui64_to_f32.c
@@ -0,0 +1,64 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
+California.  All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float32_t ui64_to_f32( uint64_t a )
+{
+    int_fast8_t shiftDist;
+    union ui32_f32 u;
+    uint_fast32_t sig;
+
+    shiftDist = softfloat_countLeadingZeros64( a ) - 40;
+    if ( 0 <= shiftDist ) {
+        u.ui =
+            a ? packToF32UI(
+                    0, 0x95 - shiftDist, (uint_fast32_t) a<<shiftDist )
+                : 0;
+        return u.f;
+    } else {
+        shiftDist += 7;
+        sig =
+            (shiftDist < 0) ? softfloat_shortShiftRightJam64( a, -shiftDist )
+                : (uint_fast32_t) a<<shiftDist;
+        return softfloat_roundPackToF32( 0, 0x9C - shiftDist, sig );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/softfloat/ui64_to_f64.c b/tb/riscv-isa-sim/softfloat/ui64_to_f64.c
new file mode 100644
index 0000000000000000000000000000000000000000..57102a74b6782f86d09f2c6a218d3e7901ccd549
--- /dev/null
+++ b/tb/riscv-isa-sim/softfloat/ui64_to_f64.c
@@ -0,0 +1,59 @@
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3d, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+    this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions, and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ 3. Neither the name of the University nor the names of its contributors may
+    be used to endorse or promote products derived from this software without
+    specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
+DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=============================================================================*/
+
+#include <stdint.h>
+#include "platform.h"
+#include "internals.h"
+#include "softfloat.h"
+
+float64_t ui64_to_f64( uint64_t a )
+{
+    union ui64_f64 uZ;
+
+    if ( ! a ) {
+        uZ.ui = 0;
+        return uZ.f;
+    }
+    if ( a & UINT64_C( 0x8000000000000000 ) ) {
+        return
+            softfloat_roundPackToF64(
+                0, 0x43D, softfloat_shortShiftRightJam64( a, 1 ) );
+    } else {
+        return softfloat_normRoundPackToF64( 0, 0x43C, a );
+    }
+
+}
+
diff --git a/tb/riscv-isa-sim/spike_main/disasm.cc b/tb/riscv-isa-sim/spike_main/disasm.cc
new file mode 100644
index 0000000000000000000000000000000000000000..81264dd802ec6896f8b3bc69b561775fe4ae0a65
--- /dev/null
+++ b/tb/riscv-isa-sim/spike_main/disasm.cc
@@ -0,0 +1,648 @@
+// See LICENSE for license details.
+
+#include "disasm.h"
+#include <string>
+#include <vector>
+#include <cstdarg>
+#include <sstream>
+#include <stdlib.h>
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.i_imm()) + '(' + xpr_name[insn.rs1()] + ')';
+  }
+} load_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.s_imm()) + '(' + xpr_name[insn.rs1()] + ')';
+  }
+} store_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::string("(") + xpr_name[insn.rs1()] + ')';
+  }
+} amo_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rd()];
+  }
+} xrd;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rs1()];
+  }
+} xrs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rs2()];
+  }
+} xrs2;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr_name[insn.rd()];
+  }
+} frd;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr_name[insn.rs1()];
+  }
+} frs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr_name[insn.rs2()];
+  }
+} frs2;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr_name[insn.rs3()];
+  }
+} frs3;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    switch (insn.csr())
+    {
+      #define DECLARE_CSR(name, num) case num: return #name;
+      #include "encoding.h"
+      #undef DECLARE_CSR
+      default:
+      {
+        char buf[16];
+        snprintf(buf, sizeof buf, "unknown_%03" PRIx64, insn.csr());
+        return std::string(buf);
+      }
+    }
+  }
+} csr;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.i_imm());
+  }
+} imm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.shamt());
+  }
+} shamt;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    std::stringstream s;
+    s << std::hex << "0x" << ((uint32_t)insn.u_imm() >> 12);
+    return s.str();
+  }
+} bigimm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string(insn.rs1());
+  }
+} zimm5;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    std::stringstream s;
+    int32_t target = insn.sb_imm();
+    char sign = target >= 0 ? '+' : '-';
+    s << "pc " << sign << ' ' << abs(target);
+    return s.str();
+  }
+} branch_target;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    std::stringstream s;
+    int32_t target = insn.uj_imm();
+    char sign = target >= 0 ? '+' : '-';
+    s << "pc " << sign << std::hex << " 0x" << abs(target);
+    return s.str();
+  }
+} jump_target;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rvc_rs1()];
+  }
+} rvc_rs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rvc_rs2()];
+  }
+} rvc_rs2;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr_name[insn.rvc_rs2()];
+  }
+} rvc_fp_rs2;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rvc_rs1s()];
+  }
+} rvc_rs1s;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[insn.rvc_rs2s()];
+  }
+} rvc_rs2s;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr_name[insn.rvc_rs2s()];
+  }
+} rvc_fp_rs2s;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr_name[X_SP];
+  }
+} rvc_sp;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_imm());
+  }
+} rvc_imm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_addi4spn_imm());
+  }
+} rvc_addi4spn_imm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_addi16sp_imm());
+  }
+} rvc_addi16sp_imm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_lwsp_imm());
+  }
+} rvc_lwsp_imm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)(insn.rvc_imm() & 0x3f));
+  }
+} rvc_shamt;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    std::stringstream s;
+    s << std::hex << "0x" << ((uint32_t)insn.rvc_imm() << 12 >> 12);
+    return s.str();
+  }
+} rvc_uimm;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_lwsp_imm()) + '(' + xpr_name[X_SP] + ')';
+  }
+} rvc_lwsp_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_ldsp_imm()) + '(' + xpr_name[X_SP] + ')';
+  }
+} rvc_ldsp_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_swsp_imm()) + '(' + xpr_name[X_SP] + ')';
+  }
+} rvc_swsp_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_sdsp_imm()) + '(' + xpr_name[X_SP] + ')';
+  }
+} rvc_sdsp_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_lw_imm()) + '(' + xpr_name[insn.rvc_rs1s()] + ')';
+  }
+} rvc_lw_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.rvc_ld_imm()) + '(' + xpr_name[insn.rvc_rs1s()] + ')';
+  }
+} rvc_ld_address;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    std::stringstream s;
+    int32_t target = insn.rvc_b_imm();
+    char sign = target >= 0 ? '+' : '-';
+    s << "pc " << sign << ' ' << abs(target);
+    return s.str();
+  }
+} rvc_branch_target;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    std::stringstream s;
+    int32_t target = insn.rvc_j_imm();
+    char sign = target >= 0 ? '+' : '-';
+    s << "pc " << sign << ' ' << abs(target);
+    return s.str();
+  }
+} rvc_jump_target;
+
+std::string disassembler_t::disassemble(insn_t insn) const
+{
+  const disasm_insn_t* disasm_insn = lookup(insn);
+  return disasm_insn ? disasm_insn->to_string(insn) : "unknown";
+}
+
+disassembler_t::disassembler_t(int xlen)
+{
+  const uint32_t mask_rd = 0x1fUL << 7;
+  const uint32_t match_rd_ra = 1UL << 7;
+  const uint32_t mask_rs1 = 0x1fUL << 15;
+  const uint32_t match_rs1_ra = 1UL << 15;
+  const uint32_t mask_rs2 = 0x1fUL << 20;
+  const uint32_t mask_imm = 0xfffUL << 20;
+  const uint32_t match_imm_1 = 1UL << 20;
+  const uint32_t mask_rvc_rs2 = 0x1fUL << 2;
+  const uint32_t mask_rvc_imm = mask_rvc_rs2 | 0x1000UL;
+
+  #define DECLARE_INSN(code, match, mask) \
+   const uint32_t match_##code = match; \
+   const uint32_t mask_##code = mask;
+  #include "encoding.h"
+  #undef DECLARE_INSN
+
+  // explicit per-instruction disassembly
+  #define DISASM_INSN(name, code, extra, ...) \
+    add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
+  #define DEFINE_NOARG(code) \
+    add_insn(new disasm_insn_t(#code, match_##code, mask_##code, {}));
+  #define DEFINE_RTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &xrs2})
+  #define DEFINE_ITYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &imm})
+  #define DEFINE_ITYPE_SHIFT(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &shamt})
+  #define DEFINE_I0TYPE(name, code) DISASM_INSN(name, code, mask_rs1, {&xrd, &imm})
+  #define DEFINE_I1TYPE(name, code) DISASM_INSN(name, code, mask_imm, {&xrd, &xrs1})
+  #define DEFINE_I2TYPE(name, code) DISASM_INSN(name, code, mask_rd | mask_imm, {&xrs1})
+  #define DEFINE_LTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &bigimm})
+  #define DEFINE_BTYPE(code) DISASM_INSN(#code, code, 0, {&xrs1, &xrs2, &branch_target})
+  #define DEFINE_B0TYPE(name, code) DISASM_INSN(name, code, mask_rs1 | mask_rs2, {&branch_target})
+  #define DEFINE_B1TYPE(name, code) DISASM_INSN(name, code, mask_rs2, {&xrs1, &branch_target})
+  #define DEFINE_XLOAD(code) DISASM_INSN(#code, code, 0, {&xrd, &load_address})
+  #define DEFINE_XSTORE(code) DISASM_INSN(#code, code, 0, {&xrs2, &store_address})
+  #define DEFINE_XAMO(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs2, &amo_address})
+  #define DEFINE_XAMO_LR(code) DISASM_INSN(#code, code, 0, {&xrd, &amo_address})
+  #define DEFINE_FLOAD(code) DISASM_INSN(#code, code, 0, {&frd, &load_address})
+  #define DEFINE_FSTORE(code) DISASM_INSN(#code, code, 0, {&frs2, &store_address})
+  #define DEFINE_FRTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2})
+  #define DEFINE_FR1TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1})
+  #define DEFINE_FR3TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2, &frs3})
+  #define DEFINE_FXTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &frs1})
+  #define DEFINE_FX2TYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &frs1, &frs2})
+  #define DEFINE_XFTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &xrs1})
+  #define DEFINE_SFENCE_TYPE(code) DISASM_INSN(#code, code, 0, {&xrs1, &xrs2})
+
+  DEFINE_XLOAD(lb)
+  DEFINE_XLOAD(lbu)
+  DEFINE_XLOAD(lh)
+  DEFINE_XLOAD(lhu)
+  DEFINE_XLOAD(lw)
+  DEFINE_XLOAD(lwu)
+  DEFINE_XLOAD(ld)
+
+  DEFINE_XSTORE(sb)
+  DEFINE_XSTORE(sh)
+  DEFINE_XSTORE(sw)
+  DEFINE_XSTORE(sd)
+
+  DEFINE_XAMO(amoadd_w)
+  DEFINE_XAMO(amoswap_w)
+  DEFINE_XAMO(amoand_w)
+  DEFINE_XAMO(amoor_w)
+  DEFINE_XAMO(amoxor_w)
+  DEFINE_XAMO(amomin_w)
+  DEFINE_XAMO(amomax_w)
+  DEFINE_XAMO(amominu_w)
+  DEFINE_XAMO(amomaxu_w)
+  DEFINE_XAMO(amoadd_d)
+  DEFINE_XAMO(amoswap_d)
+  DEFINE_XAMO(amoand_d)
+  DEFINE_XAMO(amoor_d)
+  DEFINE_XAMO(amoxor_d)
+  DEFINE_XAMO(amomin_d)
+  DEFINE_XAMO(amomax_d)
+  DEFINE_XAMO(amominu_d)
+  DEFINE_XAMO(amomaxu_d)
+
+  DEFINE_XAMO_LR(lr_w)
+  DEFINE_XAMO(sc_w)
+  DEFINE_XAMO_LR(lr_d)
+  DEFINE_XAMO(sc_d)
+
+  DEFINE_FLOAD(flw)
+  DEFINE_FLOAD(fld)
+  DEFINE_FLOAD(flq)
+
+  DEFINE_FSTORE(fsw)
+  DEFINE_FSTORE(fsd)
+  DEFINE_FSTORE(fsq)
+
+  add_insn(new disasm_insn_t("j", match_jal, mask_jal | mask_rd, {&jump_target}));
+  add_insn(new disasm_insn_t("jal", match_jal | match_rd_ra, mask_jal | mask_rd, {&jump_target}));
+  add_insn(new disasm_insn_t("jal", match_jal, mask_jal, {&xrd, &jump_target}));
+
+  DEFINE_B1TYPE("beqz", beq);
+  DEFINE_B1TYPE("bnez", bne);
+  DEFINE_B1TYPE("bltz", blt);
+  DEFINE_B1TYPE("bgez", bge);
+  DEFINE_BTYPE(beq)
+  DEFINE_BTYPE(bne)
+  DEFINE_BTYPE(blt)
+  DEFINE_BTYPE(bge)
+  DEFINE_BTYPE(bltu)
+  DEFINE_BTYPE(bgeu)
+
+  DEFINE_LTYPE(lui);
+  DEFINE_LTYPE(auipc);
+
+  add_insn(new disasm_insn_t("ret", match_jalr | match_rs1_ra, mask_jalr | mask_rd | mask_rs1 | mask_imm, {}));
+  DEFINE_I2TYPE("jr", jalr);
+  add_insn(new disasm_insn_t("jalr", match_jalr | match_rd_ra, mask_jalr | mask_rd | mask_imm, {&xrs1}));
+  DEFINE_ITYPE(jalr);
+
+  add_insn(new disasm_insn_t("nop", match_addi, mask_addi | mask_rd | mask_rs1 | mask_imm, {}));
+  add_insn(new disasm_insn_t(" - ", match_xor, mask_xor | mask_rd | mask_rs1 | mask_rs2, {})); // for machine-generated bubbles
+  DEFINE_I0TYPE("li", addi);
+  DEFINE_I1TYPE("mv", addi);
+  DEFINE_ITYPE(addi);
+  DEFINE_ITYPE(slti);
+  add_insn(new disasm_insn_t("seqz", match_sltiu | match_imm_1, mask_sltiu | mask_imm, {&xrd, &xrs1}));
+  DEFINE_ITYPE(sltiu);
+  add_insn(new disasm_insn_t("not", match_xori | mask_imm, mask_xori | mask_imm, {&xrd, &xrs1}));
+  DEFINE_ITYPE(xori);
+
+  DEFINE_ITYPE_SHIFT(slli);
+  DEFINE_ITYPE_SHIFT(srli);
+  DEFINE_ITYPE_SHIFT(srai);
+
+  DEFINE_ITYPE(ori);
+  DEFINE_ITYPE(andi);
+  DEFINE_I1TYPE("sext.w", addiw);
+  DEFINE_ITYPE(addiw);
+
+  DEFINE_ITYPE_SHIFT(slliw);
+  DEFINE_ITYPE_SHIFT(srliw);
+  DEFINE_ITYPE_SHIFT(sraiw);
+
+  DEFINE_RTYPE(add);
+  DEFINE_RTYPE(sub);
+  DEFINE_RTYPE(sll);
+  DEFINE_RTYPE(slt);
+  add_insn(new disasm_insn_t("snez", match_sltu, mask_sltu | mask_rs1, {&xrd, &xrs2}));
+  DEFINE_RTYPE(sltu);
+  DEFINE_RTYPE(xor);
+  DEFINE_RTYPE(srl);
+  DEFINE_RTYPE(sra);
+  DEFINE_RTYPE(or);
+  DEFINE_RTYPE(and);
+  DEFINE_RTYPE(mul);
+  DEFINE_RTYPE(mulh);
+  DEFINE_RTYPE(mulhu);
+  DEFINE_RTYPE(mulhsu);
+  DEFINE_RTYPE(div);
+  DEFINE_RTYPE(divu);
+  DEFINE_RTYPE(rem);
+  DEFINE_RTYPE(remu);
+  DEFINE_RTYPE(addw);
+  DEFINE_RTYPE(subw);
+  DEFINE_RTYPE(sllw);
+  DEFINE_RTYPE(srlw);
+  DEFINE_RTYPE(sraw);
+  DEFINE_RTYPE(mulw);
+  DEFINE_RTYPE(divw);
+  DEFINE_RTYPE(divuw);
+  DEFINE_RTYPE(remw);
+  DEFINE_RTYPE(remuw);
+
+  DEFINE_NOARG(ecall);
+  DEFINE_NOARG(ebreak);
+  DEFINE_NOARG(uret);
+  DEFINE_NOARG(sret);
+  DEFINE_NOARG(mret);
+  DEFINE_NOARG(dret);
+  DEFINE_NOARG(wfi);
+  DEFINE_NOARG(fence);
+  DEFINE_NOARG(fence_i);
+  DEFINE_SFENCE_TYPE(sfence_vma);
+
+  add_insn(new disasm_insn_t("csrr", match_csrrs, mask_csrrs | mask_rs1, {&xrd, &csr}));
+  add_insn(new disasm_insn_t("csrw", match_csrrw, mask_csrrw | mask_rd, {&csr, &xrs1}));
+  add_insn(new disasm_insn_t("csrs", match_csrrs, mask_csrrs | mask_rd, {&csr, &xrs1}));
+  add_insn(new disasm_insn_t("csrc", match_csrrc, mask_csrrc | mask_rd, {&csr, &xrs1}));
+  add_insn(new disasm_insn_t("csrwi", match_csrrwi, mask_csrrwi | mask_rd, {&csr, &zimm5}));
+  add_insn(new disasm_insn_t("csrsi", match_csrrsi, mask_csrrsi | mask_rd, {&csr, &zimm5}));
+  add_insn(new disasm_insn_t("csrci", match_csrrci, mask_csrrci | mask_rd, {&csr, &zimm5}));
+  add_insn(new disasm_insn_t("csrrw", match_csrrw, mask_csrrw, {&xrd, &csr, &xrs1}));
+  add_insn(new disasm_insn_t("csrrs", match_csrrs, mask_csrrs, {&xrd, &csr, &xrs1}));
+  add_insn(new disasm_insn_t("csrrc", match_csrrc, mask_csrrc, {&xrd, &csr, &xrs1}));
+  add_insn(new disasm_insn_t("csrrwi", match_csrrwi, mask_csrrwi, {&xrd, &csr, &zimm5}));
+  add_insn(new disasm_insn_t("csrrsi", match_csrrsi, mask_csrrsi, {&xrd, &csr, &zimm5}));
+  add_insn(new disasm_insn_t("csrrci", match_csrrci, mask_csrrci, {&xrd, &csr, &zimm5}));
+
+  DEFINE_FRTYPE(fadd_s);
+  DEFINE_FRTYPE(fsub_s);
+  DEFINE_FRTYPE(fmul_s);
+  DEFINE_FRTYPE(fdiv_s);
+  DEFINE_FR1TYPE(fsqrt_s);
+  DEFINE_FRTYPE(fmin_s);
+  DEFINE_FRTYPE(fmax_s);
+  DEFINE_FR3TYPE(fmadd_s);
+  DEFINE_FR3TYPE(fmsub_s);
+  DEFINE_FR3TYPE(fnmadd_s);
+  DEFINE_FR3TYPE(fnmsub_s);
+  DEFINE_FRTYPE(fsgnj_s);
+  DEFINE_FRTYPE(fsgnjn_s);
+  DEFINE_FRTYPE(fsgnjx_s);
+  DEFINE_FR1TYPE(fcvt_s_d);
+  DEFINE_FR1TYPE(fcvt_s_q);
+  DEFINE_XFTYPE(fcvt_s_l);
+  DEFINE_XFTYPE(fcvt_s_lu);
+  DEFINE_XFTYPE(fcvt_s_w);
+  DEFINE_XFTYPE(fcvt_s_wu);
+  DEFINE_XFTYPE(fcvt_s_wu);
+  DEFINE_XFTYPE(fmv_w_x);
+  DEFINE_FXTYPE(fcvt_l_s);
+  DEFINE_FXTYPE(fcvt_lu_s);
+  DEFINE_FXTYPE(fcvt_w_s);
+  DEFINE_FXTYPE(fcvt_wu_s);
+  DEFINE_FXTYPE(fclass_s);
+  DEFINE_FXTYPE(fmv_x_w);
+  DEFINE_FX2TYPE(feq_s);
+  DEFINE_FX2TYPE(flt_s);
+  DEFINE_FX2TYPE(fle_s);
+
+  DEFINE_FRTYPE(fadd_d);
+  DEFINE_FRTYPE(fsub_d);
+  DEFINE_FRTYPE(fmul_d);
+  DEFINE_FRTYPE(fdiv_d);
+  DEFINE_FR1TYPE(fsqrt_d);
+  DEFINE_FRTYPE(fmin_d);
+  DEFINE_FRTYPE(fmax_d);
+  DEFINE_FR3TYPE(fmadd_d);
+  DEFINE_FR3TYPE(fmsub_d);
+  DEFINE_FR3TYPE(fnmadd_d);
+  DEFINE_FR3TYPE(fnmsub_d);
+  DEFINE_FRTYPE(fsgnj_d);
+  DEFINE_FRTYPE(fsgnjn_d);
+  DEFINE_FRTYPE(fsgnjx_d);
+  DEFINE_FR1TYPE(fcvt_d_s);
+  DEFINE_FR1TYPE(fcvt_d_q);
+  DEFINE_XFTYPE(fcvt_d_l);
+  DEFINE_XFTYPE(fcvt_d_lu);
+  DEFINE_XFTYPE(fcvt_d_w);
+  DEFINE_XFTYPE(fcvt_d_wu);
+  DEFINE_XFTYPE(fcvt_d_wu);
+  DEFINE_XFTYPE(fmv_d_x);
+  DEFINE_FXTYPE(fcvt_l_d);
+  DEFINE_FXTYPE(fcvt_lu_d);
+  DEFINE_FXTYPE(fcvt_w_d);
+  DEFINE_FXTYPE(fcvt_wu_d);
+  DEFINE_FXTYPE(fclass_d);
+  DEFINE_FXTYPE(fmv_x_d);
+  DEFINE_FX2TYPE(feq_d);
+  DEFINE_FX2TYPE(flt_d);
+  DEFINE_FX2TYPE(fle_d);
+
+  DEFINE_FRTYPE(fadd_q);
+  DEFINE_FRTYPE(fsub_q);
+  DEFINE_FRTYPE(fmul_q);
+  DEFINE_FRTYPE(fdiv_q);
+  DEFINE_FR1TYPE(fsqrt_q);
+  DEFINE_FRTYPE(fmin_q);
+  DEFINE_FRTYPE(fmax_q);
+  DEFINE_FR3TYPE(fmadd_q);
+  DEFINE_FR3TYPE(fmsub_q);
+  DEFINE_FR3TYPE(fnmadd_q);
+  DEFINE_FR3TYPE(fnmsub_q);
+  DEFINE_FRTYPE(fsgnj_q);
+  DEFINE_FRTYPE(fsgnjn_q);
+  DEFINE_FRTYPE(fsgnjx_q);
+  DEFINE_FR1TYPE(fcvt_q_s);
+  DEFINE_FR1TYPE(fcvt_q_d);
+  DEFINE_XFTYPE(fcvt_q_l);
+  DEFINE_XFTYPE(fcvt_q_lu);
+  DEFINE_XFTYPE(fcvt_q_w);
+  DEFINE_XFTYPE(fcvt_q_wu);
+  DEFINE_XFTYPE(fcvt_q_wu);
+  DEFINE_XFTYPE(fmv_q_x);
+  DEFINE_FXTYPE(fcvt_l_q);
+  DEFINE_FXTYPE(fcvt_lu_q);
+  DEFINE_FXTYPE(fcvt_w_q);
+  DEFINE_FXTYPE(fcvt_wu_q);
+  DEFINE_FXTYPE(fclass_q);
+  DEFINE_FXTYPE(fmv_x_q);
+  DEFINE_FX2TYPE(feq_q);
+  DEFINE_FX2TYPE(flt_q);
+  DEFINE_FX2TYPE(fle_q);
+
+  DISASM_INSN("c.ebreak", c_add, mask_rd | mask_rvc_rs2, {});
+  add_insn(new disasm_insn_t("ret", match_c_jr | match_rd_ra, mask_c_jr | mask_rd | mask_rvc_imm, {}));
+  DISASM_INSN("c.jr", c_jr, mask_rvc_imm, {&rvc_rs1});
+  DISASM_INSN("c.jalr", c_jalr, mask_rvc_imm, {&rvc_rs1});
+  DISASM_INSN("c.nop", c_addi, mask_rd | mask_rvc_imm, {});
+  DISASM_INSN("c.addi16sp", c_addi16sp, mask_rd, {&rvc_sp, &rvc_addi16sp_imm});
+  DISASM_INSN("c.addi4spn", c_addi4spn, 0, {&rvc_rs2s, &rvc_sp, &rvc_addi4spn_imm});
+  DISASM_INSN("c.li", c_li, 0, {&xrd, &rvc_imm});
+  DISASM_INSN("c.lui", c_lui, 0, {&xrd, &rvc_uimm});
+  DISASM_INSN("c.addi", c_addi, 0, {&xrd, &rvc_imm});
+  DISASM_INSN("c.slli", c_slli, 0, {&rvc_rs1, &rvc_shamt});
+  DISASM_INSN("c.srli", c_srli, 0, {&rvc_rs1s, &rvc_shamt});
+  DISASM_INSN("c.srai", c_srai, 0, {&rvc_rs1s, &rvc_shamt});
+  DISASM_INSN("c.andi", c_andi, 0, {&rvc_rs1s, &rvc_imm});
+  DISASM_INSN("c.mv", c_mv, 0, {&xrd, &rvc_rs2});
+  DISASM_INSN("c.add", c_add, 0, {&xrd, &rvc_rs2});
+  DISASM_INSN("c.addw", c_addw, 0, {&rvc_rs1s, &rvc_rs2s});
+  DISASM_INSN("c.sub", c_sub, 0, {&rvc_rs1s, &rvc_rs2s});
+  DISASM_INSN("c.subw", c_subw, 0, {&rvc_rs1s, &rvc_rs2s});
+  DISASM_INSN("c.and", c_and, 0, {&rvc_rs1s, &rvc_rs2s});
+  DISASM_INSN("c.or", c_or, 0, {&rvc_rs1s, &rvc_rs2s});
+  DISASM_INSN("c.xor", c_xor, 0, {&rvc_rs1s, &rvc_rs2s});
+  DISASM_INSN("c.lwsp", c_lwsp, 0, {&xrd, &rvc_lwsp_address});
+  DISASM_INSN("c.fld", c_fld, 0, {&rvc_fp_rs2s, &rvc_ld_address});
+  DISASM_INSN("c.swsp", c_swsp, 0, {&rvc_rs2, &rvc_swsp_address});
+  DISASM_INSN("c.lw", c_lw, 0, {&rvc_rs2s, &rvc_lw_address});
+  DISASM_INSN("c.sw", c_sw, 0, {&rvc_rs2s, &rvc_lw_address});
+  DISASM_INSN("c.beqz", c_beqz, 0, {&rvc_rs1s, &rvc_branch_target});
+  DISASM_INSN("c.bnez", c_bnez, 0, {&rvc_rs1s, &rvc_branch_target});
+  DISASM_INSN("c.j", c_j, 0, {&rvc_jump_target});
+  DISASM_INSN("c.fldsp", c_fldsp, 0, {&rvc_fp_rs2s, &rvc_ldsp_address});
+  DISASM_INSN("c.fsd", c_fsd, 0, {&rvc_fp_rs2s, &rvc_ld_address});
+  DISASM_INSN("c.fsdsp", c_fsdsp, 0, {&rvc_fp_rs2s, &rvc_sdsp_address});
+
+  if (xlen == 32) {
+    DISASM_INSN("c.flw", c_flw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
+    DISASM_INSN("c.flwsp", c_flwsp, 0, {&frd, &rvc_lwsp_address});
+    DISASM_INSN("c.fsw", c_fsw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
+    DISASM_INSN("c.fswsp", c_fswsp, 0, {&rvc_fp_rs2, &rvc_swsp_address});
+    DISASM_INSN("c.jal", c_jal, 0, {&rvc_jump_target});
+  } else {
+    DISASM_INSN("c.ld", c_ld, 0, {&rvc_rs2s, &rvc_ld_address});
+    DISASM_INSN("c.ldsp", c_ldsp, 0, {&xrd, &rvc_ldsp_address});
+    DISASM_INSN("c.sd", c_sd, 0, {&rvc_rs2s, &rvc_ld_address});
+    DISASM_INSN("c.sdsp", c_sdsp, 0, {&rvc_rs2, &rvc_sdsp_address});
+    DISASM_INSN("c.addiw", c_addiw, 0, {&xrd, &rvc_imm});
+  }
+
+  // provide a default disassembly for all instructions as a fallback
+  #define DECLARE_INSN(code, match, mask) \
+   add_insn(new disasm_insn_t(#code " (args unknown)", match, mask, {}));
+  #include "encoding.h"
+  #undef DECLARE_INSN
+}
+
+const disasm_insn_t* disassembler_t::lookup(insn_t insn) const
+{
+  size_t idx = insn.bits() % HASH_SIZE;
+  for (size_t j = 0; j < chain[idx].size(); j++)
+    if(*chain[idx][j] == insn)
+      return chain[idx][j];
+
+  idx = HASH_SIZE;
+  for (size_t j = 0; j < chain[idx].size(); j++)
+    if(*chain[idx][j] == insn)
+      return chain[idx][j];
+
+  return NULL;
+}
+
+void disassembler_t::add_insn(disasm_insn_t* insn)
+{
+  size_t idx = HASH_SIZE;
+  if (insn->get_mask() % HASH_SIZE == HASH_SIZE - 1)
+    idx = insn->get_match() % HASH_SIZE;
+  chain[idx].push_back(insn);
+}
+
+disassembler_t::~disassembler_t()
+{
+  for (size_t i = 0; i < HASH_SIZE+1; i++)
+    for (size_t j = 0; j < chain[i].size(); j++)
+      delete chain[i][j];
+}
diff --git a/tb/riscv-isa-sim/spike_main/spike-dasm.cc b/tb/riscv-isa-sim/spike_main/spike-dasm.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1161825c2ec8d65c32c02f592b24ce19fd5c64c0
--- /dev/null
+++ b/tb/riscv-isa-sim/spike_main/spike-dasm.cc
@@ -0,0 +1,64 @@
+// See LICENSE for license details.
+
+// This little program finds occurrences of strings like
+//  DASM(ffabc013)
+// in its input, then replaces them with the disassembly
+// enclosed hexadecimal number, interpreted as a RISC-V
+// instruction.
+
+#include "disasm.h"
+#include "extension.h"
+#include <iostream>
+#include <string>
+#include <cstdint>
+#include <fesvr/option_parser.h>
+using namespace std;
+
+int main(int argc, char** argv)
+{
+  string s;
+  const char* isa = DEFAULT_ISA;
+
+  std::function<extension_t*()> extension;
+  option_parser_t parser;
+  parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);});
+  parser.option(0, "isa", 1, [&](const char* s){isa = s;});
+  parser.parse(argv);
+
+  processor_t p(isa, 0, 0);
+  if (extension)
+    p.register_extension(extension());
+
+  while (getline(cin, s))
+  {
+    for (size_t pos = 0; (pos = s.find("DASM(", pos)) != string::npos; )
+    {
+      size_t start = pos;
+
+      pos += strlen("DASM(");
+
+      if (s[pos] == '0' && (s[pos+1] == 'x' || s[pos+1] == 'X'))
+        pos += 2;
+
+      if (!isxdigit(s[pos]))
+        continue;
+
+      char* endp;
+      int64_t bits = strtoull(&s[pos], &endp, 16);
+      if (*endp != ')')
+        continue;
+
+      size_t nbits = 4 * (endp - &s[pos]);
+      if (nbits < 64)
+        bits = bits << (64 - nbits) >> (64 - nbits);
+
+      string dis = p.get_disassembler()->disassemble(bits);
+      s = s.substr(0, start) + dis + s.substr(endp - &s[0] + 1);
+      pos = start + dis.length();
+    }
+
+    cout << s << '\n';
+  }
+
+  return 0;
+}
diff --git a/tb/riscv-isa-sim/spike_main/spike.cc b/tb/riscv-isa-sim/spike_main/spike.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3e5c7e6c60e27d575a3b56c150123423e00fd340
--- /dev/null
+++ b/tb/riscv-isa-sim/spike_main/spike.cc
@@ -0,0 +1,187 @@
+// See LICENSE for license details.
+
+#include "sim.h"
+#include "mmu.h"
+#include "remote_bitbang.h"
+#include "cachesim.h"
+#include "extension.h"
+#include <dlfcn.h>
+#include <fesvr/option_parser.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+#include <string>
+#include <memory>
+
+static void help()
+{
+  fprintf(stderr, "usage: spike [host options] <target program> [target options]\n");
+  fprintf(stderr, "Host Options:\n");
+  fprintf(stderr, "  -p<n>                 Simulate <n> processors [default 1]\n");
+  fprintf(stderr, "  -m<n>                 Provide <n> MiB of target memory [default 2048]\n");
+  fprintf(stderr, "  -m<a:m,b:n,...>       Provide memory regions of size m and n bytes\n");
+  fprintf(stderr, "                          at base addresses a and b (with 4 KiB alignment)\n");
+  fprintf(stderr, "  -d                    Interactive debug mode\n");
+  fprintf(stderr, "  -g                    Track histogram of PCs\n");
+  fprintf(stderr, "  -l                    Generate a log of execution\n");
+  fprintf(stderr, "  -h                    Print this help message\n");
+  fprintf(stderr, "  -H                    Start halted, allowing a debugger to connect\n");
+  fprintf(stderr, "  --isa=<name>          RISC-V ISA string [default %s]\n", DEFAULT_ISA);
+  fprintf(stderr, "  --pc=<address>        Override ELF entry point\n");
+  fprintf(stderr, "  --hartids=<a,b,...>   Explicitly specify hartids, default is 0,1,...\n");
+  fprintf(stderr, "  --ic=<S>:<W>:<B>      Instantiate a cache model with S sets,\n");
+  fprintf(stderr, "  --dc=<S>:<W>:<B>        W ways, and B-byte blocks (with S and\n");
+  fprintf(stderr, "  --l2=<S>:<W>:<B>        B both powers of 2).\n");
+  fprintf(stderr, "  --log-cache-miss      Generate a log of cache miss\n");
+  fprintf(stderr, "  --extension=<name>    Specify RoCC Extension\n");
+  fprintf(stderr, "  --extlib=<name>       Shared library to load\n");
+  fprintf(stderr, "  --rbb-port=<port>     Listen on <port> for remote bitbang connection\n");
+  fprintf(stderr, "  --dump-dts            Print device tree string and exit\n");
+  fprintf(stderr, "  --disable-dtb         Don't write the device tree blob into memory\n");
+  fprintf(stderr, "  --progsize=<words>    Progsize for the debug module [default 2]\n");
+  fprintf(stderr, "  --debug-sba=<bits>    Debug bus master supports up to "
+      "<bits> wide accesses [default 0]\n");
+  fprintf(stderr, "  --debug-auth          Debug module requires debugger to authenticate\n");
+  exit(1);
+}
+
+static std::vector<std::pair<reg_t, mem_t*>> make_mems(const char* arg)
+{
+  // handle legacy mem argument
+  char* p;
+  auto mb = strtoull(arg, &p, 0);
+  if (*p == 0) {
+    reg_t size = reg_t(mb) << 20;
+    if (size != (size_t)size)
+      throw std::runtime_error("Size would overflow size_t");
+    return std::vector<std::pair<reg_t, mem_t*>>(1, std::make_pair(reg_t(DRAM_BASE), new mem_t(size)));
+  }
+
+  // handle base/size tuples
+  std::vector<std::pair<reg_t, mem_t*>> res;
+  while (true) {
+    auto base = strtoull(arg, &p, 0);
+    if (!*p || *p != ':')
+      help();
+    auto size = strtoull(p + 1, &p, 0);
+    if ((size | base) % PGSIZE != 0)
+      help();
+    res.push_back(std::make_pair(reg_t(base), new mem_t(size)));
+    if (!*p)
+      break;
+    if (*p != ',')
+      help();
+    arg = p + 1;
+  }
+  return res;
+}
+
+int main(int argc, char** argv)
+{
+  bool debug = false;
+  bool halted = false;
+  bool histogram = false;
+  bool log = false;
+  bool dump_dts = false;
+  bool dtb_enabled = true;
+  size_t nprocs = 1;
+  reg_t start_pc = reg_t(-1);
+  std::vector<std::pair<reg_t, mem_t*>> mems;
+  std::unique_ptr<icache_sim_t> ic;
+  std::unique_ptr<dcache_sim_t> dc;
+  std::unique_ptr<cache_sim_t> l2;
+  bool log_cache = false;
+  std::function<extension_t*()> extension;
+  const char* isa = DEFAULT_ISA;
+  uint16_t rbb_port = 0;
+  bool use_rbb = false;
+  unsigned progsize = 2;
+  unsigned max_bus_master_bits = 0;
+  bool require_authentication = false;
+  std::vector<int> hartids;
+
+  auto const hartids_parser = [&](const char *s) {
+    std::string const str(s);
+    std::stringstream stream(str);
+
+    int n;
+    while (stream >> n)
+    {
+      hartids.push_back(n);
+      if (stream.peek() == ',') stream.ignore();
+    }
+  };
+
+  option_parser_t parser;
+  parser.help(&help);
+  parser.option('h', 0, 0, [&](const char* s){help();});
+  parser.option('d', 0, 0, [&](const char* s){debug = true;});
+  parser.option('g', 0, 0, [&](const char* s){histogram = true;});
+  parser.option('l', 0, 0, [&](const char* s){log = true;});
+  parser.option('p', 0, 1, [&](const char* s){nprocs = atoi(s);});
+  parser.option('m', 0, 1, [&](const char* s){mems = make_mems(s);});
+  // I wanted to use --halted, but for some reason that doesn't work.
+  parser.option('H', 0, 0, [&](const char* s){halted = true;});
+  parser.option(0, "rbb-port", 1, [&](const char* s){use_rbb = true; rbb_port = atoi(s);});
+  parser.option(0, "pc", 1, [&](const char* s){start_pc = strtoull(s, 0, 0);});
+  parser.option(0, "hartids", 1, hartids_parser);
+  parser.option(0, "ic", 1, [&](const char* s){ic.reset(new icache_sim_t(s));});
+  parser.option(0, "dc", 1, [&](const char* s){dc.reset(new dcache_sim_t(s));});
+  parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));});
+  parser.option(0, "log-cache-miss", 0, [&](const char* s){log_cache = true;});
+  parser.option(0, "isa", 1, [&](const char* s){isa = s;});
+  parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);});
+  parser.option(0, "dump-dts", 0, [&](const char *s){dump_dts = true;});
+  parser.option(0, "disable-dtb", 0, [&](const char *s){dtb_enabled = false;});
+  parser.option(0, "extlib", 1, [&](const char *s){
+    void *lib = dlopen(s, RTLD_NOW | RTLD_GLOBAL);
+    if (lib == NULL) {
+      fprintf(stderr, "Unable to load extlib '%s': %s\n", s, dlerror());
+      exit(-1);
+    }
+  });
+  parser.option(0, "progsize", 1, [&](const char* s){progsize = atoi(s);});
+  parser.option(0, "debug-sba", 1,
+      [&](const char* s){max_bus_master_bits = atoi(s);});
+  parser.option(0, "debug-auth", 0,
+      [&](const char* s){require_authentication = true;});
+
+  auto argv1 = parser.parse(argv);
+  std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc);
+  if (mems.empty())
+    mems = make_mems("2048");
+
+  if (!*argv1)
+    help();
+
+  sim_t s(isa, nprocs, halted, start_pc, mems, htif_args, std::move(hartids),
+      progsize, max_bus_master_bits, require_authentication);
+  std::unique_ptr<remote_bitbang_t> remote_bitbang((remote_bitbang_t *) NULL);
+  std::unique_ptr<jtag_dtm_t> jtag_dtm(new jtag_dtm_t(&s.debug_module));
+  if (use_rbb) {
+    remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm)));
+    s.set_remote_bitbang(&(*remote_bitbang));
+  }
+  s.set_dtb_enabled(dtb_enabled);
+
+  if (dump_dts) {
+    printf("%s", s.get_dts());
+    return 0;
+  }
+
+  if (ic && l2) ic->set_miss_handler(&*l2);
+  if (dc && l2) dc->set_miss_handler(&*l2);
+  if (ic) ic->set_log(log_cache);
+  if (dc) dc->set_log(log_cache);
+  for (size_t i = 0; i < nprocs; i++)
+  {
+    if (ic) s.get_core(i)->get_mmu()->register_memtracer(&*ic);
+    if (dc) s.get_core(i)->get_mmu()->register_memtracer(&*dc);
+    if (extension) s.get_core(i)->register_extension(extension());
+  }
+
+  s.set_debug(debug);
+  s.set_log(log);
+  s.set_histogram(histogram);
+  return s.run();
+}
diff --git a/tb/riscv-isa-sim/spike_main/spike_main.ac b/tb/riscv-isa-sim/spike_main/spike_main.ac
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tb/riscv-isa-sim/spike_main/spike_main.mk.in b/tb/riscv-isa-sim/spike_main/spike_main.mk.in
new file mode 100644
index 0000000000000000000000000000000000000000..500446fa6ce6fed8ccef37196c9ea8847bb28a98
--- /dev/null
+++ b/tb/riscv-isa-sim/spike_main/spike_main.mk.in
@@ -0,0 +1,13 @@
+spike_main_subproject_deps = \
+	softfloat \
+	riscv \
+
+spike_main_install_prog_srcs = \
+	spike.cc \
+	spike-dasm.cc \
+	xspike.cc \
+	termios-xspike.cc \
+
+spike_main_hdrs = \
+
+spike_main_srcs = \
diff --git a/tb/riscv-isa-sim/spike_main/termios-xspike.cc b/tb/riscv-isa-sim/spike_main/termios-xspike.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e533933bf567a2309e6de9a0ed5cf64195c04c76
--- /dev/null
+++ b/tb/riscv-isa-sim/spike_main/termios-xspike.cc
@@ -0,0 +1,29 @@
+// See LICENSE for license details.
+
+// termios-xspike sets up a canonical terminal and blocks forever.
+// It allows us to send Ctrl-C etc. to the target machine.
+
+#include <unistd.h>
+#include <termios.h>
+#include <signal.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main()
+{
+  struct termios old_tios;
+  if (tcgetattr(0, &old_tios) < 0)
+    return -1;
+
+  signal(SIGTERM, [](int) { });
+
+  struct termios new_tios = old_tios;
+  new_tios.c_lflag &= ~(ICANON | ECHO | ISIG);
+  if (tcsetattr(0, TCSANOW, &new_tios) < 0)
+    return -1;
+
+  pause();
+
+  return tcsetattr(0, TCSANOW, &old_tios);
+}
diff --git a/tb/riscv-isa-sim/spike_main/xspike.cc b/tb/riscv-isa-sim/spike_main/xspike.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f8c8ca7e3e9b4cf31da88e606b908c01259bb476
--- /dev/null
+++ b/tb/riscv-isa-sim/spike_main/xspike.cc
@@ -0,0 +1,102 @@
+// See LICENSE for license details.
+
+// xspike forks an xterm for spike's target machine console,
+// preserving the current terminal for debugging.
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <cstdio>
+#include <climits>
+#include <cstring>
+#include <stdexcept>
+
+static pid_t fork_spike(int tty_fd, int argc, char** argv);
+static pid_t fork_xterm(int* tty_fd);
+
+int main(int argc, char** argv)
+{
+  int tty_fd, wait_status, ret = -1;
+  pid_t xterm, spike;
+
+  static bool signal_exit = false;
+  auto handle_signal = [](int) { signal_exit = true; };
+
+  if ((xterm = fork_xterm(&tty_fd)) < 0)
+  {
+    fprintf(stderr, "could not open xterm\n");
+    goto out;
+  }
+
+  signal(SIGINT, handle_signal);
+
+  if ((spike = fork_spike(tty_fd, argc, argv)) < 0)
+  {
+    fprintf(stderr, "could not open spike\n");
+    goto close_xterm;
+  }
+
+  while ((ret = waitpid(spike, &wait_status, 0)) < 0)
+    if (signal_exit)
+      break;
+
+  if (ret < 0) // signal_exit
+    kill(spike, SIGTERM);
+  else
+    ret = WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : -1;
+
+close_xterm:
+  kill(-xterm, SIGTERM);
+out:
+  return ret;
+}
+
+static pid_t fork_spike(int tty_fd, int argc, char** argv)
+{
+  pid_t pid = fork();
+  if (pid < 0)
+    return -1;
+
+  if (pid == 0)
+  {
+    if (dup2(tty_fd, STDIN_FILENO) < 0 || dup2(tty_fd, STDOUT_FILENO) < 0)
+      return -1;
+    execvp("spike", argv);
+    return -1;
+  }
+
+  return pid;
+}
+
+static pid_t fork_xterm(int* tty_fd)
+{
+  static const char cmd[] = "3>&1 xterm -title xspike -e sh -c 'tty 1>&3; termios-xspike'";
+
+  int fds[2];
+  if (pipe(fds) < 0)
+    return -1;
+
+  pid_t pid = fork();
+  if (pid < 0)
+    return -1;
+
+  if (pid == 0)
+  {
+    setpgid(0, 0);
+    if (dup2(fds[1], STDOUT_FILENO) < 0)
+      return -1;
+    execl("/bin/sh", "sh", "-c", cmd, NULL);
+    return -1;
+  }
+
+  char tty[PATH_MAX];
+  ssize_t ttylen = read(fds[0], tty, sizeof(tty));
+  if (ttylen <= 1 || tty[ttylen-1] != '\n')
+    return -1;
+  tty[ttylen-1] = '\0';
+  if ((*tty_fd = open(tty, O_RDWR)) < 0)
+    return -1;
+
+  return pid;
+}
diff --git a/tb/riscv-isa-sim/tests/ebreak.py b/tb/riscv-isa-sim/tests/ebreak.py
new file mode 100755
index 0000000000000000000000000000000000000000..dd7e65878b7a9f19dc0e9634d7bb24c385fc8de7
--- /dev/null
+++ b/tb/riscv-isa-sim/tests/ebreak.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import os
+import testlib
+import unittest
+import tempfile
+import time
+
+class EbreakTest(unittest.TestCase):
+    def setUp(self):
+        self.binary = testlib.compile("ebreak.s")
+
+    def test_noport(self):
+        """Make sure that we can run past ebreak when --gdb-port isn't used."""
+        spike = testlib.Spike(self.binary, with_gdb=False, timeout=10)
+        result = spike.wait()
+        self.assertEqual(result, 0)
+
+    def test_nogdb(self):
+        """Make sure that we can run past ebreak when gdb isn't attached."""
+        spike = testlib.Spike(self.binary, timeout=10)
+        result = spike.wait()
+        self.assertEqual(result, 0)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tb/riscv-isa-sim/tests/ebreak.s b/tb/riscv-isa-sim/tests/ebreak.s
new file mode 100644
index 0000000000000000000000000000000000000000..99f3e07ccdf831dbe22cc26eaaebee664babc661
--- /dev/null
+++ b/tb/riscv-isa-sim/tests/ebreak.s
@@ -0,0 +1,5 @@
+        .global main
+main:
+        li      a0, 0
+        ebreak
+        ret
diff --git a/tb/riscv-isa-sim/tests/testlib.py b/tb/riscv-isa-sim/tests/testlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..d5e8d795c9e5370a515979a4512551d0bace1243
--- /dev/null
+++ b/tb/riscv-isa-sim/tests/testlib.py
@@ -0,0 +1,116 @@
+import os.path
+import pexpect
+import subprocess
+import tempfile
+import testlib
+import unittest
+
+# Note that gdb comes with its own testsuite. I was unable to figure out how to
+# run that testsuite against the spike simulator.
+
+def find_file(path):
+    for directory in (os.getcwd(), os.path.dirname(testlib.__file__)):
+        fullpath = os.path.join(directory, path)
+        if os.path.exists(fullpath):
+            return fullpath
+    return None
+
+def compile(*args):
+    """Compile a single .c file into a binary."""
+    dst = os.path.splitext(args[0])[0]
+    cc = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gcc")
+    cmd = [cc, "-g", "-O", "-o", dst]
+    for arg in args:
+        found = find_file(arg)
+        if found:
+            cmd.append(found)
+        else:
+            cmd.append(arg)
+    cmd = " ".join(cmd)
+    result = os.system(cmd)
+    assert result == 0, "%r failed" % cmd
+    return dst
+
+def unused_port():
+    # http://stackoverflow.com/questions/2838244/get-open-tcp-port-in-python/2838309#2838309
+    import socket
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.bind(("",0))
+    port = s.getsockname()[1]
+    s.close()
+    return port
+
+class Spike(object):
+    def __init__(self, binary, halted=False, with_gdb=True, timeout=None):
+        """Launch spike. Return tuple of its process and the port it's running on."""
+        cmd = []
+        if timeout:
+            cmd += ["timeout", str(timeout)]
+
+        cmd += [find_file("spike")]
+        if halted:
+            cmd.append('-H')
+        if with_gdb:
+            self.port = unused_port()
+            cmd += ['--gdb-port', str(self.port)]
+        cmd.append('pk')
+        if binary:
+            cmd.append(binary)
+        logfile = open("spike.log", "w")
+        self.process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=logfile,
+                stderr=logfile)
+
+    def __del__(self):
+        try:
+            self.process.kill()
+            self.process.wait()
+        except OSError:
+            pass
+
+    def wait(self, *args, **kwargs):
+        return self.process.wait(*args, **kwargs)
+
+class Gdb(object):
+    def __init__(self):
+        path = os.path.expandvars("$RISCV/bin/riscv64-unknown-elf-gdb")
+        self.child = pexpect.spawn(path)
+        self.child.logfile = file("gdb.log", "w")
+        self.wait()
+        self.command("set width 0")
+        self.command("set height 0")
+        # Force consistency.
+        self.command("set print entry-values no")
+
+    def wait(self):
+        """Wait for prompt."""
+        self.child.expect("\(gdb\)")
+
+    def command(self, command, timeout=-1):
+        self.child.sendline(command)
+        self.child.expect("\n", timeout=timeout)
+        self.child.expect("\(gdb\)", timeout=timeout)
+        return self.child.before.strip()
+
+    def c(self, wait=True):
+        if wait:
+            return self.command("c")
+        else:
+            self.child.sendline("c")
+            self.child.expect("Continuing")
+
+    def interrupt(self):
+        self.child.send("\003");
+        self.child.expect("\(gdb\)")
+
+    def x(self, address, size='w'):
+        output = self.command("x/%s %s" % (size, address))
+        value = int(output.split(':')[1].strip(), 0)
+        return value
+
+    def p(self, obj):
+        output = self.command("p %s" % obj)
+        value = int(output.split('=')[-1].strip())
+        return value
+
+    def stepi(self):
+        return self.command("stepi")